[
  {
    "path": ".copr/Makefile",
    "content": ".PHONY: deps srpm\n.DEFAULT_GOAL := srpm\n\nDOT_COPR := $(dir $(firstword $(MAKEFILE_LIST)))\nTOP_DIR := $(realpath $(DOT_COPR)/../)\n\nRPM_DIR := $(TOP_DIR)/rpm\noutdir ?= $(RPM_DIR)/SRPMS\n\nHAS_GIT := $(shell command -v git 2> /dev/null)\nifndef HAS_GIT\ndeps:\n\tdnf -y install git\nelse\ndeps:\nendif\n\nsrpm: deps\n\tgit config --global --add safe.directory $(TOP_DIR)\n\tgit config --global --add safe.directory $(TOP_DIR)/libbloom\n\tgit config --global --add safe.directory $(TOP_DIR)/libcork\n\tgit config --global --add safe.directory $(TOP_DIR)/libipset\n\t$(RPM_DIR)/genrpm.sh -o $(outdir)\n"
  },
  {
    "path": ".dockerignore",
    "content": "# General\n.dockerignore\n.git\n.gitmodules\n.gitignore\n.github\nAUTHORS\nChanges\nCOPYING\nINSTALL\nLICENSE\nREADME.md\n\n# Code formatting\n.uncrustify.cfg\ncode-format.bat\ncode-format.sh\n\n# CI & CD\n.travis.yml\ntests\n\n# OS-specific packaging, etc.\ndebian\nscripts/build_deb.sh\nrpm\ncompletions\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "custom: ['https://crowdfunding.lfx.linuxfoundation.org/projects/shadowsocks']\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\""
  },
  {
    "path": ".github/issue_template.md",
    "content": "Please answer these questions before submitting your issue. Thanks!\n\n(Please mention that if the issue you filed is solved, you may wish to close it by yourself. Thanks again.)\n\n(PS, you can remove 3 lines above, including this one, before post your issue.)\n\n### What version of shadowsocks-libev are you using?\n\n\n### What operating system are you using?\n\n\n### What did you do?\n\n\n### What did you expect to see?\n\n\n### What did you see instead?\n\n\n### What is your config in detail (with all sensitive info masked)?\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: build\n\non:\n  push:\n    branches: [master]\n  pull_request:\n    branches: [master]\n\njobs:\n  build:\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ubuntu-latest, macos-latest]\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          submodules: recursive\n\n      - name: Install dependencies (Linux)\n        if: runner.os == 'Linux'\n        run: |\n          sudo apt-get update\n          sudo apt-get install -y libpcre2-dev libmbedtls-dev libsodium-dev libev-dev libc-ares-dev\n\n      - name: Install dependencies (macOS)\n        if: runner.os == 'macOS'\n        run: brew install mbedtls@3 libsodium libev c-ares pcre2\n\n      - name: Build\n        run: |\n          mkdir -p build && cd build\n          cmake .. -DCMAKE_BUILD_TYPE=Release -DWITH_STATIC=OFF\n          make -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)\n\n      - name: Unit tests\n        run: |\n          cd build\n          ctest --output-on-failure\n\n      - name: ss-setup TUI tests\n        run: bash tests/test_ss_setup.sh\n\n      - name: Stress test\n        run: |\n          python3 tests/stress_test.py --bin build/shared/bin/ --size 10\n\n      - name: ss-redir transparent proxy test (QEMU)\n        if: runner.os == 'Linux'\n        run: |\n          sudo apt-get install -y qemu-system-x86\n          bash tests/test_redir_qemu.sh build/shared/bin/\n        timeout-minutes: 8\n\n      - name: Debian package build test\n        if: runner.os == 'Linux'\n        run: |\n          sudo apt-get install -y --no-install-recommends \\\n            build-essential debhelper dpkg-dev fakeroot asciidoc-base xmlto pkg-config\n          bash tests/test_deb_build.sh\n        timeout-minutes: 10\n"
  },
  {
    "path": ".gitignore",
    "content": "# Ignore files generated by autoconf\n/Makefile.in\n/aclocal.m4\n/auto/\n/config.h.in\n/configure\n/doc/Makefile.in\n/m4/libtool.m4\n/m4/ltoptions.m4\n/m4/ltsugar.m4\n/m4/ltversion.m4\n/m4/lt~obsolete.m4\n/src/Makefile.in\n/src/config.h\n\n# Ignore files generated by configure\nbuild/\n.deps/\n/Makefile\nsrc/Makefile\nlibev/Makefile\nlibudns/Makefile\nlibcork/Makefile\nlibipset/Makefile\ndoc/Makefile\nautom4te.cache/\n/config.h\nconfig.log\nconfig.status\nlibtool\npid\nsrc/ss-*\n!src/ss-nat\nstamp-h1\n.libs\n.pc\ndebian/shadowsocks-libev/\ndebian/patches/\ndebian/files\ndebian/shadowsocks-libev.substvars\ndebian/*.debhelper*\n.dirstamp\nshadowsocks-libev.pc\ndebian/libshadowsocks-libev*.symbols\nlibsodium/src/libsodium/include/sodium/version.h\nrpm/SPECS/shadowsocks-libev.spec\nrpm/SRPMS/\nrpm/RPMS/\nrpm/BUILD/\nrpm/BUILDROOT/\n*.rpm\n*.deb\n\n# Ignore per-project vim config\n.vimrc\n\n# Ignore garbage of OS X\n*.DS_Store\n\n# Ignore vim cache\n*.swp\n\n# Documentation files\ndoc/*.1\ndoc/*.8\ndoc/*.gz\ndoc/*.xml\ndoc/*.html\n\n#\tDo not edit the following section\n# \tEdit Compile Debug Document Distribute\n*~\n*.bak\n*.bin\n*.dll\n*.exe\n*-ISO*.bdf\n*-JIS*.bdf\n*-KOI8*.bdf\n*.kld\n*.ko\n*.ko.cmd\n*.lai\n*.l[oa]\n*.[oa]\n*.obj\n*.patch\n*.so\n*.pcf.gz\n*.pdb\n*.tar\n*.tar.bz2\n*.tar.gz\n*.tgz\n*.snap\n#\n\n# Visual Studio Code\n.vscode/*\n.devcontainer/*\n\n# CMake objection\nobj-*\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"libcork\"]\n\tpath = libcork\n\turl = https://github.com/shadowsocks/libcork.git\n    ignore = dirty\n[submodule \"libipset\"]\n\tpath = libipset\n\turl = https://github.com/shadowsocks/ipset.git\n    ignore = dirty\n[submodule \"libbloom\"]\n\tpath = libbloom\n\turl = https://github.com/shadowsocks/libbloom.git\n    ignore = dirty\n"
  },
  {
    "path": ".travis.yml",
    "content": "sudo: required\nlanguage: c\ndist : trusty\ncompiler:\n    - clang\n    - gcc\nos:\n    - linux\n    - osx\nenv:\n    global:\n        - LIBSODIUM_VER=1.0.12\n        - MBEDTLS_VER=2.4.0\nbefore_install:\n    - |\n      if [[ \"$TRAVIS_OS_NAME\" == \"osx\" ]]; then\n          # All dependencies for macOS build. Some packages has been installed by travis so use reinstall.\n          brew reinstall cmake xmlto c-ares libev mbedtls libsodium asciidoc >> /dev/null 2>&1;\n      else\n          wget  https://github.com/jedisct1/libsodium/releases/download/$LIBSODIUM_VER/libsodium-$LIBSODIUM_VER.tar.gz;\n          tar xvf libsodium-$LIBSODIUM_VER.tar.gz;\n          pushd libsodium-$LIBSODIUM_VER;\n          ./configure --prefix=/usr && make;\n          sudo make install;\n          popd;\n          wget https://tls.mbed.org/download/mbedtls-$MBEDTLS_VER-gpl.tgz;\n          tar xvf mbedtls-$MBEDTLS_VER-gpl.tgz;\n          pushd mbedtls-$MBEDTLS_VER;\n          make SHARED=1;\n          sudo make install;\n          popd;\n          # Load cached docker images\n          if [[ -d $HOME/docker ]]; then\n              ls $HOME/docker/*.tar.gz | xargs -I {file} sh -c \"zcat {file} | docker load\";\n          fi\n      fi\naddons:\n    apt:\n        sources:\n            - george-edison55-precise-backports # cmake 3.2.3 / doxygen 1.8.3\n        packages:\n            - cmake\n            - libc-ares-dev\n            - libev-dev\n            - asciidoc\n            - xmlto\nscript:\n    - git submodule update --init --recursive\n    - mkdir -p build && cd build\n    - cmake ..\n    - make\n    - ctest --output-on-failure\nbranches:\n    only:\n        - master\nnotifications:\n    recipients:\n        - max.c.lv@gmail.com\n    email:\n        on_success: change\n        on_failure: always\n"
  },
  {
    "path": ".uncrustify.cfg",
    "content": "#\n# General options\n#\n\n# The type of line endings\nnewlines                                 = lf       # auto/lf/crlf/cr\n\n# The original size of tabs in the input\ninput_tab_size                           = 8        # number\n\n# The size of tabs in the output (only used if align_with_tabs=true)\noutput_tab_size                          = 8        # number\n\n# The ASCII value of the string escape char, usually 92 (\\) or 94 (^). (Pawn)\nstring_escape_char                       = 92       # number\n\n# Alternate string escape char for Pawn. Only works right before the quote char.\nstring_escape_char2                      = 0        # number\n\n#\n# Indenting\n#\n\n# The number of columns to indent per level.\n# Usually 2, 3, 4, or 8.\nindent_columns                           = 4        # number\n\n# The continuation indent. If non-zero, this overrides the indent of '(' and '=' continuation indents.\n# For FreeBSD, this is set to 4.\nindent_continue                          = 0        # number\n\n# How to use tabs when indenting code\n# 0=spaces only\n# 1=indent with tabs to brace level, align with spaces\n# 2=indent and align with tabs, using spaces when not on a tabstop\nindent_with_tabs                         = 0        # number\n\n# Comments that are not a brace level are indented with tabs on a tabstop.\n# Requires indent_with_tabs=2. If false, will use spaces.\nindent_cmt_with_tabs                     = false    # false/true\n\n# Whether to indent strings broken by '\\' so that they line up\nindent_align_string                      = true     # false/true\n\n# The number of spaces to indent multi-line XML strings.\n# Requires indent_align_string=True\nindent_xml_string                        = 0        # number\n\n# Spaces to indent '{' from level\nindent_brace                             = 0        # number\n\n# Whether braces are indented to the body level\nindent_braces                            = false    # false/true\n\n# Disabled indenting function braces if indent_braces is true\nindent_braces_no_func                    = false    # false/true\n\n# Disabled indenting class braces if indent_braces is true\nindent_braces_no_class                   = false    # false/true\n\n# Disabled indenting struct braces if indent_braces is true\nindent_braces_no_struct                  = false    # false/true\n\n# Indent based on the size of the brace parent, i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc.\nindent_brace_parent                      = false    # false/true\n\n# Whether the 'namespace' body is indented\nindent_namespace                         = false    # false/true\n\n# The number of spaces to indent a namespace block\nindent_namespace_level                   = 0        # number\n\n# If the body of the namespace is longer than this number, it won't be indented.\n# Requires indent_namespace=true. Default=0 (no limit)\nindent_namespace_limit                   = 0        # number\n\n# Whether the 'extern \"C\"' body is indented\nindent_extern                            = false    # false/true\n\n# Whether the 'class' body is indented\nindent_class                             = false    # false/true\n\n# Whether to indent the stuff after a leading class colon\nindent_class_colon                       = false    # false/true\n\n# False=treat 'else\\nif' as 'else if' for indenting purposes\n# True=indent the 'if' one level\nindent_else_if                           = false    # false/true\n\n# Amount to indent variable declarations after a open brace. neg=relative, pos=absolute\nindent_var_def_blk                       = 0        # number\n\n# Indent continued variable declarations instead of aligning.\nindent_var_def_cont                      = false    # false/true\n\n# True:  indent continued function call parameters one indent level\n# False: align parameters under the open paren\nindent_func_call_param                   = false    # false/true\n\n# Same as indent_func_call_param, but for function defs\nindent_func_def_param                    = false    # false/true\n\n# Same as indent_func_call_param, but for function protos\nindent_func_proto_param                  = false    # false/true\n\n# Same as indent_func_call_param, but for class declarations\nindent_func_class_param                  = false    # false/true\n\n# Same as indent_func_call_param, but for class variable constructors\nindent_func_ctor_var_param               = false    # false/true\n\n# Same as indent_func_call_param, but for templates\nindent_template_param                    = false    # false/true\n\n# Double the indent for indent_func_xxx_param options\nindent_func_param_double                 = false    # false/true\n\n# Indentation column for standalone 'const' function decl/proto qualifier\nindent_func_const                        = 0        # number\n\n# Indentation column for standalone 'throw' function decl/proto qualifier\nindent_func_throw                        = 0        # number\n\n# The number of spaces to indent a continued '->' or '.'\n# Usually set to 0, 1, or indent_columns.\nindent_member                            = 0        # number\n\n# Spaces to indent single line ('//') comments on lines before code\nindent_sing_line_comments                = 0        # number\n\n# If set, will indent trailing single line ('//') comments relative\n# to the code instead of trying to keep the same absolute column\nindent_relative_single_line_comments     = false    # false/true\n\n# Spaces to indent 'case' from 'switch'\n# Usually 0 or indent_columns.\nindent_switch_case                       = 0        # number\n\n# Spaces to shift the 'case' line, without affecting any other lines\n# Usually 0.\nindent_case_shift                        = 0        # number\n\n# Spaces to indent '{' from 'case'.\n# By default, the brace will appear under the 'c' in case.\n# Usually set to 0 or indent_columns.\nindent_case_brace                        = 0        # number\n\n# Whether to indent comments found in first column\nindent_col1_comment                      = false    # false/true\n\n# How to indent goto labels\n#  >0 : absolute column where 1 is the leftmost column\n#  <=0 : subtract from brace indent\nindent_label                             = 1        # number\n\n# Same as indent_label, but for access specifiers that are followed by a colon\nindent_access_spec                       = 1        # number\n\n# Indent the code after an access specifier by one level.\n# If set, this option forces 'indent_access_spec=0'\nindent_access_spec_body                  = false    # false/true\n\n# If an open paren is followed by a newline, indent the next line so that it lines up after the open paren (not recommended)\nindent_paren_nl                          = false    # false/true\n\n# Controls the indent of a close paren after a newline.\n# 0: Indent to body level\n# 1: Align under the open paren\n# 2: Indent to the brace level\nindent_paren_close                       = 0        # number\n\n# Controls the indent of a comma when inside a paren.If TRUE, aligns under the open paren\nindent_comma_paren                       = false    # false/true\n\n# Controls the indent of a BOOL operator when inside a paren.If TRUE, aligns under the open paren\nindent_bool_paren                        = false    # false/true\n\n# If 'indent_bool_paren' is true, controls the indent of the first expression. If TRUE, aligns the first expression to the following ones\nindent_first_bool_expr                   = false    # false/true\n\n# If an open square is followed by a newline, indent the next line so that it lines up after the open square (not recommended)\nindent_square_nl                         = false    # false/true\n\n# Don't change the relative indent of ESQL/C 'EXEC SQL' bodies\nindent_preserve_sql                      = false    # false/true\n\n# Align continued statements at the '='. Default=True\n# If FALSE or the '=' is followed by a newline, the next line is indent one tab.\nindent_align_assign                      = true     # false/true\n\n#\n# Spacing options\n#\n\n# Add or remove space around arithmetic operator '+', '-', '/', '*', etc\nsp_arith                                 = force    # ignore/add/remove/force\n\n# Add or remove space around assignment operator '=', '+=', etc\nsp_assign                                = force    # ignore/add/remove/force\n\n# Add or remove space around assignment operator '=' in a prototype\nsp_assign_default                        = ignore   # ignore/add/remove/force\n\n# Add or remove space before assignment operator '=', '+=', etc. Overrides sp_assign.\nsp_before_assign                         = ignore   # ignore/add/remove/force\n\n# Add or remove space after assignment operator '=', '+=', etc. Overrides sp_assign.\nsp_after_assign                          = ignore   # ignore/add/remove/force\n\n# Add or remove space around assignment '=' in enum\nsp_enum_assign                           = force    # ignore/add/remove/force\n\n# Add or remove space before assignment '=' in enum. Overrides sp_enum_assign.\nsp_enum_before_assign                    = ignore   # ignore/add/remove/force\n\n# Add or remove space after assignment '=' in enum. Overrides sp_enum_assign.\nsp_enum_after_assign                     = ignore   # ignore/add/remove/force\n\n# Add or remove space around preprocessor '##' concatenation operator. Default=Add\nsp_pp_concat                             = add      # ignore/add/remove/force\n\n# Add or remove space after preprocessor '#' stringify operator. Also affects the '#@' charizing operator. Default=Add\nsp_pp_stringify                          = add      # ignore/add/remove/force\n\n# Add or remove space around boolean operators '&&' and '||'\nsp_bool                                  = force    # ignore/add/remove/force\n\n# Add or remove space around compare operator '<', '>', '==', etc\nsp_compare                               = force    # ignore/add/remove/force\n\n# Add or remove space inside '(' and ')'\nsp_inside_paren                          = remove   # ignore/add/remove/force\n\n# Add or remove space between nested parens\nsp_paren_paren                           = remove   # ignore/add/remove/force\n\n# Whether to balance spaces inside nested parens\nsp_balance_nested_parens                 = false    # false/true\n\n# Add or remove space between ')' and '{'\nsp_paren_brace                           = force    # ignore/add/remove/force\n\n# Add or remove space before pointer star '*'\nsp_before_ptr_star                       = add      # ignore/add/remove/force\n\n# Add or remove space before pointer star '*' that isn't followed by a variable name\n# If set to 'ignore', sp_before_ptr_star is used instead.\nsp_before_unnamed_ptr_star               = add      # ignore/add/remove/force\n\n# Add or remove space between pointer stars '*'\nsp_between_ptr_star                      = remove   # ignore/add/remove/force\n\n# Add or remove space after pointer star '*', if followed by a word.\nsp_after_ptr_star                        = remove   # ignore/add/remove/force\n\n# Add or remove space after a pointer star '*', if followed by a func proto/def.\nsp_after_ptr_star_func                   = remove   # ignore/add/remove/force\n\n# Add or remove space before a pointer star '*', if followed by a func proto/def.\nsp_before_ptr_star_func                  = ignore   # ignore/add/remove/force\n\n# Add or remove space before a reference sign '&'\nsp_before_byref                          = force    # ignore/add/remove/force\n\n# Add or remove space before a reference sign '&' that isn't followed by a variable name\n# If set to 'ignore', sp_before_byref is used instead.\nsp_before_unnamed_byref                  = force    # ignore/add/remove/force\n\n# Add or remove space after reference sign '&', if followed by a word.\nsp_after_byref                           = ignore   # ignore/add/remove/force\n\n# Add or remove space after a reference sign '&', if followed by a func proto/def.\nsp_after_byref_func                      = ignore   # ignore/add/remove/force\n\n# Add or remove space before a reference sign '&', if followed by a func proto/def.\nsp_before_byref_func                     = ignore   # ignore/add/remove/force\n\n# Add or remove space between type and word. Default=Force\nsp_after_type                            = force    # ignore/add/remove/force\n\n# Add or remove space in 'template <' vs 'template<'.\n# If set to ignore, sp_before_angle is used.\nsp_template_angle                        = ignore   # ignore/add/remove/force\n\n# Add or remove space before '<>'\nsp_before_angle                          = ignore   # ignore/add/remove/force\n\n# Add or remove space inside '<' and '>'\nsp_inside_angle                          = ignore   # ignore/add/remove/force\n\n# Add or remove space after '<>'\nsp_after_angle                           = ignore   # ignore/add/remove/force\n\n# Add or remove space between '<>' and '(' as found in 'new List<byte>();'\nsp_angle_paren                           = ignore   # ignore/add/remove/force\n\n# Add or remove space between '<>' and a word as in 'List<byte> m;'\nsp_angle_word                            = ignore   # ignore/add/remove/force\n\n# Add or remove space between '>' and '>' in '>>' (template stuff C++/C# only). Default=Add\nsp_angle_shift                           = add      # ignore/add/remove/force\n\n# Add or remove space before '(' of 'if', 'for', 'switch', and 'while'\nsp_before_sparen                         = force    # ignore/add/remove/force\n\n# Add or remove space inside if-condition '(' and ')'\nsp_inside_sparen                         = remove   # ignore/add/remove/force\n\n# Add or remove space before if-condition ')'. Overrides sp_inside_sparen.\nsp_inside_sparen_close                   = ignore   # ignore/add/remove/force\n\n# Add or remove space after ')' of 'if', 'for', 'switch', and 'while'\nsp_after_sparen                          = ignore   # ignore/add/remove/force\n\n# Add or remove space between ')' and '{' of 'if', 'for', 'switch', and 'while'\nsp_sparen_brace                          = force    # ignore/add/remove/force\n\n# Add or remove space between 'invariant' and '(' in the D language.\nsp_invariant_paren                       = ignore   # ignore/add/remove/force\n\n# Add or remove space after the ')' in 'invariant (C) c' in the D language.\nsp_after_invariant_paren                 = ignore   # ignore/add/remove/force\n\n# Add or remove space before empty statement ';' on 'if', 'for' and 'while'\nsp_special_semi                          = ignore   # ignore/add/remove/force\n\n# Add or remove space before ';'. Default=Remove\nsp_before_semi                           = remove   # ignore/add/remove/force\n\n# Add or remove space before ';' in non-empty 'for' statements\nsp_before_semi_for                       = ignore   # ignore/add/remove/force\n\n# Add or remove space before a semicolon of an empty part of a for statement.\nsp_before_semi_for_empty                 = ignore   # ignore/add/remove/force\n\n# Add or remove space after ';', except when followed by a comment. Default=Add\nsp_after_semi                            = force    # ignore/add/remove/force\n\n# Add or remove space after ';' in non-empty 'for' statements. Default=Force\nsp_after_semi_for                        = force    # ignore/add/remove/force\n\n# Add or remove space after the final semicolon of an empty part of a for statement: for ( ; ; <here> ).\nsp_after_semi_for_empty                  = remove   # ignore/add/remove/force\n\n# Add or remove space before '[' (except '[]')\nsp_before_square                         = remove   # ignore/add/remove/force\n\n# Add or remove space before '[]'\nsp_before_squares                        = ignore   # ignore/add/remove/force\n\n# Add or remove space inside '[' and ']'\nsp_inside_square                         = remove   # ignore/add/remove/force\n\n# Add or remove space after ','\nsp_after_comma                           = force    # ignore/add/remove/force\n\n# Add or remove space before ','\nsp_before_comma                          = remove   # ignore/add/remove/force\n\n# Add or remove space between an open paren and comma: '(,' vs '( ,'\nsp_paren_comma                           = force    # ignore/add/remove/force\n\n# Add or remove space before the variadic '...' when preceded by a non-punctuator\nsp_before_ellipsis                       = ignore   # ignore/add/remove/force\n\n# Add or remove space after class ':'\nsp_after_class_colon                     = ignore   # ignore/add/remove/force\n\n# Add or remove space before class ':'\nsp_before_class_colon                    = ignore   # ignore/add/remove/force\n\n# Add or remove space before case ':'. Default=Remove\nsp_before_case_colon                     = remove   # ignore/add/remove/force\n\n# Add or remove space between 'operator' and operator sign\nsp_after_operator                        = ignore   # ignore/add/remove/force\n\n# Add or remove space between the operator symbol and the open paren, as in 'operator ++('\nsp_after_operator_sym                    = ignore   # ignore/add/remove/force\n\n# Add or remove space after C/D cast, i.e. 'cast(int)a' vs 'cast(int) a' or '(int)a' vs '(int) a'\nsp_after_cast                            = remove      # ignore/add/remove/force\n\n# Add or remove spaces inside cast parens\nsp_inside_paren_cast                     = remove   # ignore/add/remove/force\n\n# Add or remove space between the type and open paren in a C++ cast, i.e. 'int(exp)' vs 'int (exp)'\nsp_cpp_cast_paren                        = ignore   # ignore/add/remove/force\n\n# Add or remove space between 'sizeof' and '('\nsp_sizeof_paren                          = remove   # ignore/add/remove/force\n\n# Add or remove space after the tag keyword (Pawn)\nsp_after_tag                             = ignore   # ignore/add/remove/force\n\n# Add or remove space inside enum '{' and '}'\nsp_inside_braces_enum                    = remove   # ignore/add/remove/force\n\n# Add or remove space inside struct/union '{' and '}'\nsp_inside_braces_struct                  = force    # ignore/add/remove/force\n\n# Add or remove space inside '{' and '}'\nsp_inside_braces                         = force    # ignore/add/remove/force\n\n# Add or remove space inside '{}'\nsp_inside_braces_empty                   = remove   # ignore/add/remove/force\n\n# Add or remove space between return type and function name\n# A minimum of 1 is forced except for pointer return types.\nsp_type_func                             = remove   # ignore/add/remove/force\n\n# Add or remove space between function name and '(' on function declaration\nsp_func_proto_paren                      = remove   # ignore/add/remove/force\n\n# Add or remove space between function name and '(' on function definition\nsp_func_def_paren                        = remove   # ignore/add/remove/force\n\n# Add or remove space inside empty function '()'\nsp_inside_fparens                        = remove   # ignore/add/remove/force\n\n# Add or remove space inside function '(' and ')'\nsp_inside_fparen                         = remove   # ignore/add/remove/force\n\n# Add or remove space between ']' and '(' when part of a function call.\nsp_square_fparen                         = ignore   # ignore/add/remove/force\n\n# Add or remove space between ')' and '{' of function\nsp_fparen_brace                          = ignore   # ignore/add/remove/force\n\n# Add or remove space between function name and '(' on function calls\nsp_func_call_paren                       = remove   # ignore/add/remove/force\n\n# Add or remove space between function name and '()' on function calls without parameters.\n# If set to 'ignore' (the default), sp_func_call_paren is used.\nsp_func_call_paren_empty                 = ignore   # ignore/add/remove/force\n\n# Add or remove space between the user function name and '(' on function calls\n# You need to set a keyword to be a user function, like this: 'set func_call_user _' in the config file.\nsp_func_call_user_paren                  = ignore   # ignore/add/remove/force\n\n# Add or remove space between a constructor/destructor and the open paren\nsp_func_class_paren                      = ignore   # ignore/add/remove/force\n\n# Add or remove space between 'return' and '('\nsp_return_paren                          = ignore   # ignore/add/remove/force\n\n# Add or remove space between '__attribute__' and '('\nsp_attribute_paren                       = remove   # ignore/add/remove/force\n\n# Add or remove space between 'defined' and '(' in '#if defined (FOO)'\nsp_defined_paren                         = ignore   # ignore/add/remove/force\n\n# Add or remove space between 'throw' and '(' in 'throw (something)'\nsp_throw_paren                           = ignore   # ignore/add/remove/force\n\n# Add or remove space between macro and value\nsp_macro                                 = ignore   # ignore/add/remove/force\n\n# Add or remove space between macro function ')' and value\nsp_macro_func                            = ignore   # ignore/add/remove/force\n\n# Add or remove space between 'else' and '{' if on the same line\nsp_else_brace                            = force    # ignore/add/remove/force\n\n# Add or remove space between '}' and 'else' if on the same line\nsp_brace_else                            = force    # ignore/add/remove/force\n\n# Add or remove space between '}' and the name of a typedef on the same line\nsp_brace_typedef                         = force    # ignore/add/remove/force\n\n# Add or remove space between 'catch' and '{' if on the same line\nsp_catch_brace                           = ignore   # ignore/add/remove/force\n\n# Add or remove space between '}' and 'catch' if on the same line\nsp_brace_catch                           = ignore   # ignore/add/remove/force\n\n# Add or remove space between 'finally' and '{' if on the same line\nsp_finally_brace                         = ignore   # ignore/add/remove/force\n\n# Add or remove space between '}' and 'finally' if on the same line\nsp_brace_finally                         = ignore   # ignore/add/remove/force\n\n# Add or remove space between 'try' and '{' if on the same line\nsp_try_brace                             = ignore   # ignore/add/remove/force\n\n# Add or remove space between get/set and '{' if on the same line\nsp_getset_brace                          = ignore   # ignore/add/remove/force\n\n# Add or remove space before the '::' operator\nsp_before_dc                             = ignore   # ignore/add/remove/force\n\n# Add or remove space after the '::' operator\nsp_after_dc                              = ignore   # ignore/add/remove/force\n\n# Add or remove around the D named array initializer ':' operator\nsp_d_array_colon                         = ignore   # ignore/add/remove/force\n\n# Add or remove space after the '!' (not) operator. Default=Remove\nsp_not                                   = remove   # ignore/add/remove/force\n\n# Add or remove space after the '~' (invert) operator. Default=Remove\nsp_inv                                   = remove   # ignore/add/remove/force\n\n# Add or remove space after the '&' (address-of) operator. Default=Remove\n# This does not affect the spacing after a '&' that is part of a type.\nsp_addr                                  = remove   # ignore/add/remove/force\n\n# Add or remove space around the '.' or '->' operators. Default=Remove\nsp_member                                = remove   # ignore/add/remove/force\n\n# Add or remove space after the '*' (dereference) operator. Default=Remove\n# This does not affect the spacing after a '*' that is part of a type.\nsp_deref                                 = remove   # ignore/add/remove/force\n\n# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. Default=Remove\nsp_sign                                  = remove   # ignore/add/remove/force\n\n# Add or remove space before or after '++' and '--', as in '(--x)' or 'y++;'. Default=Remove\nsp_incdec                                = remove   # ignore/add/remove/force\n\n# Add or remove space before a backslash-newline at the end of a line. Default=Add\nsp_before_nl_cont                        = add      # ignore/add/remove/force\n\n# Add or remove space after the scope '+' or '-', as in '-(void) foo;' or '+(int) bar;'\nsp_after_oc_scope                        = ignore   # ignore/add/remove/force\n\n# Add or remove space after the colon in message specs\n# '-(int) f:(int) x;' vs '-(int) f: (int) x;'\nsp_after_oc_colon                        = ignore   # ignore/add/remove/force\n\n# Add or remove space before the colon in message specs\n# '-(int) f: (int) x;' vs '-(int) f : (int) x;'\nsp_before_oc_colon                       = ignore   # ignore/add/remove/force\n\n# Add or remove space after the colon in message specs\n# '[object setValue:1];' vs '[object setValue: 1];'\nsp_after_send_oc_colon                   = ignore   # ignore/add/remove/force\n\n# Add or remove space before the colon in message specs\n# '[object setValue:1];' vs '[object setValue :1];'\nsp_before_send_oc_colon                  = ignore   # ignore/add/remove/force\n\n# Add or remove space after the (type) in message specs\n# '-(int)f: (int) x;' vs '-(int)f: (int)x;'\nsp_after_oc_type                         = ignore   # ignore/add/remove/force\n\n# Add or remove space after the first (type) in message specs\n# '-(int) f:(int)x;' vs '-(int)f:(int)x;'\nsp_after_oc_return_type                  = ignore   # ignore/add/remove/force\n\n# Add or remove space between '@selector' and '('\n# '@selector(msgName)' vs '@selector (msgName)'\n# Also applies to @protocol() constructs\nsp_after_oc_at_sel                       = ignore   # ignore/add/remove/force\n\n# Add or remove space between '@selector(x)' and the following word\n# '@selector(foo) a:' vs '@selector(foo)a:'\nsp_after_oc_at_sel_parens                = ignore   # ignore/add/remove/force\n\n# Add or remove space inside '@selector' parens\n# '@selector(foo)' vs '@selector( foo )'\n# Also applies to @protocol() constructs\nsp_inside_oc_at_sel_parens               = ignore   # ignore/add/remove/force\n\n# Add or remove space before a block pointer caret\n# '^int (int arg){...}' vs. ' ^int (int arg){...}'\nsp_before_oc_block_caret                 = ignore   # ignore/add/remove/force\n\n# Add or remove space after a block pointer caret\n# '^int (int arg){...}' vs. '^ int (int arg){...}'\nsp_after_oc_block_caret                  = ignore   # ignore/add/remove/force\n\n# Add or remove space around the ':' in 'b ? t : f'\nsp_cond_colon                            = force    # ignore/add/remove/force\n\n# Add or remove space around the '?' in 'b ? t : f'\nsp_cond_question                         = force    # ignore/add/remove/force\n\n# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make sense here.\nsp_case_label                            = ignore   # ignore/add/remove/force\n\n# Control the space around the D '..' operator.\nsp_range                                 = ignore   # ignore/add/remove/force\n\n# Control the space after the opening of a C++ comment '// A' vs '//A'\n# MPlayer devs note: we ignore the following setting because it breaks Doxygen comments\n#sp_cmt_cpp_start                         = ignore   # ignore/add/remove/force\nsp_cmt_cpp_start                         = add   # ignore/add/remove/force\n\n# Controls the spaces between #else or #endif and a trailing comment\nsp_endif_cmt                             = ignore   # ignore/add/remove/force\n\n#\n# Code alignment (not left column spaces/tabs)\n#\n\n# Whether to keep non-indenting tabs\nalign_keep_tabs                          = false    # false/true\n\n# Whether to use tabs for aligning\nalign_with_tabs                          = false    # false/true\n\n# Whether to bump out to the next tab when aligning\nalign_on_tabstop                         = false    # false/true\n\n# Whether to left-align numbers\nalign_number_left                        = true     # false/true\n\n# Align variable definitions in prototypes and functions\nalign_func_params                        = false    # false/true\n\n# Align parameters in single-line functions that have the same name.\n# The function names must already be aligned with each other.\nalign_same_func_call_params              = false    # false/true\n\n# The span for aligning variable definitions (0=don't align)\nalign_var_def_span                       = 0        # number\n\n# How to align the star in variable definitions.\n#  0=Part of the type     'void *   foo;'\n#  1=Part of the variable 'void     *foo;'\n#  2=Dangling             'void    *foo;'\nalign_var_def_star_style                 = 2        # number\n\n# How to align the '&' in variable definitions.\n#  0=Part of the type\n#  1=Part of the variable\n#  2=Dangling\nalign_var_def_amp_style                  = 0        # number\n\n# The threshold for aligning variable definitions (0=no limit)\nalign_var_def_thresh                     = 0        # number\n\n# The gap for aligning variable definitions\nalign_var_def_gap                        = 0        # number\n\n# Whether to align the colon in struct bit fields\nalign_var_def_colon                      = false    # false/true\n\n# Whether to align any attribute after the variable name\nalign_var_def_attribute                  = false    # false/true\n\n# Whether to align inline struct/enum/union variable definitions\nalign_var_def_inline                     = false    # false/true\n\n# The span for aligning on '=' in assignments (0=don't align)\nalign_assign_span                        = 1        # number\n\n# The threshold for aligning on '=' in assignments (0=no limit)\nalign_assign_thresh                      = 0        # number\n\n# The span for aligning on '=' in enums (0=don't align)\nalign_enum_equ_span                      = 1        # number\n\n# The threshold for aligning on '=' in enums (0=no limit)\nalign_enum_equ_thresh                    = 0        # number\n\n# The span for aligning struct/union (0=don't align)\nalign_var_struct_span                    = 0        # number\n\n# The threshold for aligning struct/union member definitions (0=no limit)\nalign_var_struct_thresh                  = 0        # number\n\n# The gap for aligning struct/union member definitions\nalign_var_struct_gap                     = 0        # number\n\n# The span for aligning struct initializer values (0=don't align)\nalign_struct_init_span                   = 1        # number\n\n# The minimum space between the type and the synonym of a typedef\nalign_typedef_gap                        = 0        # number\n\n# The span for aligning single-line typedefs (0=don't align)\nalign_typedef_span                       = 0        # number\n\n# How to align typedef'd functions with other typedefs\n# 0: Don't mix them at all\n# 1: align the open paren with the types\n# 2: align the function type name with the other type names\nalign_typedef_func                       = 0        # number\n\n# Controls the positioning of the '*' in typedefs. Just try it.\n# 0: Align on typedef type, ignore '*'\n# 1: The '*' is part of type name: typedef int  *pint;\n# 2: The '*' is part of the type, but dangling: typedef int *pint;\nalign_typedef_star_style                 = 0        # number\n\n# Controls the positioning of the '&' in typedefs. Just try it.\n# 0: Align on typedef type, ignore '&'\n# 1: The '&' is part of type name: typedef int  &pint;\n# 2: The '&' is part of the type, but dangling: typedef int &pint;\nalign_typedef_amp_style                  = 0        # number\n\n# The span for aligning comments that end lines (0=don't align)\nalign_right_cmt_span                     = 0        # number\n\n# If aligning comments, mix with comments after '}' and #endif with less than 3 spaces before the comment\nalign_right_cmt_mix                      = false    # false/true\n\n# If a trailing comment is more than this number of columns away from the text it follows,\n# it will qualify for being aligned. This has to be > 0 to do anything.\nalign_right_cmt_gap                      = 0        # number\n\n# Align trailing comment at or beyond column N; 'pulls in' comments as a bonus side effect (0=ignore)\nalign_right_cmt_at_col                   = 0        # number\n\n# The span for aligning function prototypes (0=don't align)\nalign_func_proto_span                    = 0        # number\n\n# Minimum gap between the return type and the function name.\nalign_func_proto_gap                     = 0        # number\n\n# Align function protos on the 'operator' keyword instead of what follows\nalign_on_operator                        = false    # false/true\n\n# Whether to mix aligning prototype and variable declarations.\n# If true, align_var_def_XXX options are used instead of align_func_proto_XXX options.\nalign_mix_var_proto                      = false    # false/true\n\n# Align single-line functions with function prototypes, uses align_func_proto_span\nalign_single_line_func                   = false    # false/true\n\n# Aligning the open brace of single-line functions.\n# Requires align_single_line_func=true, uses align_func_proto_span\nalign_single_line_brace                  = false    # false/true\n\n# Gap for align_single_line_brace.\nalign_single_line_brace_gap              = 0        # number\n\n# The span for aligning ObjC msg spec (0=don't align)\nalign_oc_msg_spec_span                   = 0        # number\n\n# Whether to align macros wrapped with a backslash and a newline.\n# This will not work right if the macro contains a multi-line comment.\nalign_nl_cont                            = false    # false/true\n\n# The minimum space between label and value of a preprocessor define\nalign_pp_define_gap                      = 0        # number\n\n# The span for aligning on '#define' bodies (0=don't align)\nalign_pp_define_span                     = 0        # number\n\n# Align lines that start with '<<' with previous '<<'. Default=true\nalign_left_shift                         = true     # false/true\n\n# Span for aligning parameters in an Obj-C message call on the ':' (0=don't align)\nalign_oc_msg_colon_span                  = 0        # number\n\n# Aligning parameters in an Obj-C '+' or '-' declaration on the ':'\nalign_oc_decl_colon                      = false    # false/true\n\n#\n# Newline adding and removing options\n#\n\n# Whether to collapse empty blocks between '{' and '}'\nnl_collapse_empty_body                   = false    # false/true\n\n# Don't split one-line braced assignments - 'foo_t f = { 1, 2 };'\nnl_assign_leave_one_liners               = false    # false/true\n\n# Don't split one-line braced statements inside a class xx { } body\nnl_class_leave_one_liners                = false    # false/true\n\n# Don't split one-line enums: 'enum foo { BAR = 15 };'\nnl_enum_leave_one_liners                 = false    # false/true\n\n# Don't split one-line get or set functions\nnl_getset_leave_one_liners               = false    # false/true\n\n# Don't split one-line function definitions - 'int foo() { return 0; }'\nnl_func_leave_one_liners                 = false    # false/true\n\n# Don't split one-line if/else statements - 'if(a) b++;'\nnl_if_leave_one_liners                   = false    # false/true\n\n# Add or remove newlines at the start of the file\nnl_start_of_file                         = remove   # ignore/add/remove/force\n\n# The number of newlines at the start of the file (only used if nl_start_of_file is 'add' or 'force'\nnl_start_of_file_min                     = 0        # number\n\n# Add or remove newline at the end of the file\nnl_end_of_file                           = force    # ignore/add/remove/force\n\n# The number of newlines at the end of the file (only used if nl_end_of_file is 'add' or 'force')\nnl_end_of_file_min                       = 1        # number\n\n# Add or remove newline between '=' and '{'\nnl_assign_brace                          = remove   # ignore/add/remove/force\n\n# Add or remove newline between '=' and '[' (D only)\nnl_assign_square                         = ignore   # ignore/add/remove/force\n\n# Add or remove newline after '= [' (D only). Will also affect the newline before the ']'\nnl_after_square_assign                   = ignore   # ignore/add/remove/force\n\n# The number of blank lines after a block of variable definitions\nnl_func_var_def_blk                      = 0        # number\n\n# Add or remove newline between a function call's ')' and '{', as in:\n# list_for_each(item, &list) { }\nnl_fcall_brace                           = ignore   # ignore/add/remove/force\n\n# Add or remove newline between 'enum' and '{'\nnl_enum_brace                            = remove   # ignore/add/remove/force\n\n# Add or remove newline between 'struct and '{'\nnl_struct_brace                          = remove   # ignore/add/remove/force\n\n# Add or remove newline between 'union' and '{'\nnl_union_brace                           = remove   # ignore/add/remove/force\n\n# Add or remove newline between 'if' and '{'\nnl_if_brace                              = remove   # ignore/add/remove/force\n\n# Add or remove newline between '}' and 'else'\nnl_brace_else                            = remove   # ignore/add/remove/force\n\n# Add or remove newline between 'else if' and '{'\n# If set to ignore, nl_if_brace is used instead\nnl_elseif_brace                          = ignore   # ignore/add/remove/force\n\n# Add or remove newline between 'else' and '{'\nnl_else_brace                            = remove   # ignore/add/remove/force\n\n# Add or remove newline between 'else' and 'if'\nnl_else_if                               = remove   # ignore/add/remove/force\n\n# Add or remove newline between '}' and 'finally'\nnl_brace_finally                         = ignore   # ignore/add/remove/force\n\n# Add or remove newline between 'finally' and '{'\nnl_finally_brace                         = ignore   # ignore/add/remove/force\n\n# Add or remove newline between 'try' and '{'\nnl_try_brace                             = ignore   # ignore/add/remove/force\n\n# Add or remove newline between get/set and '{'\nnl_getset_brace                          = ignore   # ignore/add/remove/force\n\n# Add or remove newline between 'for' and '{'\nnl_for_brace                             = remove   # ignore/add/remove/force\n\n# Add or remove newline between 'catch' and '{'\nnl_catch_brace                           = ignore   # ignore/add/remove/force\n\n# Add or remove newline between '}' and 'catch'\nnl_brace_catch                           = ignore   # ignore/add/remove/force\n\n# Add or remove newline between 'while' and '{'\nnl_while_brace                           = remove   # ignore/add/remove/force\n\n# Add or remove newline between 'using' and '{'\nnl_using_brace                           = ignore   # ignore/add/remove/force\n\n# Add or remove newline between two open or close braces.\n# Due to general newline/brace handling, REMOVE may not work.\nnl_brace_brace                           = ignore   # ignore/add/remove/force\n\n# Add or remove newline between 'do' and '{'\nnl_do_brace                              = remove   # ignore/add/remove/force\n\n# Add or remove newline between '}' and 'while' of 'do' statement\nnl_brace_while                           = remove   # ignore/add/remove/force\n\n# Add or remove newline between 'switch' and '{'\nnl_switch_brace                          = remove   # ignore/add/remove/force\n\n# Add a newline between ')' and '{' if the ')' is on a different line than the if/for/etc.\n# Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch, and nl_catch_brace.\nnl_multi_line_cond                       = false    # false/true\n\n# Force a newline in a define after the macro name for multi-line defines.\nnl_multi_line_define                     = false    # false/true\n\n# Whether to put a newline before 'case' statement\nnl_before_case                           = false    # false/true\n\n# Add or remove newline between ')' and 'throw'\nnl_before_throw                          = ignore   # ignore/add/remove/force\n\n# Whether to put a newline after 'case' statement\nnl_after_case                            = true     # false/true\n\n# Newline between namespace and {\nnl_namespace_brace                       = ignore   # ignore/add/remove/force\n\n# Add or remove newline between 'template<>' and whatever follows.\nnl_template_class                        = ignore   # ignore/add/remove/force\n\n# Add or remove newline between 'class' and '{'\nnl_class_brace                           = ignore   # ignore/add/remove/force\n\n# Add or remove newline after each ',' in the constructor member initialization\nnl_class_init_args                       = ignore   # ignore/add/remove/force\n\n# Add or remove newline between return type and function name in a function definition\nnl_func_type_name                        = force    # ignore/add/remove/force\n\n# Add or remove newline between return type and function name inside a class {}\n# Uses nl_func_type_name or nl_func_proto_type_name if set to ignore.\nnl_func_type_name_class                  = ignore   # ignore/add/remove/force\n\n# Add or remove newline between function scope and name in a definition\n# Controls the newline after '::' in 'void A::f() { }'\nnl_func_scope_name                       = ignore   # ignore/add/remove/force\n\n# Add or remove newline between return type and function name in a prototype\nnl_func_proto_type_name                  = remove   # ignore/add/remove/force\n\n# Add or remove newline between a function name and the opening '('\nnl_func_paren                            = remove   # ignore/add/remove/force\n\n# Add or remove newline between a function name and the opening '(' in the definition\nnl_func_def_paren                        = remove   # ignore/add/remove/force\n\n# Add or remove newline after '(' in a function declaration\nnl_func_decl_start                       = remove   # ignore/add/remove/force\n\n# Add or remove newline after '(' in a function definition\nnl_func_def_start                        = ignore   # ignore/add/remove/force\n\n# Overrides nl_func_decl_start when there is only one parameter.\nnl_func_decl_start_single                = ignore   # ignore/add/remove/force\n\n# Overrides nl_func_def_start when there is only one parameter.\nnl_func_def_start_single                 = ignore   # ignore/add/remove/force\n\n# Add or remove newline after each ',' in a function declaration\nnl_func_decl_args                        = ignore   # ignore/add/remove/force\n\n# Add or remove newline after each ',' in a function definition\nnl_func_def_args                         = ignore   # ignore/add/remove/force\n\n# Add or remove newline before the ')' in a function declaration\nnl_func_decl_end                         = remove   # ignore/add/remove/force\n\n# Add or remove newline before the ')' in a function definition\nnl_func_def_end                          = ignore   # ignore/add/remove/force\n\n# Overrides nl_func_decl_end when there is only one parameter.\nnl_func_decl_end_single                  = ignore   # ignore/add/remove/force\n\n# Overrides nl_func_def_end when there is only one parameter.\nnl_func_def_end_single                   = ignore   # ignore/add/remove/force\n\n# Add or remove newline between '()' in a function declaration.\nnl_func_decl_empty                       = ignore   # ignore/add/remove/force\n\n# Add or remove newline between '()' in a function definition.\nnl_func_def_empty                        = ignore   # ignore/add/remove/force\n\n# Add or remove newline between function signature and '{'\nnl_fdef_brace                            = force    # ignore/add/remove/force\n\n# Whether to put a newline after 'return' statement\nnl_after_return                          = false    # false/true\n\n# Add or remove a newline between the return keyword and return expression.\nnl_return_expr                           = ignore   # ignore/add/remove/force\n\n# Whether to put a newline after semicolons, except in 'for' statements\nnl_after_semicolon                       = true     # false/true\n\n# Whether to put a newline after brace open.\n# This also adds a newline before the matching brace close.\nnl_after_brace_open                      = false    # false/true\n\n# If nl_after_brace_open and nl_after_brace_open_cmt are true, a newline is\n# placed between the open brace and a trailing single-line comment.\nnl_after_brace_open_cmt                  = false    # false/true\n\n# Whether to put a newline after a virtual brace open with a non-empty body.\n# These occur in un-braced if/while/do/for statement bodies.\nnl_after_vbrace_open                     = true     # false/true\n\n# Whether to put a newline after a virtual brace open with an empty body.\n# These occur in un-braced if/while/do/for statement bodies.\nnl_after_vbrace_open_empty               = false    # false/true\n\n# Whether to put a newline after a brace close.\n# Does not apply if followed by a necessary ';'.\nnl_after_brace_close                     = false    # false/true\n\n# Whether to put a newline after a virtual brace close.\n# Would add a newline before return in: 'if (foo) a++; return;'\nnl_after_vbrace_close                    = false    # false/true\n\n# Whether to alter newlines in '#define' macros\nnl_define_macro                          = false    # false/true\n\n# Whether to not put blanks after '#ifxx', '#elxx', or before '#endif'\nnl_squeeze_ifdef                         = false    # false/true\n\n# Add or remove blank line before 'if'\nnl_before_if                             = ignore   # ignore/add/remove/force\n\n# Add or remove blank line after 'if' statement\nnl_after_if                              = ignore   # ignore/add/remove/force\n\n# Add or remove blank line before 'for'\nnl_before_for                            = ignore   # ignore/add/remove/force\n\n# Add or remove blank line after 'for' statement\nnl_after_for                             = ignore   # ignore/add/remove/force\n\n# Add or remove blank line before 'while'\nnl_before_while                          = ignore   # ignore/add/remove/force\n\n# Add or remove blank line after 'while' statement\nnl_after_while                           = ignore   # ignore/add/remove/force\n\n# Add or remove blank line before 'switch'\nnl_before_switch                         = ignore   # ignore/add/remove/force\n\n# Add or remove blank line after 'switch' statement\nnl_after_switch                          = ignore   # ignore/add/remove/force\n\n# Add or remove blank line before 'do'\nnl_before_do                             = ignore   # ignore/add/remove/force\n\n# Add or remove blank line after 'do/while' statement\nnl_after_do                              = ignore   # ignore/add/remove/force\n\n# Whether to double-space commented-entries in struct/enum\nnl_ds_struct_enum_cmt                    = false    # false/true\n\n# Whether to double-space before the close brace of a struct/union/enum\n# (lower priority than 'eat_blanks_before_close_brace')\nnl_ds_struct_enum_close_brace            = false    # false/true\n\n# Add or remove a newline around a class colon.\n# Related to pos_class_colon, nl_class_init_args, and pos_comma.\nnl_class_colon                           = ignore   # ignore/add/remove/force\n\n# Change simple unbraced if statements into a one-liner\n# 'if(b)\\n i++;' => 'if(b) i++;'\nnl_create_if_one_liner                   = false    # false/true\n\n# Change simple unbraced for statements into a one-liner\n# 'for (i=0;i<5;i++)\\n foo(i);' => 'for (i=0;i<5;i++) foo(i);'\nnl_create_for_one_liner                  = false    # false/true\n\n# Change simple unbraced while statements into a one-liner\n# 'while (i<5)\\n foo(i++);' => 'while (i<5) foo(i++);'\nnl_create_while_one_liner                = false    # false/true\n\n#\n# Positioning options\n#\n\n# The position of arithmetic operators in wrapped expressions\npos_arith                                = ignore   # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force\n\n# The position of assignment in wrapped expressions.\n# Do not affect '=' followed by '{'\npos_assign                               = ignore   # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force\n\n# The position of boolean operators in wrapped expressions\npos_bool                                 = ignore   # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force\n\n# The position of comparison operators in wrapped expressions\npos_compare                              = ignore   # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force\n\n# The position of conditional (b ? t : f) operators in wrapped expressions\npos_conditional                          = ignore   # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force\n\n# The position of the comma in wrapped expressions\npos_comma                                = ignore   # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force\n\n# The position of the comma in the constructor initialization list\npos_class_comma                          = ignore   # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force\n\n# The position of colons between constructor and member initialization\npos_class_colon                          = ignore   # ignore/lead/lead_break/lead_force/trail/trail_break/trail_force\n\n#\n# Line Splitting options\n#\n\n# Try to limit code width to N number of columns\ncode_width                               = 120      # number\n\n# Whether to fully split long 'for' statements at semi-colons\nls_for_split_full                        = false    # false/true\n\n# Whether to fully split long function protos/calls at commas\nls_func_split_full                       = false    # false/true\n\n#\n# Blank line options\n#\n\n# The maximum consecutive newlines\nnl_max                                   = 2        # number\n\n# The number of newlines after a function prototype, if followed by another function prototype\nnl_after_func_proto                      = 0        # number\n\n# The number of newlines after a function prototype, if not followed by another function prototype\nnl_after_func_proto_group                = 0        # number\n\n# The number of newlines after '}' of a multi-line function body\nnl_after_func_body                       = 2        # number\n\n# The number of newlines after '}' of a single line function body\nnl_after_func_body_one_liner             = 2        # number\n\n# The minimum number of newlines before a multi-line comment.\n# Doesn't apply if after a brace open or another multi-line comment.\nnl_before_block_comment                  = 0        # number\n\n# The minimum number of newlines before a single-line C comment.\n# Doesn't apply if after a brace open or other single-line C comments.\nnl_before_c_comment                      = 0        # number\n\n# The minimum number of newlines before a CPP comment.\n# Doesn't apply if after a brace open or other CPP comments.\nnl_before_cpp_comment                    = 0        # number\n\n# Whether to force a newline after a multi-line comment.\nnl_after_multiline_comment               = false    # false/true\n\n# The number of newlines before a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label.\n# Will not change the newline count if after a brace open.\n# 0 = No change.\nnl_before_access_spec                    = 0        # number\n\n# The number of newlines after a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label.\n# 0 = No change.\nnl_after_access_spec                     = 0        # number\n\n# The number of newlines between a function def and the function comment.\n# 0 = No change.\nnl_comment_func_def                      = 0        # number\n\n# The number of newlines after a try-catch-finally block that isn't followed by a brace close.\n# 0 = No change.\nnl_after_try_catch_finally               = 0        # number\n\n# The number of newlines before and after a property, indexer or event decl.\n# 0 = No change.\nnl_around_cs_property                    = 0        # number\n\n# The number of newlines between the get/set/add/remove handlers in C#.\n# 0 = No change.\nnl_between_get_set                       = 0        # number\n\n# Whether to remove blank lines after '{'\neat_blanks_after_open_brace              = true     # false/true\n\n# Whether to remove blank lines before '}'\neat_blanks_before_close_brace            = true     # false/true\n\n#\n# Code modifying options (non-whitespace)\n#\n\n# Add or remove braces on single-line 'do' statement\nmod_full_brace_do                        = remove   # ignore/add/remove/force\n\n# Add or remove braces on single-line 'for' statement\nmod_full_brace_for                       = remove   # ignore/add/remove/force\n\n# Add or remove braces on single-line function definitions. (Pawn)\nmod_full_brace_function                  = ignore   # ignore/add/remove/force\n\n# Add or remove braces on single-line 'if' statement. Will not remove the braces if they contain an 'else'.\nmod_full_brace_if                        = ignore   # ignore/add/remove/force\n\n# Make all if/elseif/else statements in a chain be braced or not. Overrides mod_full_brace_if.\n# If any must be braced, they are all braced.  If all can be unbraced, then the braces are removed.\nmod_full_brace_if_chain                  = false    # false/true\n\n# Don't remove braces around statements that span N newlines\nmod_full_brace_nl                        = 0        # number\n\n# Add or remove braces on single-line 'while' statement\nmod_full_brace_while                     = remove   # ignore/add/remove/force\n\n# Add or remove braces on single-line 'using ()' statement\nmod_full_brace_using                     = remove   # ignore/add/remove/force\n\n# Add or remove unnecessary paren on 'return' statement\nmod_paren_on_return                      = remove   # ignore/add/remove/force\n\n# Whether to change optional semicolons to real semicolons\nmod_pawn_semicolon                       = false    # false/true\n\n# Add parens on 'while' and 'if' statement around bools\nmod_full_paren_if_bool                   = false    # false/true\n\n# Whether to remove superfluous semicolons\nmod_remove_extra_semicolon               = true     # false/true\n\n# If a function body exceeds the specified number of newlines and doesn't have a comment after\n# the close brace, a comment will be added.\nmod_add_long_function_closebrace_comment = 0        # number\n\n# If a switch body exceeds the specified number of newlines and doesn't have a comment after\n# the close brace, a comment will be added.\nmod_add_long_switch_closebrace_comment   = 0        # number\n\n# If an #ifdef body exceeds the specified number of newlines and doesn't have a comment after\n# the #else, a comment will be added.\nmod_add_long_ifdef_endif_comment         = 0        # number\n\n# If an #ifdef or #else body exceeds the specified number of newlines and doesn't have a comment after\n# the #endif, a comment will be added.\nmod_add_long_ifdef_else_comment          = 0        # number\n\n# If TRUE, will sort consecutive single-line 'import' statements [Java, D]\nmod_sort_import                          = false    # false/true\n\n# If TRUE, will sort consecutive single-line 'using' statements [C#]\nmod_sort_using                           = false    # false/true\n\n# If TRUE, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C]\n# This is generally a bad idea, as it may break your code.\nmod_sort_include                         = false    # false/true\n\n# If TRUE, it will move a 'break' that appears after a fully braced 'case' before the close brace.\nmod_move_case_break                      = false    # false/true\n\n# Will add or remove the braces around a fully braced case statement.\n# Will only remove the braces if there are no variable declarations in the block.\nmod_case_brace                           = ignore   # ignore/add/remove/force\n\n# If TRUE, it will remove a void 'return;' that appears as the last statement in a function.\nmod_remove_empty_return                  = false    # false/true\n\n#\n# Comment modifications\n#\n\n# Try to wrap comments at cmt_width columns\ncmt_width                                = 0        # number\n\n# Set the comment reflow mode (default: 0)\n# 0: no reflowing (apart from the line wrapping due to cmt_width)\n# 1: no touching at all\n# 2: full reflow\ncmt_reflow_mode                          = 0        # number\n\n# If false, disable all multi-line comment changes, including cmt_width. keyword substitution, and leading chars.\n# Default is true.\ncmt_indent_multi                         = true     # false/true\n\n# Whether to group c-comments that look like they are in a block\ncmt_c_group                              = false    # false/true\n\n# Whether to put an empty '/*' on the first line of the combined c-comment\ncmt_c_nl_start                           = false    # false/true\n\n# Whether to put a newline before the closing '*/' of the combined c-comment\ncmt_c_nl_end                             = false    # false/true\n\n# Whether to group cpp-comments that look like they are in a block\ncmt_cpp_group                            = false    # false/true\n\n# Whether to put an empty '/*' on the first line of the combined cpp-comment\ncmt_cpp_nl_start                         = false    # false/true\n\n# Whether to put a newline before the closing '*/' of the combined cpp-comment\ncmt_cpp_nl_end                           = false    # false/true\n\n# Whether to change cpp-comments into c-comments\ncmt_cpp_to_c                             = false    # false/true\n\n# Whether to put a star on subsequent comment lines\ncmt_star_cont                            = true     # false/true\n\n# The number of spaces to insert at the start of subsequent comment lines\ncmt_sp_before_star_cont                  = 0        # number\n\n# The number of spaces to insert after the star on subsequent comment lines\ncmt_sp_after_star_cont                   = 0        # number\n\n# For multi-line comments with a '*' lead, remove leading spaces if the first and last lines of\n# the comment are the same length. Default=True\ncmt_multi_check_last                     = false    # false/true\n\n# The filename that contains text to insert at the head of a file if the file doesn't start with a C/C++ comment.\n# Will substitute $(filename) with the current file's name.\ncmt_insert_file_header                   = \"\"         # string\n\n# The filename that contains text to insert at the end of a file if the file doesn't end with a C/C++ comment.\n# Will substitute $(filename) with the current file's name.\ncmt_insert_file_footer                   = \"\"         # string\n\n# The filename that contains text to insert before a function implementation if the function isn't preceded with a C/C++ comment.\n# Will substitute $(function) with the function name and $(javaparam) with the javadoc @param and @return stuff.\n# Will also substitute $(fclass) with the class name: void CFoo::Bar() { ... }\ncmt_insert_func_header                   = \"\"         # string\n\n# The filename that contains text to insert before a class if the class isn't preceded with a C/C++ comment.\n# Will substitute $(class) with the class name.\ncmt_insert_class_header                  = \"\"         # string\n\n# If a preprocessor is encountered when stepping backwards from a function name, then\n# this option decides whether the comment should be inserted.\n# Affects cmt_insert_func_header and cmt_insert_class_header.\ncmt_insert_before_preproc                = false    # false/true\n\n#\n# Preprocessor options\n#\n\n# Control indent of preprocessors inside #if blocks at brace level 0\npp_indent                                = remove   # ignore/add/remove/force\n\n# Whether to indent #if/#else/#endif at the brace level (true) or from column 1 (false)\npp_indent_at_level                       = false    # false/true\n\n# If pp_indent_at_level=false, specifies the number of columns to indent per level. Default=1.\npp_indent_count                          = 1        # number\n\n# Add or remove space after # based on pp_level of #if blocks\npp_space                                 = remove   # ignore/add/remove/force\n\n# Sets the number of spaces added with pp_space\npp_space_count                           = 0        # number\n\n# The indent for #region and #endregion in C# and '#pragma region' in C/C++\npp_indent_region                         = 0        # number\n\n# Whether to indent the code between #region and #endregion\npp_region_indent_code                    = false    # false/true\n\n# If pp_indent_at_level=true, sets the indent for #if, #else, and #endif when not at file-level\npp_indent_if                             = 0        # number\n\n# Control whether to indent the code between #if, #else and #endif when not at file-level\npp_if_indent_code                        = false    # false/true\n\n# Whether to indent '#define' at the brace level (true) or from column 1 (false)\npp_define_at_level                       = false    # false/true\n\n# You can force a token to be a type with the 'type' option.\n# Example:\n# type myfoo1 myfoo2\n#\n# You can create custom macro-based indentation using macro-open,\n# macro-else and macro-close.\n# Example:\n# macro-open  BEGIN_TEMPLATE_MESSAGE_MAP\n# macro-open  BEGIN_MESSAGE_MAP\n# macro-close END_MESSAGE_MAP\n#\n# You can assign any keyword to any type with the set option.\n# set func_call_user _ N_\n#\n# The full syntax description of all custom definition config entries\n# is shown below:\n#\n# define custom tokens as:\n# - embed whitespace in token using '' escape character, or\n#   put token in quotes\n# - these: ' \" and ` are recognized as quote delimiters\n#\n# type token1 token2 token3 ...\n#             ^ optionally specify multiple tokens on a single line\n# define def_token output_token\n#                  ^ output_token is optional, then NULL is assumed\n# macro-open token\n# macro-close token\n# macro-else token\n# set id token1 token2 ...\n#               ^ optionally specify multiple tokens on a single line\n#     ^ id is one of the names in token_enum.h sans the CT_ prefix,\n#       e.g. PP_PRAGMA\n#\n# all tokens are separated by any mix of ',' commas, '=' equal signs\n# and whitespace (space, tab)\n#\n"
  },
  {
    "path": "AUTHORS",
    "content": "Shadowsocks-libev was originally created in late 2013, by\nClowwindy <clowwindy@gmail.com>, then rewritten and maintained by\nMax Lv <max.c.lv@gmail.com>.\n\nHere is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS --\npeople who have submitted patches, fixed bugs, added translations, and\ngenerally made shadowsocks-libev that much better:\n\nhttps://github.com/shadowsocks/shadowsocks-libev/graphs/contributors\n"
  },
  {
    "path": "CLAUDE.md",
    "content": "# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\nshadowsocks-libev is a lightweight SOCKS5 proxy written in pure C. Version 3.3.6, licensed under GPLv3.\n\n## Build Commands\n\n### CMake (sole build system)\n\n```bash\ngit submodule update --init --recursive\nmkdir -p build && cd build\ncmake ..\nmake\nsudo make install\n```\n\nOn macOS, CMake should auto-detect library paths. If needed, specify paths:\n```bash\ncmake .. -DCMAKE_PREFIX_PATH=\"/usr/local/opt/mbedtls;/usr/local/opt/libsodium\"\n```\n\nCMake outputs binaries to `build/bin/` (static) and `build/shared/bin/` (shared).\n\n### Build Dependencies\n\n- cmake (>= 3.2), a C compiler (gcc or clang), pkg-config\n- libmbedtls, libsodium (>= 1.0.4), libpcre3, libev, libc-ares\n- asciidoc + xmlto (documentation only)\n\n### CMake Options\n\n- `-DWITH_EMBEDDED_SRC=OFF`: use system libcork/libipset/libbloom instead of bundled submodules\n- `-DWITH_DOC_MAN=OFF`: skip man page generation\n- `-DENABLE_CONNMARKTOS=ON`: Linux netfilter conntrack QoS support\n- `-DENABLE_NFTABLES=ON`: nftables firewall integration\n- `-DDISABLE_SSP=ON`: disable stack protector\n- `-DBUILD_TESTING=OFF`: disable unit tests\n\n## Testing\n\n### Unit Tests (CTest)\n\n```bash\ncd build\nctest --output-on-failure\n```\n\n10 unit test modules cover: base64, buffer, crypto, json, jconf, cache, ppbloom, rule, netutils, utils.\n\n### Integration Tests\n\nIntegration tests use Python and require `curl` and `dig` to be available:\n```bash\nbash tests/test.sh\n```\n\nThe test harness (`tests/test.py`) starts ss-server, ss-local, and ss-tunnel locally, then runs curl through the SOCKS5 proxy and dig through the tunnel. Each test config in `tests/*.json` exercises a different cipher.\n\nRun a single cipher test:\n```bash\npython tests/test.py --bin build/bin/ -c tests/aes-gcm.json\n```\n\n## Code Formatting\n\nUses **uncrustify** with the config at `.uncrustify.cfg`. Key settings: 4-space indent, no tabs, 120-column width, K&R brace style (braces on same line).\n\n## Architecture\n\n### Binaries (all in `src/`)\n\nEach binary is compiled with a module define that controls conditional compilation:\n\n| Binary | Define | Purpose |\n|---|---|---|\n| `ss-local` | `MODULE_LOCAL` | SOCKS5 client proxy |\n| `ss-server` | `MODULE_REMOTE` | Server-side proxy |\n| `ss-tunnel` | `MODULE_TUNNEL` | Port forwarding tunnel (implies `MODULE_LOCAL`) |\n| `ss-redir` | `MODULE_REDIR` | Transparent proxy via iptables (Linux only, implies `MODULE_LOCAL`) |\n| `ss-manager` | `MODULE_MANAGER` | Multi-server manager daemon |\n\nA shared library `libshadowsocks-libev` is also built from the ss-local sources with `-DLIB_ONLY`. Its public API is in `src/shadowsocks.h`.\n\n### Source Organization (`src/`)\n\n**Shared by all binaries:**\n- `utils.c` - logging, system utilities\n- `jconf.c` / `json.c` - JSON config file parsing\n- `netutils.c` - network address utilities\n- `cache.c` - hash-based LRU connection cache\n- `udprelay.c` - UDP relay implementation (shared, but uses `#ifdef MODULE_*` for per-binary behavior)\n\n**Crypto layer** (two parallel implementations behind a common `crypto_t` interface):\n- `crypto.c` / `crypto.h` - crypto initialization, key derivation (HKDF), buffer management. Defines `crypto_t` with function pointers for encrypt/decrypt.\n- `stream.c` - stream cipher implementation (CFB mode via mbedTLS)\n- `aead.c` - AEAD cipher implementation (AES-GCM via mbedTLS, ChaCha20-Poly1305 via libsodium)\n- `ppbloom.c` - ping-pong bloom filter for nonce replay detection\n\n**ACL (Access Control Lists):**\n- `acl.c` / `rule.c` - IP/domain-based routing rules using libipset\n\n**Plugin support:**\n- `plugin.c` - SIP003 plugin subprocess management\n\n### Bundled Submodules\n\nThree git submodules in the repo root (can be replaced with system libs via `-DWITH_EMBEDDED_SRC=OFF`):\n- `libcork/` - data structures (dllist, hash-table, buffers)\n- `libipset/` - IP set operations for ACL\n- `libbloom/` - bloom filter implementation\n\n### Event Loop\n\nAll binaries use **libev** for async I/O. The connection lifecycle follows stages defined in `src/common.h`: `STAGE_INIT` -> `STAGE_HANDSHAKE` -> `STAGE_RESOLVE` -> `STAGE_STREAM` -> `STAGE_STOP`. Each binary defines its own `listen_ctx_t`, `server_t`, and `remote_t` structs (note: \"server\" in `local.h` means the local-side connection, \"remote\" means the ss-server side).\n\n### Compiler Flags\n\nDefault flags from `CMakeLists.txt`: `-g -O2 -Wall -Werror -Wno-deprecated-declarations -fno-strict-aliasing -std=gnu99 -D_GNU_SOURCE`\n\nThe `-Werror` flag means all warnings are errors - new code must compile warning-free.\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nset(PROJECT_NAME shadowsocks-libev)\nset(RELEASE_DATE 2026-02-09)\nset(PROJECT_VERSION \"3.3.6\")\nset(PROJECT_DESC \"a lightweight secured socks5 proxy\")\nset(PROJECT_URL \"https://shadowsocks.org\")\nset(PROJECT_ISSUES_URL \"https://github.com/shadowsocks/shadowsocks-libev\")\nproject(${PROJECT_NAME} VERSION ${PROJECT_VERSION})\n\ninclude(GNUInstallDirs)\n\n# Compiler flags matching autotools\n# Note: -Werror is applied per-target in src/CMakeLists.txt to avoid\n# breaking bundled submodules (libcork, libipset, libbloom)\nset(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -std=gnu99 -D_GNU_SOURCE\")\nset(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -g -O2 -Wall -Wno-deprecated-declarations -fno-strict-aliasing\")\n\nset(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)\nset(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)\nset(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)\nset(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)\nset(RUNTIME_SHARED_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/shared/bin)\n\nset(CMAKE_MACOSX_RPATH TRUE)\n\nset(CMAKE_POSITION_INDEPENDENT_CODE ON)\n\nif (NOT CMAKE_BUILD_TYPE)\n    set(CMAKE_BUILD_TYPE Debug)\nendif ()\n# Detect linux\nif (UNIX AND NOT APPLE)\n    set(LINUX TRUE)\nendif ()\n\nmessage(STATUS \"Running cmake version ${CMAKE_VERSION}\")\n\noption(WITH_STATIC \"build with static libraries.\" ON)\noption(WITH_EMBEDDED_SRC \"build with embedded libcork, libipset, and libbloom source.\" ON)\noption(ENABLE_CONNMARKTOS \"Enable saved connmark to IP TOS QoS feature\" OFF)\noption(ENABLE_NFTABLES \"Report malicious IP to nftables\" OFF)\n\n# When choose to not use embedded libcork, libipset and libbloom, use libs shipped by system\nif (NOT WITH_EMBEDDED_SRC)\n    set(USE_SYSTEM_SHARED_LIB TRUE)\nendif ()\n\n# Find dependencies via Find modules\nfind_package(PCRE2 REQUIRED)\nfind_package(MbedTLS REQUIRED)\nfind_package(Sodium REQUIRED)\nfind_package(Cares REQUIRED)\n\n# Connmarktos support\nif(ENABLE_CONNMARKTOS)\n    if(NOT LINUX)\n        message(FATAL_ERROR \"connmarktos is only supported on Linux\")\n    endif()\n    find_library(NETFILTER_CONNTRACK_LIB netfilter_conntrack)\n    find_library(NFNETLINK_LIB nfnetlink)\n    if(NOT NETFILTER_CONNTRACK_LIB)\n        message(FATAL_ERROR \"--enable-connmarktos specified but libnetfilter_conntrack not found\")\n    endif()\n    set(USE_NFCONNTRACK_TOS 1)\n    message(STATUS \"Connmarktos enabled\")\nendif()\n\n# Nftables support\nif(ENABLE_NFTABLES)\n    if(NOT LINUX)\n        message(FATAL_ERROR \"nftables is only supported on Linux\")\n    endif()\n    find_library(MNL_LIB mnl)\n    find_library(NFTNL_LIB nftnl)\n    if(NOT MNL_LIB OR NOT NFTNL_LIB)\n        message(FATAL_ERROR \"--enable-nftables specified but libmnl or libnftnl not found\")\n    endif()\n    set(USE_NFTABLES 1)\n    message(STATUS \"Nftables enabled\")\nendif()\n\n# Run platform tests\ninclude(${PROJECT_SOURCE_DIR}/cmake/configure.cmake)\nconfigure_file(${PROJECT_SOURCE_DIR}/cmake/config.h.cmake ${PROJECT_BINARY_DIR}/src/config.h)\nadd_definitions(-I${PROJECT_BINARY_DIR}/src)\nadd_definitions(-DHAVE_CONFIG_H)\n\n# pkg-config\nconfigure_file(\n        ${PROJECT_SOURCE_DIR}/cmake/shadowsocks-libev.pc.cmake\n        ${PROJECT_BINARY_DIR}/pkgconfig/shadowsocks-libev.pc\n        @ONLY\n)\ninstall(FILES\n        ${PROJECT_BINARY_DIR}/pkgconfig/shadowsocks-libev.pc\n        DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig\n        )\n\nif (WITH_EMBEDDED_SRC)\n# We need libcork,libipset headers\ninclude_directories(libcork/include)\ninclude_directories(libipset/include)\ninclude_directories(libbloom/murmur2)\ninclude_directories(libbloom)\n\nset(LIBCORK_SOURCE\n        libcork/src/libcork/cli/commands.c\n        libcork/src/libcork/core/allocator.c\n        libcork/src/libcork/core/error.c\n        libcork/src/libcork/core/gc.c\n        libcork/src/libcork/core/hash.c\n        libcork/src/libcork/core/ip-address.c\n        libcork/src/libcork/core/mempool.c\n        libcork/src/libcork/core/timestamp.c\n        libcork/src/libcork/core/u128.c\n        libcork/src/libcork/core/version.c\n        libcork/src/libcork/ds/array.c\n        libcork/src/libcork/ds/bitset.c\n        libcork/src/libcork/ds/buffer.c\n        libcork/src/libcork/ds/dllist.c\n        libcork/src/libcork/ds/file-stream.c\n        libcork/src/libcork/ds/hash-table.c\n        libcork/src/libcork/ds/managed-buffer.c\n        libcork/src/libcork/ds/ring-buffer.c\n        libcork/src/libcork/ds/slice.c\n        libcork/src/libcork/posix/directory-walker.c\n        libcork/src/libcork/posix/env.c\n        libcork/src/libcork/posix/exec.c\n        libcork/src/libcork/posix/files.c\n        libcork/src/libcork/posix/process.c\n        libcork/src/libcork/pthreads/thread.c\n        )\nif (NOT MINGW)\nset(LIBCORK_SOURCE ${LIBCORK_SOURCE} libcork/src/libcork/posix/subprocess.c)\nelse ()\nset(LIBCORK_SOURCE ${LIBCORK_SOURCE} libcork/src/libcork/posix/mingw.c)\nendif ()\n\nadd_library(cork STATIC ${LIBCORK_SOURCE})\ntarget_compile_definitions(cork PUBLIC -DCORK_API=CORK_LOCAL)\nif (MINGW)\ntarget_link_libraries(cork ws2_32)\nendif ()\n\nset(LIBIPSET_SOURCE\n        libipset/src/libipset/general.c\n        libipset/src/libipset/bdd/assignments.c\n        libipset/src/libipset/bdd/basics.c\n        libipset/src/libipset/bdd/bdd-iterator.c\n        libipset/src/libipset/bdd/expanded.c\n        libipset/src/libipset/bdd/reachable.c\n        libipset/src/libipset/bdd/read.c\n        libipset/src/libipset/bdd/write.c\n        libipset/src/libipset/map/allocation.c\n        libipset/src/libipset/map/inspection.c\n        libipset/src/libipset/map/ipv4_map.c\n        libipset/src/libipset/map/ipv6_map.c\n        libipset/src/libipset/map/storage.c\n        libipset/src/libipset/set/allocation.c\n        libipset/src/libipset/set/inspection.c\n        libipset/src/libipset/set/ipv4_set.c\n        libipset/src/libipset/set/ipv6_set.c\n        libipset/src/libipset/set/iterator.c\n        libipset/src/libipset/set/storage.c\n        )\n\nadd_library(ipset STATIC ${LIBIPSET_SOURCE})\n\nset(LIBBLOOM_SOURCE\n        libbloom/bloom.c\n        libbloom/murmur2/MurmurHash2.c\n        )\n\nadd_library(bloom STATIC ${LIBBLOOM_SOURCE})\ntarget_link_libraries(ipset cork bloom)\nendif ()\n\nadd_subdirectory(src)\nadd_subdirectory(doc)\n\n# Testing\ninclude(CTest)\nif(BUILD_TESTING)\n    add_subdirectory(tests)\nendif()\n\n# Install ss-nat on Linux\nif(LINUX)\n    install(PROGRAMS src/ss-nat DESTINATION ${CMAKE_INSTALL_BINDIR})\nendif()\n\n# Install ss-setup TUI tool\ninstall(PROGRAMS scripts/ss-setup.sh DESTINATION ${CMAKE_INSTALL_BINDIR} RENAME ss-setup)\n"
  },
  {
    "path": "COPYING",
    "content": "This program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful, \nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not, see <http://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "Changes",
    "content": "shadowsocks-libev (3.3.5-1) unstable; urgency=medium\n\n  * Remove the SNI proxy function.\n  * Minor bug fixes. (#2581, #2582, #2590, #2595, #2599,\n    #2600, #2620, #2687, #2692)\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 15 Sep 2020 10:24:43 +0800\n\nshadowsocks-libev (3.3.4-1) unstable; urgency=medium\n\n  * Minor bug fixes. (#2539, #2565, #2566, #2577)\n  * Security bug fixes. (CVE-2019-5163, CVE-2019-5164)\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 10 Jan 2020 09:28:25 +0800\n\nshadowsocks-libev (3.3.3-1) unstable; urgency=medium\n\n  * Refine the handling of suspicious connections.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 31 Oct 2019 15:06:04 +0800\n\nshadowsocks-libev (3.3.2-1) unstable; urgency=medium\n\n  * Refine the handling of fragment request.\n  * Minor bug fixes. (#2463, #2481, #2508)\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 12 Oct 2019 08:42:24 +0800\n\nshadowsocks-libev (3.3.1-1) unstable; urgency=high\n\n  * Fix a high CPU bug introduced in 3.3.0. (#2449)\n  * Fix MinGW build. (#2438)\n  * Minor bug fixes. (#2402, #2412, #2427, #2443)\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 09 Aug 2019 15:02:34 +0800\n\nshadowsocks-libev (3.3.0-1) unstable; urgency=medium\n\n  * Enlarge the socket buffer size to 16KB.\n  * Fix the empty list bug in ss-manager.\n  * Fix the IPv6 address parser.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 08 Jun 2019 07:53:20 +0800\n\nshadowsocks-libev (3.2.5-1) unstable; urgency=medium\n\n  * Fix a bug of port parser.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 09 Mar 2019 18:54:36 +0800\n\nshadowsocks-libev (3.2.4-1) unstable; urgency=medium\n\n  * Fix a crash with MinGW.\n  * Refine SIP003 plugin interface.\n  * Remove connection timeout from all clients.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 26 Feb 2019 09:40:18 +0800\n\nshadowsocks-libev (3.2.3-1) unstable; urgency=medium\n\n  * Fix the alignment issue again.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 28 Nov 2018 00:27:40 -0800\n\nshadowsocks-libev (3.2.2-1) unstable; urgency=medium\n\n  * Fix a bug on 32-bit arch.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 26 Nov 2018 20:07:21 -0800\n\nshadowsocks-libev (3.2.1-1) unstable; urgency=medium\n\n  * Add TCP fast open support to ss-tunnel by @PantherJohn.\n  * Fix several security issues.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 07 Nov 2018 22:31:59 -0800\n\nshadowsocks-libev (3.2.0-1) unstable; urgency=medium\n\n  * Add MinGW support by @linusyang.\n  * Refine c-ares integration by @xnoreq.\n  * Fix building issues with GCC8 by @FlyingheartCN.\n  * Minor bug fixes.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 28 May 2018 19:46:21 -0700\n\nshadowsocks-libev (3.1.3-1) unstable; urgency=medium\n\n  * Fix a bug in UDP relay.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 15 Jan 2018 17:19:31 -0800\n\nshadowsocks-libev (3.1.2-1) unstable; urgency=medium\n\n  * Fix a bug in DNS resolver.\n  * Add new TFO API support.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 28 Dec 2017 21:01:56 -0800\n\nshadowsocks-libev (3.1.1-1) unstable; urgency=high\n\n  * Fix a security issue in ss-manager. (CVE-2017-15924)\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 20 Nov 2017 12:13:04 +0800\n\nshadowsocks-libev (3.1.0-1) unstable; urgency=low\n\n  * Replace libudns with libc-ares.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 14 Sep 2017 19:27:51 -0700\n\nshadowsocks-libev (3.0.8-1) unstable; urgency=medium\n\n  * Refine the ping-pong bloom filter.\n  * Minor bug fixes by @vfreex, @vlolteanu and @jackyyf.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 27 Jul 2017 11:01:37 +0800\n\nshadowsocks-libev (3.0.7-1) unstable; urgency=medium\n\n  * Refine manager mode by @mengxd.\n  * Fix a potential memory leak by @vlolteanu.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 27 Jun 2017 14:08:27 +0800\n\nshadowsocks-libev (3.0.6-1) unstable; urgency=medium\n\n  * Fix a bug with AEAD ciphers.\n  * Refine ACL support by @blackgear.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 26 Apr 2017 13:48:11 +0800\n\nshadowsocks-libev (3.0.5-1) unstable; urgency=medium\n\n  * Fix a bug of TCP Fast Open in ss-redir.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 21 Mar 2017 13:49:18 +0800\n\nshadowsocks-libev (3.0.4-1) unstable; urgency=medium\n\n  * Add CMake files by @wenerme.\n  * Support TCP Fast Open in ss-redir by @lqs.\n  * Support TOS/DESCP in ss-redir by @sduponch.\n  * Refine MPTCP by @sduponch.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 16 Mar 2017 14:07:57 +0800\n\nshadowsocks-libev (3.0.3-1) unstable; urgency=medium\n\n  * Replace nonce cache with a ping-pong bloom filter.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 24 Feb 2017 12:08:31 +0800\n\nshadowsocks-libev (3.0.2-1) unstable; urgency=high\n\n  * Add session key for AEAD. (SIP007)\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 13 Feb 2017 09:07:17 +0800\n\nshadowsocks-libev (3.0.1-1) unstable; urgency=medium\n\n  * Fix a crashe when using stream ciphers.\n  * Fix a protocol bug in AEAD ciphers. (SIP004)\n  * Allow setting keys directly. (SIP006)\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 07 Feb 2017 13:18:02 +0800\n\nshadowsocks-libev (3.0.0-1) unstable; urgency=medium\n\n  * Drop dependencies of OpenSSL and PolarSSL.\n  * Deprecate OTA (One-Time-Auth).\n  * Add new ciphers for SIP004: aes-128-gcm, aes-192-gcm, aes-256-gcm,\n    chacha20-poly1305 and chacha20-ietf-poly1305.\n  * Refine SIP003 to support standalone mode of obfsproxy.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 01 Feb 2017 19:10:14 +0800\n\nshadowsocks-libev (2.6.3-1) unstable; urgency=medium\n\n  * Refine the project structure.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 24 Jan 2017 19:10:45 +0800\n\nshadowsocks-libev (2.6.2-1) unstable; urgency=medium\n\n  * Refine SIP003 plugin support.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 16 Jan 2017 10:16:12 +0800\n\nshadowsocks-libev (2.6.1-1) unstable; urgency=medium\n\n  * Deprecate HTTP/TLS obfuscating.\n  * Add SIP003 plugin support.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 08 Jan 2017 15:14:19 +0800\n\nshadowsocks-libev (2.6.0-1) unstable; urgency=medium\n\n  * Add HTTP/TLS obfuscating.\n  * Add support of aunch_activate_socket on macOS.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 27 Dec 2016 16:37:23 +0800\n\nshadowsocks-libev (2.5.6-1) unstable; urgency=medium\n\n  * Add outbound ACL for server.\n  * Refine log format.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 01 Nov 2016 09:51:52 +0800\n\nshadowsocks-libev (2.5.5-1) unstable; urgency=medium\n\n  * Refine attack detection.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 11 Oct 2016 15:45:09 +0800\n\nshadowsocks-libev (2.5.4-1) unstable; urgency=medium\n\n  * Fix a bug of auto blocking mechanism.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 09 Oct 2016 19:36:37 +0800\n\nshadowsocks-libev (2.5.3-1) unstable; urgency=medium\n\n  * Fix TCP Fast Open on macOS.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 21 Sep 2016 19:31:57 +0800\n\nshadowsocks-libev (2.5.2-1) unstable; urgency=medium\n\n  * Fix a bug of UDP relay mode of ss-local.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 12 Sep 2016 12:54:33 +0800\n\nshadowsocks-libev (2.5.1-1) unstable; urgency=medium\n\n  * Refine ACL feature with hostname support.\n  * Add HTTP/SNI parser for ss-local/ss-redir.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 10 Sep 2016 17:06:49 +0800\n\nshadowsocks-libev (2.5.0-1) unstable; urgency=medium\n\n  * Fix several bugs of the command line interface.\n  * Add aes-128/192/256-ctr ciphers.\n  * Add option MTU for UDP relay.\n  * Add MultiPath TCP support.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 29 Aug 2016 13:07:51 +0800\n\nshadowsocks-libev (2.4.8-1) unstable; urgency=low\n\n  * Update manual pages with asciidoc.\n  * Fix issues of bind_address option.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 20 Jul 2016 09:25:50 +0800\n\nshadowsocks-libev (2.4.7-1) unstable; urgency=low\n\n  * Add ss-nat, a helper script to set up NAT rules for ss-redir.\n  * Fix several issues for debian package.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 1 Jun 2016 18:21:45 +0800\n\nshadowsocks-libev (2.4.6-1) unstable; urgency=low\n\n  * Update manual pages.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 21 Apr 2016 17:33:34 +0800\n\nshadowsocks-libev (2.4.5-1) unstable; urgency=low\n\n  * Fix build issues on OpenWRT.\n  * Reduce the latency of redir mode.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 01 Feb 2016 13:22:50 +0800\n\nshadowsocks-libev (2.4.4-1) unstable; urgency=low\n\n  * Fix a potential memory leak.\n  * Fix some compiler related issues.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 13 Jan 2016 11:50:12 +0800\n\nshadowsocks-libev (2.4.3-1) unstable; urgency=high\n\n  * Refine the buffer allocation.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 19 Dec 2015 12:30:21 +0900\n\nshadowsocks-libev (2.4.1-1) unstable; urgency=high\n\n  * Fix a security bug.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 29 Oct 2015 15:42:47 +0900\n\nshadowsocks-libev (2.4.0-1) unstable; urgency=low\n\n  * Update the one-time authentication\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 24 Sep 2015 14:11:05 +0900\n\nshadowsocks-libev (2.3.3-1) unstable; urgency=low\n\n  * Refine the onetime authentication of header.\n  * Enforce CRC16 on the payload.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 18 Sep 2015 10:38:21 +0900\n\nshadowsocks-libev (2.3.2-1) unstable; urgency=low\n\n  * Fix minor issues of build scripts.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 13 Sep 2015 15:22:28 +0900\n\nshadowsocks-libev (2.3.1-1) unstable; urgency=low\n\n  * Fix an issue of connection cache of UDP relay.\n  * Add support of onetime authentication for header verification.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 04 Sep 2015 07:54:02 +0900\n\nshadowsocks-libev (2.3.0-1) unstable; urgency=low\n\n  * Add manager mode to support multi-user and traffic stat.\n  * Fix a build issue on OS X El Capitan.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 30 Jul 2015 17:30:43 +0900\n\nshadowsocks-libev (2.2.3-1) unstable; urgency=high\n\n  * Fix the multiple UDP source port issue.\n  * Allow working in UDP only mode.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 11 Jul 2015 08:31:02 +0900\n\nshadowsocks-libev (2.2.2-1) unstable; urgency=low\n\n  * Fix the timer of UDP relay.\n  * Check name_len in the header.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 15 Jun 2015 10:26:40 +0900\n\nshadowsocks-libev (2.2.1-1) unstable; urgency=low\n\n  * Fix an issue of UDP relay.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 10 May 2015 21:23:44 +0900\n\nshadowsocks-libev (2.2.0-1) unstable; urgency=low\n\n  * Add TPROXY support in redir mode.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 04 May 2015 02:44:17 -0300\n\nshadowsocks-libev (2.1.4-1) unstable; urgency=low\n\n  * Fix a bug of server mode ACL.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 08 Feb 2015 20:24:43 +0900\n\nshadowsocks-libev (2.1.3-1) unstable; urgency=low\n\n  * Add ACL support to remote server.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 08 Feb 2015 10:59:44 +0900\n\nshadowsocks-libev (2.1.2-1) unstable; urgency=low\n\n  * Refine multiple port binding.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 31 Jan 2015 18:56:25 +0900\n\nshadowsocks-libev (2.1.1-1) unstable; urgency=low\n\n  * Fix a memory leak.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 21 Jan 2015 21:40:58 +0900\n\nshadowsocks-libev (2.1.0-1) unstable; urgency=low\n\n  * Fix a bug of tunnel mode.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 19 Jan 2015 09:59:52 +0900\n\nshadowsocks-libev (2.0.8-1) unstable; urgency=low\n\n  * Fix a bug of IPv6.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 16 Jan 2015 10:58:12 +0900\n\nshadowsocks-libev (2.0.7-1) unstable; urgency=low\n\n  * Fix some performance issue.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 13 Jan 2015 13:17:58 +0900\n\nshadowsocks-libev (2.0.6-1) unstable; urgency=high\n\n  * Fix a critical issue in redir mode.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 12 Jan 2015 21:51:19 +0900\n\nshadowsocks-libev (2.0.5-1) unstable; urgency=low\n\n  * Refine local, tunnel, and redir modes.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 12 Jan 2015 12:39:05 +0800\n\nshadowsocks-libev (2.0.4-1) unstable; urgency=low\n\n  * Fix building issues with MinGW32.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 11 Jan 2015 13:33:31 +0900\n\nshadowsocks-libev (2.0.3-1) unstable; urgency=high\n\n  * Fix some issues.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 10 Jan 2015 16:27:54 +0800\n\nshadowsocks-libev (2.0.2-1) unstable; urgency=low\n\n  * Fix issues with MinGW.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 10 Jan 2015 15:17:10 +0800\n\nshadowsocks-libev (2.0.1-1) unstable; urgency=low\n\n  * Implement a real asynchronous DNS resolver.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 10 Jan 2015 10:04:28 +0800\n\nshadowsocks-libev (1.6.4-1) unstable; urgency=low\n\n  * Update documents.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 07 Jan 2015 21:48:58 +0900\n\nshadowsocks-libev (1.6.3-1) unstable; urgency=low\n\n  * Refine ss-redir.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 04 Jan 2015 19:23:52 +0900\n\nshadowsocks-libev (1.6.2-1) unstable; urgency=low\n\n  * Fix some build issues.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 30 Dec 2014 10:30:28 +0800\n\nshadowsocks-libev (1.6.1-1) unstable; urgency=high\n\n  * Add salsa20 and chacha20 support.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 13 Dec 2014 15:11:34 +0800\n\nshadowsocks-libev (1.6.0-1) unstable; urgency=low\n\n  * Solve conflicts with other shadowsocks portings.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 17 Nov 2014 14:10:21 +0800\n\nshadowsocks-libev (1.5.3-2) unstable; urgency=low\n\n  * rename as shadowsocks-libev.\n\n -- Symeon Huang <hzwhuang@gmail.com>  Sat, 15 Nov 2014 14:55:28 +0000\n\nshadowsocks (1.5.3-1) unstable; urgency=low\n\n  * Fix log on Win32.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 14 Nov 2014 09:10:06 +0800\n\nshadowsocks (1.5.2-1) unstable; urgency=low\n\n  * Handle SIGTERM and SIGKILL nicely.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 12 Nov 2014 13:11:29 +0800\n\nshadowsocks (1.5.1-1) unstable; urgency=low\n\n  * Fix a bug of tcp fast open.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 08 Nov 2014 19:45:37 +0900\n\nshadowsocks (1.5.0-1) unstable; urgency=low\n\n  * Support to build static or shared library.\n  * Supprot IPv6 NAT in redirect mode.\n  * Refine the cache size of UDPRelay.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 07 Nov 2014 09:33:19 +0800\n\nshadowsocks (1.4.8-1) unstable; urgency=low\n\n  * Fix a bug of tcp fast open.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 08 Oct 2014 18:02:02 +0800\n\nshadowsocks (1.4.7-1) unstable; urgency=low\n\n  * Add a new encryptor rc4-md5.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 09 Sep 2014 07:50:10 +0800\n\nshadowsocks (1.4.6-1) unstable; urgency=low\n\n  * Add ACL support.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 03 May 2014 04:37:10 -0400\n\nshadowsocks (1.4.5-1) unstable; urgency=high\n\n  * Fix the compatibility issue of udprelay.\n  * Enhance asyncns to reduce the latency.\n  * Add TCP_FASTOPEN support.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 20 Apr 2014 08:12:45 +0800\n\nshadowsocks (1.4.4-1) unstable; urgency=low\n\n  * Add CommonCrypto support for darwin.\n  * Fix some config related issues.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 26 Mar 2014 13:29:03 +0800\n\nshadowsocks (1.4.3-1) unstable; urgency=low\n\n  * Add tunnel mode with local port forwarding feature.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 21 Feb 2014 11:52:13 +0900\n\nshadowsocks (1.4.2-1) unstable; urgency=high\n\n  * Fix the UDP relay issues.\n  * Add syslog support.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 05 Jan 2014 10:05:29 +0900\n\nshadowsocks (1.4.1-1) unstable; urgency=low\n\n  * Add multi-port support.\n  * Add PolarSSL support by @linusyang.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 12 Nov 2013 03:57:21 +0000\n\nshadowsocks (1.4.0-1) unstable; urgency=low\n\n  * Add standard socks5 udp support.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 08 Sep 2013 02:20:40 +0000\n\nshadowsocks (1.3.3-1) unstable; urgency=high\n\n  * Provide more info in verbose mode.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 21 Jun 2013 09:59:20 +0800\n\nshadowsocks (1.3.2-1) unstable; urgency=high\n\n  * Fix some ciphers by @linusyang.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 09 Jun 2013 09:52:31 +0000\n\nshadowsocks (1.3.1-1) unstable; urgency=low\n\n  * Support more cihpers: camellia, idea, rc2 and seed.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 04 Jun 2013 00:56:17 +0000\n\nshadowsocks (1.3-1) unstable; urgency=low\n\n  * Able to bind connections to specific interface.\n  * Support more ciphers: aes-128-cfb, aes-192-cfb, aes-256-cfb, bf-cfb, cast5-cfb, des-cfb.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 16 May 2013 10:51:15 +0800\n\nshadowsocks (1.2-2) unstable; urgency=low\n\n  * Close timeouted TCP connections.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 07 May 2013 14:10:33 +0800\n\nshadowsocks (1.2-1) unstable; urgency=low\n\n  * Fix a high load issue.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 18 Apr 2013 10:52:34 +0800\n\nshadowsocks (1.1-1) unstable; urgency=low\n\n  * Fix a IPV6 resolve issue.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 10 Apr 2013 12:11:36 +0800\n\nshadowsocks (1.0-2) unstable; urgency=low\n\n  * Initial release.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 06 Apr 2013 16:59:15 +0800\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n"
  },
  {
    "path": "README.md",
    "content": "# shadowsocks-libev\n\n[![Build Status](https://travis-ci.com/shadowsocks/shadowsocks-libev.svg?branch=master)](https://travis-ci.com/shadowsocks/shadowsocks-libev) [![Snap Status](https://snapcraft.io/shadowsocks-libev/badge.svg)](https://snapcraft.io/shadowsocks-libev)\n\n## Intro\n\n[Shadowsocks-libev](https://shadowsocks.org) is a lightweight secured SOCKS5\nproxy for embedded devices and low-end boxes.\n\nIt is a port of [Shadowsocks](https://github.com/shadowsocks/shadowsocks)\ncreated by [@clowwindy](https://github.com/clowwindy), and maintained by\n[@madeye](https://github.com/madeye) and [@linusyang](https://github.com/linusyang).\n\nCurrent version: 3.3.6 | [Changelog](debian/changelog)\n\n## Features\n\nShadowsocks-libev is written in pure C and depends on [libev](http://software.schmorp.de/pkg/libev.html). It's designed\nto be a lightweight implementation of shadowsocks protocol, in order to keep the resource usage as low as possible.\n\nFor a full list of feature comparison between different versions of shadowsocks,\nrefer to the [Wiki page](https://github.com/shadowsocks/shadowsocks/wiki/Feature-Comparison-across-Different-Versions).\n\n## Quick Start\n\nSnap is the recommended way to install the latest binaries.\n\n### Install snap core\n\nhttps://snapcraft.io/core\n\n### Install from snapcraft.io\n\nStable channel:\n\n```bash\nsudo snap install shadowsocks-libev\n```\n\nEdge channel:\n\n```bash\nsudo snap install shadowsocks-libev --edge\n```\n\n## Installation\n\n### Distribution-specific guide\n\n- [Debian & Ubuntu](#debian--ubuntu)\n    + [Install from repository](#install-from-repository-not-recommended)\n    + [Build deb package from source](#build-deb-package-from-source)\n    + [Configure and start the service](#configure-and-start-the-service)\n- [Fedora & RHEL](#fedora--rhel)\n    + [Build from source with centos](#build-from-source-with-centos)\n- [Archlinux & Manjaro](#archlinux--manjaro)\n- [NixOS](#nixos)\n- [Nix](#nix)\n- [Directly build and install on UNIX-like system](#linux)\n- [FreeBSD](#freebsd)\n    + [Install](#install)\n    + [Configuration](#configuration)\n    + [Run](#run)\n    + [Run as client](#run-as-client)\n- [OpenWRT](#openwrt)\n- [OS X](#os-x)\n- [Windows (MinGW)](#windows-mingw)\n- [Docker](#docker)\n\n* * *\n\n### Build from source (CMake)\n\nshadowsocks-libev uses CMake as its sole build system. Start by pulling submodules:\n\n```bash\ngit submodule update --init --recursive\n```\n\nThen build:\n\n```bash\nmkdir -p build && cd build\ncmake ..\nmake\nsudo make install\n```\n\nTo run unit tests:\n\n```bash\ncd build\nctest --output-on-failure\n```\n\n#### CMake options\n\nFor a complete list of available options, run `cmake -LH` from a build directory.\nCommonly used options:\n\n| Option | Default | Description |\n|---|---|---|\n| `-DWITH_EMBEDDED_SRC=OFF` | `ON` | Use system libcork/libipset/libbloom instead of bundled submodules |\n| `-DWITH_DOC_MAN=OFF` | `ON` | Skip man page generation (removes asciidoc/xmlto dependency) |\n| `-DBUILD_TESTING=OFF` | `ON` | Disable unit tests |\n| `-DENABLE_CONNMARKTOS=ON` | `OFF` | Linux netfilter conntrack QoS support |\n| `-DENABLE_NFTABLES=ON` | `OFF` | nftables firewall integration |\n\nOn macOS, if libraries are installed via Homebrew, specify paths:\n\n```bash\ncmake .. -DCMAKE_PREFIX_PATH=\"/usr/local/opt/mbedtls;/usr/local/opt/libsodium\"\n```\n\n### Debian & Ubuntu\n\n#### Install from repository (not recommended)\n\nShadowsocks-libev is available in the official repository for following distributions:\n\n* Debian 8 or higher, including oldoldstable (jessie), old stable (stretch), stable (buster), testing (bullseye) and unstable (sid)\n* Ubuntu 16.10 or higher\n\n```bash\nsudo apt update\nsudo apt install shadowsocks-libev\n```\n\n#### Build deb package from source\n\nYou can build shadowsocks-libev and all its dependencies by script:\n\n```bash\nmkdir -p ~/build-area/\ncp ./scripts/build_deb.sh ~/build-area/\ncd ~/build-area\n./build_deb.sh\n```\n\nFor older systems, building `.deb` packages is not supported.\nPlease try to build and install directly from source. See the [Linux](#linux) section below.\n\n#### Configure and start the service\n\n```\n# Edit the configuration file\nsudo vim /etc/shadowsocks-libev/config.json\n\n# Edit the default configuration for debian\nsudo vim /etc/default/shadowsocks-libev\n\n# Start the service\nsudo /etc/init.d/shadowsocks-libev start    # for sysvinit, or\nsudo systemctl start shadowsocks-libev      # for systemd\n```\n\n### Fedora & RHEL\n\nSupported distributions:\n\n* Recent Fedora versions (until EOL)\n* RHEL 6, 7 and derivatives (including CentOS, Scientific Linux)\n\n#### Build from source with centos\n\nIf you are using CentOS 7, you need to install these prerequirements to build from source code:\n\n```bash\nyum install epel-release -y\nyum install gcc gettext autoconf libtool automake make pcre-devel asciidoc xmlto c-ares-devel libev-devel libsodium-devel mbedtls-devel -y\n```\n\n### Archlinux & Manjaro\n\n```bash\nsudo pacman -S shadowsocks-libev\n```\n\nPlease refer to downstream [PKGBUILD](https://github.com/archlinux/svntogit-community/blob/packages/shadowsocks-libev/trunk/PKGBUILD)\nscript for extra modifications and distribution-specific bugs.\n\n### NixOS\n\n```bash\nnix-env -iA nixos.shadowsocks-libev\n```\n\n### Nix\n\n```bash\nnix-env -iA nixpkgs.shadowsocks-libev\n```\n\n### Linux\n\nIn general, you need the following build dependencies:\n\n* cmake (>= 3.2)\n* a C compiler (gcc or clang)\n* pkg-config\n* libmbedtls\n* libsodium (>= 1.0.4)\n* libpcre2\n* libev\n* libc-ares\n* asciidoc (for documentation only)\n* xmlto (for documentation only)\n\nIf your system is too old to provide libmbedtls and libsodium (>= 1.0.4), you will need to either install those libraries manually or upgrade your system.\n\nInstall build dependencies for your distribution:\n\n```bash\n# Debian / Ubuntu\nsudo apt-get install --no-install-recommends build-essential cmake pkg-config \\\n    libpcre2-dev libev-dev libc-ares-dev libmbedtls-dev libsodium-dev \\\n    asciidoc xmlto\n\n# CentOS / Fedora / RHEL\nsudo yum install gcc cmake make pkg-config pcre2-devel c-ares-devel \\\n    libev-devel libsodium-devel mbedtls-devel asciidoc xmlto\n\n# Arch\nsudo pacman -S gcc cmake make pkg-config pcre2 c-ares libev libsodium mbedtls \\\n    asciidoc xmlto\n```\n\nThen build and install:\n\n```bash\ngit submodule update --init --recursive\nmkdir -p build && cd build\ncmake ..\nmake\nsudo make install\n```\n\n### FreeBSD\n#### Install\nShadowsocks-libev is available in FreeBSD Ports Collection. You can install it in either way, `pkg` or `ports`.\n\n**pkg (recommended)**\n\n```bash\npkg install shadowsocks-libev\n```\n\n**ports**\n\n```bash\ncd /usr/ports/net/shadowsocks-libev\nmake install\n```\n\n#### Configuration\nEdit your `config.json` file. By default, it's located in `/usr/local/etc/shadowsocks-libev`.\n\nTo enable shadowsocks-libev, add the following rc variable to your `/etc/rc.conf` file:\n\n```\nshadowsocks_libev_enable=\"YES\"\n```\n\n#### Run\n\nStart the Shadowsocks server:\n\n```bash\nservice shadowsocks_libev start\n```\n\n#### Run as client\nBy default, shadowsocks-libev is running as a server in FreeBSD. If you would like to start shadowsocks-libev in client mode, you can modify the rc script (`/usr/local/etc/rc.d/shadowsocks_libev`) manually.\n\n```\n# modify the following line from \"ss-server\" to \"ss-local\"\ncommand=\"/usr/local/bin/ss-local\"\n```\n\nNote that is simply a workaround, each time you upgrade the port your changes will be overwritten by the new version.\n\n### OpenWRT\n\nThe OpenWRT project is maintained here:\n[openwrt-shadowsocks](https://github.com/shadowsocks/openwrt-shadowsocks).\n\n### OS X\nFor OS X, use [Homebrew](http://brew.sh) to install or build.\n\nInstall Homebrew:\n\n```bash\nruby -e \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\"\n```\nInstall shadowsocks-libev:\n\n```bash\nbrew install shadowsocks-libev\n```\n\n### Windows (MinGW)\nTo build Windows native binaries, the recommended method is to use Docker:\n\n* On Windows: double-click `make.bat` in `docker\\mingw`\n* On Unix-like system:\n\n        cd shadowsocks-libev/docker/mingw\n        make\n\nA tarball with 32-bit and 64-bit binaries will be generated in the same directory.\n\nYou could also manually use MinGW-w64 compilers to build in Unix-like shell (MSYS2/Cygwin), or cross-compile on Unix-like systems (Linux/MacOS). Please refer to build scripts in `docker/mingw`.\n\nCurrently you need to use a patched libev library for MinGW:\n\n* https://github.com/shadowsocks/libev/archive/mingw.zip\n\nNotice that TCP Fast Open (TFO) is only available on **Windows 10**, **1607** or later version (precisely, build >= 14393). If you are using **1709** (build 16299) or later version, you also need to run the following command in PowerShell/Command Prompt **as Administrator** and **reboot** to use TFO properly:\n\n        netsh int tcp set global fastopenfallback=disabled\n\n### Docker\n\nAs you expect, simply pull the image and run.\n```\ndocker pull shadowsocks/shadowsocks-libev\ndocker run -e PASSWORD=<password> -p<server-port>:8388 -p<server-port>:8388/udp -d shadowsocks/shadowsocks-libev\n```\n\nMore information about the image can be found [here](docker/alpine/README.md).\n\n## Usage\n\nFor a detailed and complete list of all supported arguments,\nyou may refer to the man pages of the applications, respectively.\n\n    ss-[local|redir|server|tunnel|manager]\n\n       -s <server_host>           Host name or IP address of your remote server.\n\n       -p <server_port>           Port number of your remote server.\n\n       -l <local_port>            Port number of your local server.\n\n       -k <password>              Password of your remote server.\n\n       -m <encrypt_method>        Encrypt method: rc4-md5,\n                                  aes-128-gcm, aes-192-gcm, aes-256-gcm,\n                                  aes-128-cfb, aes-192-cfb, aes-256-cfb,\n                                  aes-128-ctr, aes-192-ctr, aes-256-ctr,\n                                  camellia-128-cfb, camellia-192-cfb,\n                                  camellia-256-cfb, bf-cfb,\n                                  chacha20-ietf-poly1305,\n                                  xchacha20-ietf-poly1305,\n                                  salsa20, chacha20 and chacha20-ietf.\n                                  The default cipher is chacha20-ietf-poly1305.\n\n       [-a <user>]                Run as another user.\n\n       [-f <pid_file>]            The file path to store pid.\n\n       [-t <timeout>]             Socket timeout in seconds.\n\n       [-c <config_file>]         The path to config file.\n\n       [-n <number>]              Max number of open files.\n\n       [-i <interface>]           Network interface to bind.\n                                  (not available in redir mode)\n\n       [-b <local_address>]       Local address to bind.\n                                  For servers: Specify the local address to use \n                                  while this server is making outbound \n                                  connections to remote servers on behalf of the\n                                  clients.\n                                  For clients: Specify the local address to use \n                                  while this client is making outbound \n                                  connections to the server.\n\n       [-u]                       Enable UDP relay.\n                                  (TPROXY is required in redir mode)\n\n       [-U]                       Enable UDP relay and disable TCP relay.\n                                  (not available in local mode)\n\n       [-T]                       Use tproxy instead of redirect. (for tcp)\n                                  (only available in redir mode)\n\n       [-L <addr>:<port>]         Destination server address and port\n                                  for local port forwarding.\n                                  (only available in tunnel mode)\n\n       [-6]                       Resolve hostname to IPv6 address first.\n\n       [-d <addr>]                Name servers for internal DNS resolver.\n                                  (only available in server mode)\n\n       [--reuse-port]             Enable port reuse.\n\n       [--fast-open]              Enable TCP fast open.\n                                  with Linux kernel > 3.7.0.\n                                  (only available in local and server mode)\n\n       [--acl <acl_file>]         Path to ACL (Access Control List).\n                                  (only available in local and server mode)\n\n       [--manager-address <addr>] UNIX domain socket address.\n                                  (only available in server and manager mode)\n\n       [--mtu <MTU>]              MTU of your network interface.\n\n       [--mptcp]                  Enable Multipath TCP on MPTCP Kernel.\n\n       [--no-delay]               Enable TCP_NODELAY.\n\n       [--executable <path>]      Path to the executable of ss-server.\n                                  (only available in manager mode)\n\n       [-D <path>]                Path to the working directory of ss-manager.\n                                  (only available in manager mode)\n\n       [--key <key_in_base64>]    Key of your remote server.\n\n       [--plugin <name>]          Enable SIP003 plugin. (Experimental)\n\n       [--plugin-opts <options>]  Set SIP003 plugin options. (Experimental)\n\n       [-v]                       Verbose mode.\n\n## Helper Scripts\n\n### ss-setup\n\n`ss-setup` is an interactive TUI (text user interface) tool for setting up shadowsocks-libev server and client configurations. It uses `whiptail` or `dialog` for the menu interface.\n\nIt is installed automatically by `make install` and can also be run directly from `scripts/ss-setup.sh`.\n\n**Prerequisites:** `whiptail` or `dialog`, `openssl` (optional, for password generation)\n\n#### Server setup (with systemd service)\n\nRun as root for full functionality (config + systemd service installation):\n\n```bash\nsudo ss-setup\n```\n\nThis launches an interactive menu that walks you through:\n1. Choosing a config instance name\n2. Setting the listen address and port (manual or random high port)\n3. Selecting an AEAD cipher (chacha20-ietf-poly1305, aes-256-gcm, etc.)\n4. Generating or entering a password\n5. Configuring timeout, network mode (TCP/UDP), and TCP Fast Open\n6. Optionally selecting a SIP003 plugin\n7. Installing and starting a systemd service\n\nThe config is saved to `/etc/shadowsocks-libev/<name>.json` and a systemd template service `shadowsocks-libev-server@<name>.service` is created.\n\nAt the end, it displays a `ss://` URI you can import into clients.\n\n#### Client config generation\n\nSelect \"Generate ss-local client config\" from the main menu. The wizard prompts for the remote server address, port, cipher, password, and local SOCKS5 port, then writes a JSON config:\n\n```bash\n# Run without root to generate config in the current directory\nss-setup\n# Select: client -> fill in server details -> save\n\n# Then start the client\nss-local -c ~/ss-client.json\n```\n\n#### Config-only mode (non-root)\n\nWhen run without root, `ss-setup` skips service installation and plugin management, but still generates config files in the current directory:\n\n```bash\nss-setup\n# Config saved to ./config.json (in current directory)\n# Start manually:\nss-server -c ./config.json\n```\n\n#### Service management\n\nFrom the main menu, select \"Manage running services\" to start, stop, restart, enable/disable, or view logs for any configured instance:\n\n```\nsudo ss-setup\n# Select: service -> pick instance -> start/stop/restart/logs\n```\n\n#### Plugin installation\n\nSelect \"Install a SIP003 plugin\" from the main menu (requires root). Supports automatic download of:\n- simple-obfs (build from source or package manager)\n- v2ray-plugin (GitHub release)\n- xray-plugin (GitHub release)\n- kcptun (GitHub release)\n- Custom plugin binary\n\n### ss-nat\n\n`ss-nat` is a helper script that sets up iptables NAT rules for `ss-redir` to provide transparent TCP/UDP redirection. It is installed on Linux systems by `make install`.\n\n**Prerequisites:** Linux with `iptables`, `ipset`, and optionally TPROXY kernel module for UDP\n\n#### Basic usage (TCP redirect)\n\n```bash\n# Start ss-redir first\nss-redir -s YOUR_SERVER_IP -p 8388 -l 1080 -k PASSWORD -m chacha20-ietf-poly1305 -u\n\n# Set up NAT rules to redirect TCP traffic through ss-redir\nsudo ss-nat -s YOUR_SERVER_IP -l 1080\n```\n\n#### Enable UDP relay with TPROXY\n\n```bash\nsudo ss-nat -s YOUR_SERVER_IP -l 1080 -u\n```\n\n#### Apply rules to OUTPUT chain (proxy the local machine itself)\n\n```bash\nsudo ss-nat -s YOUR_SERVER_IP -l 1080 -u -o\n```\n\n#### Use separate TCP/UDP servers\n\n```bash\nsudo ss-nat -s TCP_SERVER_IP -l 1080 -S UDP_SERVER_IP -L 1080 -U\n```\n\n#### Bypass specific WAN IPs\n\n```bash\nsudo ss-nat -s YOUR_SERVER_IP -l 1080 -b \"1.2.3.4 5.6.7.8\"\n```\n\n#### Use a bypass IP list file\n\n```bash\n# Create a file with one IP/CIDR per line\necho \"1.2.3.0/24\" > /etc/ss-bypass.list\necho \"5.6.7.0/24\" >> /etc/ss-bypass.list\n\nsudo ss-nat -s YOUR_SERVER_IP -l 1080 -i /etc/ss-bypass.list\n```\n\n#### LAN access control\n\n```bash\n# Whitelist mode: only proxy traffic from these LAN IPs\nsudo ss-nat -s YOUR_SERVER_IP -l 1080 -a \"w192.168.1.10 192.168.1.20\"\n\n# Blacklist mode: proxy all LAN traffic except these IPs\nsudo ss-nat -s YOUR_SERVER_IP -l 1080 -a \"b192.168.1.100\"\n```\n\n#### Flush all rules\n\n```bash\nsudo ss-nat -f\n```\n\n#### Complete example: transparent proxy gateway\n\nSet up a Linux box as a transparent proxy gateway for the entire LAN:\n\n```bash\n# 1. Start ss-redir with UDP relay\nss-redir -s YOUR_SERVER_IP -p 8388 -l 1080 -k PASSWORD \\\n    -m chacha20-ietf-poly1305 -u -f /var/run/ss-redir.pid\n\n# 2. Set up NAT rules (TCP + UDP, apply to local OUTPUT too)\nsudo ss-nat -s YOUR_SERVER_IP -l 1080 -u -o -I eth0\n\n# 3. Point other devices' default gateway to this machine's LAN IP\n#    and set their DNS to a public resolver (e.g., 1.1.1.1 or 8.8.8.8)\n\n# To tear down:\nsudo ss-nat -f\n```\n\n## Transparent proxy (manual iptables)\n\nThe latest shadowsocks-libev has provided a *redir* mode. You can configure your Linux-based box or router to proxy all TCP traffic transparently, which is handy if you use an OpenWRT-powered router.\n\nNote: For most use cases, [`ss-nat`](#ss-nat) above is simpler than writing iptables rules manually.\n\n    # Create new chain\n    iptables -t nat -N SHADOWSOCKS\n    iptables -t mangle -N SHADOWSOCKS\n\n    # Ignore your shadowsocks server's addresses\n    # It's very IMPORTANT, just be careful.\n    iptables -t nat -A SHADOWSOCKS -d 123.123.123.123 -j RETURN\n\n    # Ignore LANs and any other addresses you'd like to bypass the proxy\n    # See Wikipedia and RFC5735 for full list of reserved networks.\n    # See ashi009/bestroutetb for a highly optimized CHN route list.\n    iptables -t nat -A SHADOWSOCKS -d 0.0.0.0/8 -j RETURN\n    iptables -t nat -A SHADOWSOCKS -d 10.0.0.0/8 -j RETURN\n    iptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN\n    iptables -t nat -A SHADOWSOCKS -d 169.254.0.0/16 -j RETURN\n    iptables -t nat -A SHADOWSOCKS -d 172.16.0.0/12 -j RETURN\n    iptables -t nat -A SHADOWSOCKS -d 192.168.0.0/16 -j RETURN\n    iptables -t nat -A SHADOWSOCKS -d 224.0.0.0/4 -j RETURN\n    iptables -t nat -A SHADOWSOCKS -d 240.0.0.0/4 -j RETURN\n\n    # Anything else should be redirected to shadowsocks's local port\n    iptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports 12345\n\n    # Add any UDP rules\n    ip route add local default dev lo table 100\n    ip rule add fwmark 1 lookup 100\n    iptables -t mangle -A SHADOWSOCKS -p udp --dport 53 -j TPROXY --on-port 12345 --tproxy-mark 0x01/0x01\n\n    # Apply the rules\n    iptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS\n    iptables -t mangle -A PREROUTING -j SHADOWSOCKS\n\n    # Start the shadowsocks-redir\n    ss-redir -u -c /etc/config/shadowsocks.json -f /var/run/shadowsocks.pid\n\n## Transparent proxy (pure tproxy)\n\nExecuting this script on the linux host can proxy all outgoing traffic of this machine (except the traffic sent to the reserved address). Other hosts under the same LAN can also change their default gateway to the ip of this linux host (at the same time change the dns server to 1.1.1.1 or 8.8.8.8, etc.) to proxy their outgoing traffic.\n\n> Of course, the ipv6 proxy is similar, just change `iptables` to `ip6tables`, `ip` to `ip -6`, `127.0.0.1` to `::1`, and other details.\n\n```shell\n#!/bin/bash\n\nstart_ssredir() {\n    # please modify MyIP, MyPort, etc.\n    (ss-redir -s MyIP -p MyPort -m MyMethod -k MyPasswd -b 127.0.0.1 -l 60080 --no-delay -u -T -v </dev/null &>>/var/log/ss-redir.log &)\n}\n\nstop_ssredir() {\n    kill -9 $(pidof ss-redir) &>/dev/null\n}\n\nstart_iptables() {\n    ##################### SSREDIR #####################\n    iptables -t mangle -N SSREDIR\n\n    # connection-mark -> packet-mark\n    iptables -t mangle -A SSREDIR -j CONNMARK --restore-mark\n    iptables -t mangle -A SSREDIR -m mark --mark 0x2333 -j RETURN\n\n    # please modify MyIP, MyPort, etc.\n    # ignore traffic sent to ss-server\n    iptables -t mangle -A SSREDIR -p tcp -d MyIP --dport MyPort -j RETURN\n    iptables -t mangle -A SSREDIR -p udp -d MyIP --dport MyPort -j RETURN\n\n    # ignore traffic sent to reserved addresses\n    iptables -t mangle -A SSREDIR -d 0.0.0.0/8          -j RETURN\n    iptables -t mangle -A SSREDIR -d 10.0.0.0/8         -j RETURN\n    iptables -t mangle -A SSREDIR -d 100.64.0.0/10      -j RETURN\n    iptables -t mangle -A SSREDIR -d 127.0.0.0/8        -j RETURN\n    iptables -t mangle -A SSREDIR -d 169.254.0.0/16     -j RETURN\n    iptables -t mangle -A SSREDIR -d 172.16.0.0/12      -j RETURN\n    iptables -t mangle -A SSREDIR -d 192.0.0.0/24       -j RETURN\n    iptables -t mangle -A SSREDIR -d 192.0.2.0/24       -j RETURN\n    iptables -t mangle -A SSREDIR -d 192.88.99.0/24     -j RETURN\n    iptables -t mangle -A SSREDIR -d 192.168.0.0/16     -j RETURN\n    iptables -t mangle -A SSREDIR -d 198.18.0.0/15      -j RETURN\n    iptables -t mangle -A SSREDIR -d 198.51.100.0/24    -j RETURN\n    iptables -t mangle -A SSREDIR -d 203.0.113.0/24     -j RETURN\n    iptables -t mangle -A SSREDIR -d 224.0.0.0/4        -j RETURN\n    iptables -t mangle -A SSREDIR -d 240.0.0.0/4        -j RETURN\n    iptables -t mangle -A SSREDIR -d 255.255.255.255/32 -j RETURN\n\n    # mark the first packet of the connection\n    iptables -t mangle -A SSREDIR -p tcp --syn                      -j MARK --set-mark 0x2333\n    iptables -t mangle -A SSREDIR -p udp -m conntrack --ctstate NEW -j MARK --set-mark 0x2333\n\n    # packet-mark -> connection-mark\n    iptables -t mangle -A SSREDIR -j CONNMARK --save-mark\n\n    ##################### OUTPUT #####################\n    # proxy the outgoing traffic from this machine\n    iptables -t mangle -A OUTPUT -p tcp -m addrtype --src-type LOCAL ! --dst-type LOCAL -j SSREDIR\n    iptables -t mangle -A OUTPUT -p udp -m addrtype --src-type LOCAL ! --dst-type LOCAL -j SSREDIR\n\n    ##################### PREROUTING #####################\n    # proxy traffic passing through this machine (other->other)\n    iptables -t mangle -A PREROUTING -p tcp -m addrtype ! --src-type LOCAL ! --dst-type LOCAL -j SSREDIR\n    iptables -t mangle -A PREROUTING -p udp -m addrtype ! --src-type LOCAL ! --dst-type LOCAL -j SSREDIR\n\n    # hand over the marked package to TPROXY for processing\n    iptables -t mangle -A PREROUTING -p tcp -m mark --mark 0x2333 -j TPROXY --on-ip 127.0.0.1 --on-port 60080\n    iptables -t mangle -A PREROUTING -p udp -m mark --mark 0x2333 -j TPROXY --on-ip 127.0.0.1 --on-port 60080\n}\n\nstop_iptables() {\n    ##################### PREROUTING #####################\n    iptables -t mangle -D PREROUTING -p tcp -m mark --mark 0x2333 -j TPROXY --on-ip 127.0.0.1 --on-port 60080 &>/dev/null\n    iptables -t mangle -D PREROUTING -p udp -m mark --mark 0x2333 -j TPROXY --on-ip 127.0.0.1 --on-port 60080 &>/dev/null\n\n    iptables -t mangle -D PREROUTING -p tcp -m addrtype ! --src-type LOCAL ! --dst-type LOCAL -j SSREDIR &>/dev/null\n    iptables -t mangle -D PREROUTING -p udp -m addrtype ! --src-type LOCAL ! --dst-type LOCAL -j SSREDIR &>/dev/null\n\n    ##################### OUTPUT #####################\n    iptables -t mangle -D OUTPUT -p tcp -m addrtype --src-type LOCAL ! --dst-type LOCAL -j SSREDIR &>/dev/null\n    iptables -t mangle -D OUTPUT -p udp -m addrtype --src-type LOCAL ! --dst-type LOCAL -j SSREDIR &>/dev/null\n\n    ##################### SSREDIR #####################\n    iptables -t mangle -F SSREDIR &>/dev/null\n    iptables -t mangle -X SSREDIR &>/dev/null\n}\n\nstart_iproute2() {\n    ip route add local default dev lo table 100\n    ip rule  add fwmark 0x2333        table 100\n}\n\nstop_iproute2() {\n    ip rule  del   table 100 &>/dev/null\n    ip route flush table 100 &>/dev/null\n}\n\nstart_resolvconf() {\n    # or nameserver 8.8.8.8, etc.\n    echo \"nameserver 1.1.1.1\" >/etc/resolv.conf\n}\n\nstop_resolvconf() {\n    echo \"nameserver 114.114.114.114\" >/etc/resolv.conf\n}\n\nstart() {\n    echo \"start ...\"\n    start_ssredir\n    start_iptables\n    start_iproute2\n    start_resolvconf\n    echo \"start end\"\n}\n\nstop() {\n    echo \"stop ...\"\n    stop_resolvconf\n    stop_iproute2\n    stop_iptables\n    stop_ssredir\n    echo \"stop end\"\n}\n\nrestart() {\n    stop\n    sleep 1\n    start\n}\n\nmain() {\n    if [ $# -eq 0 ]; then\n        echo \"usage: $0 start|stop|restart ...\"\n        return 1\n    fi\n\n    for funcname in \"$@\"; do\n        if [ \"$(type -t $funcname)\" != 'function' ]; then\n            echo \"'$funcname' not a shell function\"\n            return 1\n        fi\n    done\n\n    for funcname in \"$@\"; do\n        $funcname\n    done\n    return 0\n}\nmain \"$@\"\n```\n\n## Security Tips\n\nFor any public server, to avoid users accessing localhost of your server, please add `--acl acl/server_block_local.acl` to the command line.\n\nAlthough shadowsocks-libev can handle thousands of concurrent connections nicely, we still recommend\nsetting up your server's firewall rules to limit connections from each user:\n\n    # Up to 32 connections are enough for normal usage\n    iptables -A INPUT -p tcp --syn --dport ${SHADOWSOCKS_PORT} -m connlimit --connlimit-above 32 -j REJECT --reject-with tcp-reset\n\n## License\n\n```\nCopyright: 2013-2015, Clow Windy <clowwindy42@gmail.com>\n           2013-2018, Max Lv <max.c.lv@gmail.com>\n           2014, Linus Yang <linusyang@gmail.com>\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program. If not, see <http://www.gnu.org/licenses/>.\n```\n"
  },
  {
    "path": "README_pt_BR.md",
    "content": "# shadowsocks-libev\n\n[![Build Status](https://travis-ci.com/shadowsocks/shadowsocks-libev.svg?branch=master)](https://travis-ci.com/shadowsocks/shadowsocks-libev) [![Snap Status](https://build.snapcraft.io/badge/shadowsocks/shadowsocks-libev.svg)](https://build.snapcraft.io/user/shadowsocks/shadowsocks-libev)\n\n## Introdução\n\n[Shadowsocks-libev](https://shadowsocks.org) é um SOCKS5 leve e seguro\nproxy para dispositivos embutidos e caixas de baixo custo.\n\nÉ uma porta de [Shadowsocks](https://github.com/shadowsocks/shadowsocks)\ncriado por [@clowwindy](https://github.com/clowwindy) e mantido por\n[@madeye](https://github.com/madeye) e [@linusyang](https://github.com/linusyang).\n\nVersão atual: 3.3.6 | [Changelog](debian/changelog)\n\n## Características\n\nShadowsocks-libev é escrito em C puro e depende de [libev](http://software.schmorp.de/pkg/libev.html). Ele foi projetado para ser uma implementação leve do protocolo shadowsocks, a fim de manter o uso de recursos o mais baixo possível.\n\nPara obter uma lista completa de comparação de recursos entre diferentes versões de shadowsocks, consulte a [página da Wiki (https://github.com/shadowsocks/shadowsocks/wiki/Feature-Comparison-across-Different-Versions).\n\n## Começo rápido\n\nSnap é a maneira recomendada de instalar os binários mais recentes.\n\n### Instale o snap core\n\nhttps://snapcraft.io/core\n\n### Instalar a partir do snapcraft.io\n\nStable channel:\n\n```bash\nsudo snap install shadowsocks-libev\n```\n\nEdge channel:\n\n```bash\nsudo snap install shadowsocks-libev --edge\n```\n\n## Instalação\n\n### Guia específico de distribuição\n\n- [Debian & Ubuntu](#debian--ubuntu)\n    + [Instalar do repositório](#instale-a-partir-do-repositório-não-recomendado)\n    + [Construa o pacote deb a partir da fonte](#compile-o-pacote-deb-a-partir-da-fonte)\n    + [Configurar e iniciar o serviço](#configurar-e-iniciar-o-serviço)\n- [Fedora & RHEL](#fedora--rhel)\n     + [Construir a partir da fonte com centos](#construa-a-partir-da-fonte-com-centos)\n- [Archlinux & Manjaro](#archlinux--manjaro)\n- [NixOS](#nixos)\n- [Nix](#nix)\n- [Compile e instale diretamente no sistema semelhante ao UNIX](#linux)\n- [FreeBSD](#freebsd)\n     + [Instalar](#instalar)\n     + [Configuração](#configuração)\n     + [Executar](#executar)\n     + [Executar como cliente](#executar-como-cliente)\n- [OpenWRT](#openwrt)\n- [OS X](#os-x)\n- [Windows (MinGW)](#windows-mingw)\n- [Docker](#docker)\n\n* * *\n\n### Inicialize o ambiente de compilação\n\nEste repositório usa submódulos, então você deve puxá-los antes de começar, usando:\n\n```bash\ngit submodule update --init --recursive\n```\n\n### Guia de configuração de pré-compilação\n\nPara obter uma lista completa das opções de tempo de configuração disponíveis,\ntentar `configure --help`.\n\n### Debian & Ubuntu\n\n#### Instale a partir do repositório (não recomendado)\n\nShadowsocks-libev está disponível no repositório oficial para as seguintes distribuições:\n\n* Debian 8 ou superior, incluindo oldoldstable (jessie), old stable (stretch), stable (buster), testing (bullseye) e unstable (sid)\n* Ubuntu 16.10 ou superior\n\n```bash\nsudo apt update\nsudo apt install shadowsocks-libev\n```\n\n#### Compile o pacote deb a partir da fonte.\n\nDistribuições suportadas:\n\n* Debian 8, 9 ou superior\n* Ubuntu 14.04 LTS, 16.04 LTS, 16.10 ou superior\n\nVocê pode construir shadowsocks-libev e todas as suas dependências por script:\n\n```bash\nmkdir -p ~/build-area/\ncp ./scripts/build_deb.sh ~/build-area/\ncd ~/build-area\n./build_deb.sh\n```\n\nPara sistemas mais antigos, a construção de pacotes `.deb` não é suportada.\nPor favor, tente construir e instalar diretamente da fonte. Veja a seção [Linux](#linux) abaixo.\n\n**Nota para usuários do Debian 8 (Jessie) para construir seus próprios pacotes deb**:\n\nNós encorajamos você a instalar shadowsocks-libev de `jessie-backports-sloppy`. Se você insistir em compilar a partir da fonte, você precisará instalar manualmente o libsodium de `jessie-backports-sloppy`, **NÃO** libsodium no repositório principal.\n\nPara mais informações sobre backports, você pode consultar [Debian Backports](https://backports.debian.org).\n\n``` bash\ncd shadowsocks-libev\nsudo sh -c 'printf \"deb http://deb.debian.org/debian jessie-backports main\" > /etc/apt/sources.list.d/jessie-backports.list'\nsudo sh -c 'printf \"deb http://deb.debian.org/debian jessie-backports-sloppy main\" >> /etc/apt/sources.list.d/jessie-backports.list'\nsudo apt-get install --no-install-recommends devscripts equivs\nmk-build-deps --root-cmd sudo --install --tool \"apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends -y\"\n./autogen.sh && dpkg-buildpackage -b -us -uc\ncd ..\nsudo dpkg -i shadowsocks-libev*.deb\n```\n\n**Nota para usuários do Debian 9 (Stretch) para construir seus próprios pacotes deb**:\n\nNós encorajamos você a instalar shadowsocks-libev de `stretch-backports`. Se você insistir em compilar a partir do código-fonte, precisará instalar manualmente o libsodium de `stretch-backports`, **NÃO** libsodium no repositório principal.\n\nPara mais informações sobre backports, você pode consultar [Debian Backports](https://backports.debian.org).\n\n``` bash\ncd shadowsocks-libev\nsudo sh -c 'printf \"deb http://deb.debian.org/debian stretch-backports main\" > /etc/apt/sources.list.d/stretch-backports.list'\nsudo apt-get install --no-install-recommends devscripts equivs\nmk-build-deps --root-cmd sudo --install --tool \"apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends -y\"\n./autogen.sh && dpkg-buildpackage -b -us -uc\ncd ..\nsudo dpkg -i shadowsocks-libev*.deb\n```\n\n#### Configurar e iniciar o serviço\n\n```\n# Edite o arquivo de configuração\nsudo vim /etc/shadowsocks-libev/config.json\n\n# Edite a configuração padrão do debian\nsudo vim /etc/default/shadowsocks-libev\n\n# Inicia o serviço\nsudo /etc/init.d/shadowsocks-libev start    # para sysvinit, ou\nsudo systemctl start shadowsocks-libev      # para systemd\n```\n\n### Fedora & RHEL\n\nDistribuições suportadas:\n\n* Versões recentes do Fedora (até EOL)\n* RHEL 6, 7 e derivados (incluindo CentOS, Scientific Linux)\n\n#### Construa a partir da fonte com centos\n\nSe você estiver usando o CentOS 7, precisará instalar estes pré-requisitos para compilar a partir do código-fonte:\n\n```bash\nyum install epel-release -y\nyum install gcc gettext autoconf libtool automake make pcre-devel asciidoc xmlto c-ares-devel libev-devel libsodium-devel mbedtls-devel -y\n```\n\n### Archlinux & Manjaro\n\n```bash\nsudo pacman -S shadowsocks-libev\n```\n\nConsulte o script downstream [PKGBUILD](https://github.com/archlinux/svntogit-community/blob/packages/shadowsocks-libev/trunk/PKGBUILD) para modificações extras e bugs específicos da distribuição.\n\n### NixOS\n\n```bash\nnix-env -iA nixos.shadowsocks-libev\n```\n\n### Nix\n\n```bash\nnix-env -iA nixpkgs.shadowsocks-libev\n```\n\n### Linux\n\nEm geral, você precisa das seguintes dependências de compilação:\n\n* autotools (autoconf, automake, libtool)\n* gettext\n* pkg-config\n* libmbedtls\n* libsodium\n* libpcre3 (antiga biblioteca pcre)\n* libev\n* libc-ares\n* asciidoc (somente para documentação)\n* xmlto (apenas para documentação)\n\nNotas: Fedora 26 libsodium versão >= 1.0.12, então você pode instalar via dnf install libsodium em vez de compilar a partir da fonte.\n\nSe seu sistema for muito antigo para fornecer libmbedtls e libsodium (posterior a **v1.0.8**), você precisará instalar essas bibliotecas manualmente ou atualizar seu sistema.\n\nSe o seu sistema fornece essas bibliotecas, você **não deve** instalá-las a partir do código-fonte. Você deve ir para esta seção e instalá-las a partir do repositório de distribuição.\n\nPara algumas das distribuições, você pode instalar dependências de compilação como esta:\n\n```bash\n# Instalação de dependências básicas de compilação\n## Debian / Ubuntu\nsudo apt-get install --no-install-recommends gettext build-essential autoconf libtool libpcre3-dev asciidoc xmlto libev-dev libc-ares-dev automake libmbedtls-dev libsodium-dev pkg-config\n## CentOS / Fedora / RHEL\nsudo yum install gettext gcc autoconf libtool automake make asciidoc xmlto c-ares-devel libev-devel\n## Arch\nsudo pacman -S gettext gcc autoconf libtool automake make asciidoc xmlto c-ares libev\n\n# Instalação do libsodium\nexport LIBSODIUM_VER=1.0.16\nwget https://download.libsodium.org/libsodium/releases/old/libsodium-$LIBSODIUM_VER.tar.gz\ntar xvf libsodium-$LIBSODIUM_VER.tar.gz\npushd libsodium-$LIBSODIUM_VER\n./configure --prefix=/usr && make\nsudo make install\npopd\nsudo ldconfig\n\n# Instalação do MbedTLS\nexport MBEDTLS_VER=2.6.0\nwget https://github.com/Mbed-TLS/mbedtls/archive/refs/tags/mbedtls-$MBEDTLS_VER.tar.gz\ntar xvf mbedtls-$MBEDTLS_VER.tar.gz\npushd mbedtls-$MBEDTLS_VER\nmake SHARED=1 CFLAGS=\"-O2 -fPIC\"\nsudo make DESTDIR=/usr install\npopd\nsudo ldconfig\n\n# Comece a construir\n./autogen.sh && ./configure && make\nsudo make install\n```\n\nPode ser necessário instalar manualmente os softwares ausentes.\n\n### FreeBSD\n#### Instalar\nShadowsocks-libev está disponível na Coleção de Ports do FreeBSD. Você pode instalá-lo de qualquer maneira, `pkg` ou `ports`.\n\n**pkg (recomendado)**\n\n```bash\npkg install shadowsocks-libev\n```\n\n**portas**\n\n```bash\ncd /usr/ports/net/shadowsocks-libev\nmake install\n```\n\n#### Configuração\nEdite seu arquivo `config.json`. Por padrão, está localizado em `/usr/local/etc/shadowsocks-libev`.\n\nPara habilitar shadowsocks-libev, adicione a seguinte variável rc ao seu arquivo `/etc/rc.conf`:\n\n```\nshadowsocks_libev_enable=\"YES\"\n```\n\n#### Executar\n\nInicie o servidor Shadowsocks:\n\n```bash\nservice shadowsocks_libev start\n```\n\n#### Executar como cliente\nPor padrão, shadowsocks-libev está rodando como um servidor no FreeBSD. Se você quiser iniciar o shadowsocks-libev no modo cliente, você pode modificar o script rc (`/usr/local/etc/rc.d/shadowsocks_libev`) manualmente.\n\n```\n# modifique a seguinte linha de \"ss-server\" para \"ss-local\"\ncommand=\"/usr/local/bin/ss-local\"\n```\n\nObserve que é simplesmente uma solução alternativa, cada vez que você atualizar a porta, suas alterações serão substituídas pela nova versão.\n\n### OpenWRT\n\nO projeto OpenWRT é mantido aqui:\n[openwrt-shadowsocks](https://github.com/shadowsocks/openwrt-shadowsocks).\n\n### OS X\nPara OS X, use [Homebrew](http://brew.sh) para instalar ou compilar.\n\nInstale o Homebrew:\n\n```bash\nruby -e \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\"\n```\nInstale shadowsocks-libev:\n\n```bash\nbrew install shadowsocks-libev\n```\n\n### Windows (MinGW)\nPara compilar binários nativos do Windows, o método recomendado é usar o Docker:\n\n* No Windows: clique duas vezes em `make.bat` em `docker\\mingw`\n* No sistema do tipo Unix:\n\n        cd shadowsocks-libev/docker/mingw\n        make\n\nUm tarball com binários de 32 bits e 64 bits será gerado no mesmo diretório.\n\nVocê também pode usar compiladores MinGW-w64 manualmente para compilar em shell do tipo Unix (MSYS2/Cygwin) ou compilar em sistemas semelhantes ao Unix (Linux/MacOS). Por favor, consulte os scripts de compilação em `docker/mingw`.\n\nAtualmente você precisa usar uma biblioteca libev corrigida para MinGW:\n\n* https://github.com/shadowsocks/libev/archive/mingw.zip\n\nObserve que o TCP Fast Open (TFO) está disponível apenas no **Windows 10**, **1607** ou versão posterior (precisamente, build >= 14393). Se você estiver usando **1709** (compilação 16299) ou versão posterior, também precisará executar o seguinte comando no PowerShell/Prompt de comando **como administrador** e **reinicializar** para usar o TFO corretamente:\n\n        netsh int tcp set global fastopenfallback=disabled\n\n### Docker\n\nComo você espera, basta puxar a imagem e executar.\n```\ndocker pull shadowsocks/shadowsocks-libev\ndocker run -e PASSWORD=<password> -p<server-port>:8388 -p<server-port>:8388/udp -d shadowsocks/shadowsocks-libev\n```\n\nMais informações sobre a imagem podem ser encontradas [aqui](docker/alpine/README.md).\n\n## Utilização\n\nPara obter uma lista detalhada e completa de todos os argumentos suportados,\nvocê pode consultar as páginas de manual dos aplicativos, respectivamente.\n\n     ss-[local|redir|server|tunnel|manager]\n\n       -s <server_host>            Nome do host ou endereço IP de seu servidor remoto.\n\n       -p <server_port>            Número da porta do seu servidor remoto.\n\n       -l <local_port>             Número da porta do seu servidor local.\n\n       -k <password>               Senha do seu servidor remoto.\n\n       -m <encrypt_method>         Método de criptografia: rc4-md5,\n                                   aes-128-gcm, aes-192-gcm, aes-256-gcm,\n                                   aes-128-cfb, aes-192-cfb, aes-256-cfb,\n                                   aes-128-ctr, aes-192-ctr, aes-256-ctr,\n                                   camellia-128-cfb, camellia-192-cfb,\n                                   camellia-256-cfb, bf-cfb,\n                                   chacha20-ietf-poly1305,\n                                   xchacha20-ietf-poly1305,\n                                   salsa20, chacha20 e chacha20-ietf.\n                                   A cifra padrão é chacha20-ietf-poly1305.\n\n       [-a <user>]                 Executar como outro usuário.\n\n       [-f <pid_file>]             O caminho do arquivo para armazenar pid.\n\n       [-t <timeout>]              Tempo limite do soquete em segundos.\n\n       [-c <config_file>]          O caminho para o arquivo de configuração.\n\n       [-n <number>]               Número máximo de arquivos abertos.\n\n       [-i <interface>]            Interface de rede a ser vinculada.\n                                   (não disponível no modo redir)\n\n       [-b <local_address>]        Endereço local para ligar.\n                                   Para servidores: Especifique o endereço local a ser usado\n                                   enquanto este servidor está fazendo saída\n                                   conexões a servidores remotos em nome do\n                                   clientes.\n                                   Para clientes: Especifique o endereço local a ser usado\n                                   enquanto este cliente está fazendo saída\n                                   conexões com o servidor.\n\n       [-u]                        Habilita retransmissão UDP.\n                                   (TPROXY é necessário no modo redir)\n\n       [-U]                        Ativa a retransmissão UDP e desativa a retransmissão TCP.\n                                   (não disponível no modo local)\n\n       [-T]                        Use tproxy em vez de redirecionar. (para tcp)\n                                   (disponível apenas no modo redir)\n\n       [-L <addr>:<port>]          Endereço e porta do servidor de destino\n                                   para encaminhamento de porta local.\n                                   (disponível apenas no modo túnel)\n\n       [-6]                        Primeiro, resolva o nome do host para o endereço IPv6.\n\n       [-d <addr>]                 Servidores de nome para resolvedor de DNS interno.\n                                   (disponível apenas no modo servidor)\n\n       [--reuse-port]              Habilita a reutilização de porta.\n\n       [--fast-open]               Habilita a abertura rápida do TCP.\n                                   com kernel do Linux > 3.7.0.\n                                   (disponível apenas no modo local e servidor)\n\n       [--acl <acl_file>]          Caminho para ACL (lista de controle de acesso).\n                                   (disponível apenas no modo local e servidor)\n\n       [--manager-address <addr>]  endereço de soquete do domínio UNIX.\n                                   (disponível apenas no modo servidor e gerenciador)\n\n       [--mtu <MTU>]               MTU de sua interface de rede.\n\n       [--mptcp]                   Habilita o Multipath TCP no Kernel MPTCP.\n \n       [--no-delay]                Habilita TCP_NODELAY.\n\n       [--executable <path>]       Caminho para o executável do ss-server.\n                                   (disponível apenas no modo gerenciador)\n \n       [-D <path>]                 Caminho para o diretório de trabalho do ss-manager.\n                                   (disponível apenas no modo gerenciador)\n\n       [--key <key_in_base64>]     Chave do seu servidor remoto.\n\n## proxy transparente\n\nO mais recente shadowsocks-libev forneceu um modo *redir*. Você pode configurar sua caixa ou roteador baseado em Linux para fazer proxy de todo o tráfego TCP de forma transparente, o que é útil se você usar um roteador com OpenWRT.\n\n    # Criar nova cadeia\n    iptables -t nat -N SHADOWSOCKS\n    iptables -t mangle -N SHADOWSOCKS\n\n    # Ignore os endereços do seu servidor shadowsocks\n    # É muito IMPORTANTE, apenas tome cuidado.\n    iptables -t nat -A SHADOWSOCKS -d 123.123.123.123 -j RETURN\n\n    # Ignore LANs e quaisquer outros endereços que você gostaria de ignorar o proxy\n    # Veja Wikipedia e RFC5735 para lista completa de redes reservadas.\n    # Consulte ashi009/bestroutetb para obter uma lista de rotas CHN altamente otimizada.\n    iptables -t nat -A SHADOWSOCKS -d 0.0.0.0/8 -j RETURN\n    iptables -t nat -A SHADOWSOCKS -d 10.0.0.0/8 -j RETURN\n    iptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN\n    iptables -t nat -A SHADOWSOCKS -d 169.254.0.0/16 -j RETURN\n    iptables -t nat -A SHADOWSOCKS -d 172.16.0.0/12 -j RETURN\n    iptables -t nat -A SHADOWSOCKS -d 192.168.0.0/16 -j RETURN\n    iptables -t nat -A SHADOWSOCKS -d 224.0.0.0/4 -j RETURN\n    iptables -t nat -A SHADOWSOCKS -d 240.0.0.0/4 -j RETURN\n\n    # Qualquer outra coisa deve ser redirecionada para a porta local do shadowsocks\n    iptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports 12345\n\n    # Adicione quaisquer regras UDP\n    ip route add local default dev lo table 100\n    ip rule add fwmark 1 lookup 100\n    iptables -t mangle -A SHADOWSOCKS -p udp --dport 53 -j TPROXY --on-port 12345 --tproxy-mark 0x01/0x01\n\n    # Aplicar as regras\n    iptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS\n    iptables -t mangle -A PREROUTING -j SHADOWSOCKS\n\n    # Iniciar o shadowsocks-redir\n    ss-redir -u -c /etc/config/shadowsocks.json -f /var/run/shadowsocks.pid\n\n## Proxy transparente (tproxy puro)\n\nA execução deste script no host linux pode fazer proxy de todo o tráfego de saída desta máquina (exceto o tráfego enviado para o endereço reservado). Outros hosts na mesma LAN também podem alterar seu gateway padrão para o ip deste host linux (ao mesmo tempo, alterar o servidor dns para 1.1.1.1 ou 8.8.8.8, etc.) para fazer proxy de seu tráfego de saída.\n\n> Claro, o proxy ipv6 é semelhante, basta alterar `iptables` para `ip6tables`, `ip` para `ip -6`, `127.0.0.1` para `::1`, e outros detalhes.\n\n```shell\n#!/bin/bash\n\nstart_ssredir() {\n    # modifique MyIP, MyPort, etc.\n    (ss-redir -s MyIP -p MyPort -m MyMethod -k MyPasswd -b 127.0.0.1 -l 60080 --no-delay -u -T -v </dev/null &>>/var/log/ss-redir.log &)\n}\n\nstop_ssredir() {\n    kill -9 $(pidof ss-redir) &>/dev/null\n}\n\nstart_iptables() {\n    ##################### SSREDIR #####################\n    iptables -t mangle -N SSREDIR\n\n    # connection-mark -> packet-mark\n    iptables -t mangle -A SSREDIR -j CONNMARK --restore-mark\n    iptables -t mangle -A SSREDIR -m mark --mark 0x2333 -j RETURN\n\n    # modifique MyIP, MyPort, etc.\n    # ignorar o tráfego enviado para o servidor ss\n    iptables -t mangle -A SSREDIR -p tcp -d MyIP --dport MyPort -j RETURN\n    iptables -t mangle -A SSREDIR -p udp -d MyIP --dport MyPort -j RETURN\n\n    # ignorar o tráfego enviado para endereços reservados\n    iptables -t mangle -A SSREDIR -d 0.0.0.0/8          -j RETURN\n    iptables -t mangle -A SSREDIR -d 10.0.0.0/8         -j RETURN\n    iptables -t mangle -A SSREDIR -d 100.64.0.0/10      -j RETURN\n    iptables -t mangle -A SSREDIR -d 127.0.0.0/8        -j RETURN\n    iptables -t mangle -A SSREDIR -d 169.254.0.0/16     -j RETURN\n    iptables -t mangle -A SSREDIR -d 172.16.0.0/12      -j RETURN\n    iptables -t mangle -A SSREDIR -d 192.0.0.0/24       -j RETURN\n    iptables -t mangle -A SSREDIR -d 192.0.2.0/24       -j RETURN\n    iptables -t mangle -A SSREDIR -d 192.88.99.0/24     -j RETURN\n    iptables -t mangle -A SSREDIR -d 192.168.0.0/16     -j RETURN\n    iptables -t mangle -A SSREDIR -d 198.18.0.0/15      -j RETURN\n    iptables -t mangle -A SSREDIR -d 198.51.100.0/24    -j RETURN\n    iptables -t mangle -A SSREDIR -d 203.0.113.0/24     -j RETURN\n    iptables -t mangle -A SSREDIR -d 224.0.0.0/4        -j RETURN\n    iptables -t mangle -A SSREDIR -d 240.0.0.0/4        -j RETURN\n    iptables -t mangle -A SSREDIR -d 255.255.255.255/32 -j RETURN\n\n    # marca o primeiro pacote da conexão\n    iptables -t mangle -A SSREDIR -p tcp --syn                      -j MARK --set-mark 0x2333\n    iptables -t mangle -A SSREDIR -p udp -m conntrack --ctstate NEW -j MARK --set-mark 0x2333\n\n    # packet-mark -> connection-mark\n    iptables -t mangle -A SSREDIR -j CONNMARK --save-mark\n\n    ##################### OUTPUT #####################\n    # proxy the outgoing traffic from this machine\n    iptables -t mangle -A OUTPUT -p tcp -m addrtype --src-type LOCAL ! --dst-type LOCAL -j SSREDIR\n    iptables -t mangle -A OUTPUT -p udp -m addrtype --src-type LOCAL ! --dst-type LOCAL -j SSREDIR\n\n    ##################### PREROUTING #####################\n    # proxy traffic passing through this machine (other->other)\n    iptables -t mangle -A PREROUTING -p tcp -m addrtype ! --src-type LOCAL ! --dst-type LOCAL -j SSREDIR\n    iptables -t mangle -A PREROUTING -p udp -m addrtype ! --src-type LOCAL ! --dst-type LOCAL -j SSREDIR\n\n    # hand over the marked package to TPROXY for processing\n    iptables -t mangle -A PREROUTING -p tcp -m mark --mark 0x2333 -j TPROXY --on-ip 127.0.0.1 --on-port 60080\n    iptables -t mangle -A PREROUTING -p udp -m mark --mark 0x2333 -j TPROXY --on-ip 127.0.0.1 --on-port 60080\n}\n\nstop_iptables() {\n    ##################### PREROUTING #####################\n    iptables -t mangle -D PREROUTING -p tcp -m mark --mark 0x2333 -j TPROXY --on-ip 127.0.0.1 --on-port 60080 &>/dev/null\n    iptables -t mangle -D PREROUTING -p udp -m mark --mark 0x2333 -j TPROXY --on-ip 127.0.0.1 --on-port 60080 &>/dev/null\n\n    iptables -t mangle -D PREROUTING -p tcp -m addrtype ! --src-type LOCAL ! --dst-type LOCAL -j SSREDIR &>/dev/null\n    iptables -t mangle -D PREROUTING -p udp -m addrtype ! --src-type LOCAL ! --dst-type LOCAL -j SSREDIR &>/dev/null\n\n    ##################### OUTPUT #####################\n    iptables -t mangle -D OUTPUT -p tcp -m addrtype --src-type LOCAL ! --dst-type LOCAL -j SSREDIR &>/dev/null\n    iptables -t mangle -D OUTPUT -p udp -m addrtype --src-type LOCAL ! --dst-type LOCAL -j SSREDIR &>/dev/null\n\n    ##################### SSREDIR #####################\n    iptables -t mangle -F SSREDIR &>/dev/null\n    iptables -t mangle -X SSREDIR &>/dev/null\n}\n\nstart_iproute2() {\n    ip route add local default dev lo table 100\n    ip rule  add fwmark 0x2333        table 100\n}\n\nstop_iproute2() {\n    ip rule  del   table 100 &>/dev/null\n    ip route flush table 100 &>/dev/null\n}\n\nstart_resolvconf() {\n    # or nameserver 8.8.8.8, etc.\n    echo \"nameserver 1.1.1.1\" >/etc/resolv.conf\n}\n\nstop_resolvconf() {\n    echo \"nameserver 114.114.114.114\" >/etc/resolv.conf\n}\n\nstart() {\n    echo \"start ...\"\n    start_ssredir\n    start_iptables\n    start_iproute2\n    start_resolvconf\n    echo \"start end\"\n}\n\nstop() {\n    echo \"stop ...\"\n    stop_resolvconf\n    stop_iproute2\n    stop_iptables\n    stop_ssredir\n    echo \"stop end\"\n}\n\nrestart() {\n    stop\n    sleep 1\n    start\n}\n\nmain() {\n    if [ $# -eq 0 ]; then\n        echo \"usage: $0 start|stop|restart ...\"\n        return 1\n    fi\n\n    for funcname in \"$@\"; do\n        if [ \"$(type -t $funcname)\" != 'function' ]; then\n            echo \"'$funcname' not a shell function\"\n            return 1\n        fi\n    done\n\n    for funcname in \"$@\"; do\n        $funcname\n    done\n    return 0\n}\nmain \"$@\"\n```\n\n## Dicas de segurança\n\nPara qualquer servidor público, para evitar que os usuários acessem o localhost do seu servidor, adicione `--acl acl/server_block_local.acl` à linha de comando.\n\nEmbora shadowsocks-libev possa lidar bem com milhares de conexões simultâneas, ainda recomendamos\nconfigurando as regras de firewall do seu servidor para limitar as conexões de cada usuário:\n\n    # Até 32 conexões são suficientes para uso normal\n    iptables -A INPUT -p tcp --syn --dport ${SHADOWSOCKS_PORT} -m connlimit --connlimit-above 32 -j REJECT --reject-with tcp-reset\n\n## Licença\n\n```\nCopyright: 2013-2015, Clow Windy <clowwindy42@gmail.com>\n           2013-2018, Max Lv <max.c.lv@gmail.com>\n           2014, Linus Yang <linusyang@gmail.com>\n\nEste programa é um software livre: você pode redistribuí-lo \ne/ou modificá-lo sob os termos da GNU General Public License \nconforme publicada pela Free Software Foundation, a versão 3\nda Licença ou (a seu critério) qualquer versão posterior.\n\nEste programa é distribuído na esperança de que seja útil,\n mas SEM QUALQUER GARANTIA; sem mesmo a garantia implícita \nde COMERCIALIZAÇÃO ou ADEQUAÇÃO A UM DETERMINADO FIM.Veja\na Licença Pública Geral GNU para mais detalhes.\n\nVocê deve ter recebido uma cópia da GNU General Public License \njuntamente com este programa. Caso contrário, \nconsulte <http://www.gnu.org/licenses/>.\n```\n"
  },
  {
    "path": "acl/chn.acl",
    "content": "[proxy_all]\n\n[bypass_list]\n1.0.1.0/24\n1.0.2.0/23\n1.0.8.0/21\n1.0.32.0/19\n1.1.0.0/24\n1.1.2.0/23\n1.1.4.0/22\n1.1.8.0/21\n1.1.16.0/20\n1.1.32.0/19\n1.2.0.0/23\n1.2.2.0/24\n1.2.5.0/24\n1.2.6.0/23\n1.2.8.0/21\n1.2.16.0/20\n1.2.32.0/19\n1.2.64.0/18\n1.3.0.0/16\n1.4.1.0/24\n1.4.2.0/23\n1.4.4.0/22\n1.4.8.0/21\n1.4.16.0/20\n1.4.32.0/19\n1.4.64.0/18\n1.8.0.0/18\n1.8.64.0/19\n1.8.96.0/22\n1.8.100.0/23\n1.8.112.0/20\n1.8.128.0/20\n1.8.144.0/22\n1.8.148.0/23\n1.8.154.0/23\n1.8.156.0/22\n1.8.160.0/19\n1.8.192.0/19\n1.8.224.0/20\n1.8.244.0/22\n1.8.248.0/21\n1.10.0.0/21\n1.10.8.0/23\n1.10.11.0/24\n1.10.12.0/22\n1.10.16.0/20\n1.10.32.0/19\n1.10.64.0/18\n1.12.0.0/14\n1.18.128.0/24\n1.24.0.0/13\n1.45.0.0/16\n1.48.0.0/14\n1.56.0.0/13\n1.68.0.0/14\n1.80.0.0/12\n1.116.0.0/15\n1.118.1.0/24\n1.118.2.0/23\n1.118.4.0/22\n1.118.8.0/21\n1.118.16.0/20\n1.118.32.0/19\n1.118.64.0/18\n1.118.128.0/17\n1.119.0.0/16\n1.180.0.0/14\n1.184.0.0/15\n1.188.0.0/14\n1.192.0.0/13\n1.202.0.0/15\n1.204.0.0/14\n2.20.54.23/32\n8.128.0.0/10\n8.209.36.0/22\n8.209.40.0/21\n8.209.48.0/20\n8.209.192.0/18\n8.210.0.0/15\n8.212.0.0/14\n8.216.0.0/13\n14.0.0.0/21\n14.0.12.0/22\n14.1.0.0/22\n14.1.24.0/22\n14.1.108.0/22\n14.16.0.0/12\n14.102.128.0/22\n14.102.180.0/22\n14.103.0.0/16\n14.104.0.0/13\n14.112.0.0/12\n14.130.0.0/15\n14.134.0.0/15\n14.144.0.0/12\n14.192.60.0/22\n14.192.76.0/22\n14.196.0.0/15\n14.204.0.0/15\n14.208.0.0/12\n20.81.0.0/24\n20.134.160.0/20\n20.139.160.0/20\n20.249.255.0/24\n20.251.0.0/22\n23.236.64.0/25\n23.236.64.128/26\n23.236.64.192/27\n27.0.128.0/21\n27.0.160.0/21\n27.0.188.0/22\n27.0.204.0/22\n27.0.208.0/21\n27.8.0.0/13\n27.16.0.0/12\n27.34.232.0/21\n27.36.0.0/14\n27.40.0.0/13\n27.50.40.0/21\n27.50.128.0/17\n27.54.72.0/21\n27.54.152.0/21\n27.54.192.0/18\n27.98.208.0/20\n27.98.224.0/19\n27.99.128.0/17\n27.103.0.0/16\n27.106.128.0/18\n27.106.204.0/22\n27.109.32.0/19\n27.109.124.0/22\n27.112.0.0/18\n27.112.80.0/20\n27.112.112.0/21\n27.113.128.0/18\n27.115.0.0/17\n27.116.44.0/22\n27.121.72.0/21\n27.121.120.0/21\n27.128.0.0/15\n27.131.220.0/22\n27.144.0.0/16\n27.148.0.0/14\n27.152.0.0/13\n27.184.0.0/13\n27.192.0.0/11\n27.224.0.0/14\n36.0.0.0/22\n36.0.16.0/20\n36.0.32.0/19\n36.0.64.0/18\n36.0.128.0/17\n36.1.0.0/16\n36.4.0.0/14\n36.16.0.0/12\n36.32.0.0/14\n36.36.0.0/16\n36.37.0.0/19\n36.37.36.0/23\n36.37.39.0/24\n36.37.40.0/21\n36.37.48.0/20\n36.40.0.0/13\n36.48.0.0/15\n36.51.0.0/17\n36.51.128.0/18\n36.51.192.0/19\n36.51.224.0/20\n36.51.240.0/21\n36.51.248.0/22\n36.51.252.0/23\n36.56.0.0/13\n36.96.0.0/11\n36.128.0.0/10\n36.192.0.0/11\n36.248.0.0/14\n36.254.0.0/16\n36.255.116.0/22\n36.255.128.0/22\n36.255.164.0/22\n36.255.172.0/22\n36.255.176.0/22\n38.142.239.114/32\n39.0.0.0/24\n39.0.2.0/23\n39.0.4.0/22\n39.0.8.0/21\n39.0.16.0/20\n39.0.32.0/19\n39.0.64.0/18\n39.0.128.0/17\n39.64.0.0/11\n39.96.0.0/13\n39.104.0.0/14\n39.108.0.0/16\n39.109.120.0/23\n39.128.0.0/10\n40.0.176.0/20\n40.0.247.0/24\n40.0.248.0/22\n40.0.252.0/23\n40.0.255.0/24\n40.72.0.0/15\n40.77.136.112/28\n40.77.236.224/27\n40.77.254.64/27\n40.125.128.0/17\n40.126.64.0/18\n40.198.10.0/24\n40.198.16.0/21\n40.198.24.0/23\n40.251.225.0/24\n40.251.227.0/24\n42.0.0.0/22\n42.0.8.0/21\n42.0.16.0/21\n42.0.24.0/22\n42.0.32.0/19\n42.0.128.0/17\n42.1.0.0/19\n42.1.32.0/20\n42.1.48.0/21\n42.1.56.0/22\n42.4.0.0/14\n42.48.0.0/13\n42.56.0.0/14\n42.62.0.0/17\n42.62.128.0/19\n42.62.160.0/20\n42.62.180.0/22\n42.62.184.0/21\n42.63.0.0/16\n42.80.0.0/15\n42.83.64.0/20\n42.83.80.0/22\n42.83.88.0/21\n42.83.96.0/19\n42.83.128.0/23\n42.83.134.0/24\n42.83.139.0/24\n42.83.140.0/22\n42.83.144.0/20\n42.83.160.0/19\n42.83.192.0/18\n42.84.0.0/14\n42.88.0.0/13\n42.96.64.0/19\n42.96.96.0/21\n42.96.108.0/22\n42.96.112.0/20\n42.96.128.0/17\n42.97.0.0/16\n42.99.0.0/18\n42.99.64.0/19\n42.99.96.0/20\n42.99.112.0/22\n42.99.120.0/21\n42.100.0.0/14\n42.120.0.0/15\n42.122.0.0/16\n42.123.0.0/19\n42.123.36.0/22\n42.123.40.0/21\n42.123.48.0/20\n42.123.64.0/18\n42.123.128.0/17\n42.128.0.0/12\n42.156.0.0/19\n42.156.36.0/22\n42.156.40.0/21\n42.156.48.0/20\n42.156.64.0/18\n42.156.128.0/17\n42.157.0.0/21\n42.157.8.0/22\n42.157.14.0/23\n42.157.16.0/20\n42.157.32.0/19\n42.157.64.0/18\n42.157.128.0/17\n42.158.0.0/15\n42.160.0.0/12\n42.176.0.0/13\n42.184.0.0/15\n42.186.0.0/16\n42.187.0.0/18\n42.187.64.0/19\n42.187.96.0/20\n42.187.112.0/21\n42.187.120.0/22\n42.187.128.0/17\n42.192.0.0/13\n42.201.0.0/17\n42.202.0.0/15\n42.204.0.0/14\n42.208.0.0/12\n42.224.0.0/12\n42.240.0.0/16\n42.242.0.0/15\n42.244.0.0/15\n42.246.0.0/16\n42.247.0.0/22\n42.247.4.0/24\n42.247.5.0/25\n42.247.5.128/26\n42.247.5.204/30\n42.247.5.208/28\n42.247.5.224/27\n42.247.6.0/23\n42.247.8.0/21\n42.247.16.0/20\n42.247.32.0/19\n42.247.64.0/18\n42.247.128.0/17\n42.248.0.0/13\n43.224.12.0/22\n43.224.24.0/22\n43.224.44.0/22\n43.224.52.0/22\n43.224.56.0/22\n43.224.68.0/22\n43.224.72.0/22\n43.224.80.0/22\n43.224.100.0/22\n43.224.144.0/22\n43.224.160.0/22\n43.224.176.0/22\n43.224.184.0/22\n43.224.200.0/21\n43.224.208.0/21\n43.224.216.0/22\n43.224.240.0/22\n43.225.76.0/22\n43.225.86.0/24\n43.225.120.0/22\n43.225.180.0/22\n43.225.208.0/22\n43.225.216.0/21\n43.225.224.0/20\n43.225.240.0/21\n43.225.252.0/22\n43.226.32.0/19\n43.226.64.0/19\n43.226.96.0/20\n43.226.112.0/21\n43.226.120.0/22\n43.226.128.0/19\n43.226.160.0/21\n43.226.236.0/22\n43.226.240.0/20\n43.227.0.0/21\n43.227.8.0/22\n43.227.32.0/19\n43.227.64.0/19\n43.227.104.0/22\n43.227.136.0/21\n43.227.144.0/22\n43.227.152.0/21\n43.227.160.0/20\n43.227.176.0/21\n43.227.188.0/22\n43.227.192.0/19\n43.227.232.0/22\n43.227.248.0/21\n43.228.0.0/18\n43.228.64.0/21\n43.228.76.0/22\n43.228.100.0/22\n43.228.116.0/24\n43.228.118.0/23\n43.228.132.0/22\n43.228.136.0/22\n43.228.148.0/22\n43.228.152.0/22\n43.228.188.0/22\n43.229.40.0/22\n43.229.48.0/22\n43.229.56.0/22\n43.229.96.0/22\n43.229.136.0/21\n43.229.168.0/21\n43.229.176.0/20\n43.229.192.0/21\n43.229.216.0/21\n43.229.232.0/21\n43.230.20.0/22\n43.230.32.0/22\n43.230.68.0/22\n43.230.72.0/22\n43.230.84.0/22\n43.230.124.0/22\n43.230.220.0/22\n43.230.224.0/19\n43.231.12.0/22\n43.231.32.0/20\n43.231.80.0/20\n43.231.96.0/20\n43.231.136.0/21\n43.231.144.0/20\n43.231.160.0/20\n43.231.176.0/21\n43.236.0.0/15\n43.238.0.0/16\n43.239.0.0/19\n43.239.32.0/20\n43.239.48.0/22\n43.239.116.0/22\n43.239.120.0/22\n43.239.172.0/22\n43.240.0.0/22\n43.240.56.0/21\n43.240.68.0/22\n43.240.72.0/21\n43.240.84.0/22\n43.240.124.0/22\n43.240.128.0/21\n43.240.136.0/22\n43.240.156.0/22\n43.240.160.0/19\n43.240.192.0/19\n43.240.240.0/20\n43.241.0.0/20\n43.241.16.0/21\n43.241.48.0/22\n43.241.76.0/22\n43.241.80.0/20\n43.241.112.0/22\n43.241.168.0/21\n43.241.176.0/21\n43.241.184.0/22\n43.241.208.0/20\n43.241.224.0/20\n43.241.240.0/22\n43.241.248.0/22\n43.242.8.0/21\n43.242.16.0/20\n43.242.48.0/22\n43.242.53.0/24\n43.242.54.0/23\n43.242.56.0/21\n43.242.64.0/22\n43.242.72.0/21\n43.242.80.0/20\n43.242.96.0/22\n43.242.144.0/20\n43.242.160.0/21\n43.242.180.0/22\n43.242.188.0/22\n43.242.192.0/21\n43.242.204.0/22\n43.242.216.0/21\n43.242.252.0/22\n43.243.4.0/22\n43.243.8.0/21\n43.243.16.0/22\n43.243.88.0/22\n43.243.128.0/22\n43.243.136.0/22\n43.243.144.0/21\n43.243.156.0/22\n43.243.180.0/22\n43.243.228.0/22\n43.243.232.0/22\n43.243.244.0/22\n43.246.0.0/18\n43.246.64.0/19\n43.246.96.0/22\n43.246.228.0/22\n43.247.4.0/22\n43.247.8.0/22\n43.247.44.0/22\n43.247.48.0/22\n43.247.68.0/22\n43.247.76.0/22\n43.247.84.0/22\n43.247.88.0/21\n43.247.96.0/21\n43.247.108.0/22\n43.247.112.0/22\n43.247.148.0/22\n43.247.152.0/22\n43.247.176.0/20\n43.247.196.0/22\n43.247.200.0/21\n43.247.208.0/20\n43.247.224.0/19\n43.248.0.0/21\n43.248.20.0/22\n43.248.28.0/22\n43.248.48.0/22\n43.248.76.0/22\n43.248.80.0/20\n43.248.96.0/19\n43.248.128.0/20\n43.248.144.0/21\n43.248.176.0/20\n43.248.192.0/20\n43.248.208.0/22\n43.248.228.0/22\n43.248.232.0/22\n43.248.244.0/22\n43.249.4.0/22\n43.249.120.0/22\n43.249.132.0/22\n43.249.136.0/22\n43.249.144.0/20\n43.249.160.0/21\n43.249.168.0/22\n43.249.192.0/22\n43.249.236.0/22\n43.250.4.0/22\n43.250.12.0/22\n43.250.16.0/21\n43.250.28.0/22\n43.250.32.0/22\n43.250.96.0/21\n43.250.108.0/22\n43.250.112.0/21\n43.250.128.0/22\n43.250.144.0/21\n43.250.160.0/22\n43.250.168.0/22\n43.250.176.0/22\n43.250.200.0/22\n43.250.212.0/22\n43.250.216.0/21\n43.250.236.0/22\n43.250.244.0/22\n43.251.4.0/22\n43.251.36.0/22\n43.251.192.0/22\n43.251.232.0/22\n43.251.244.0/22\n43.252.48.0/22\n43.252.56.0/22\n43.252.224.0/22\n43.254.0.0/21\n43.254.8.0/22\n43.254.24.0/22\n43.254.36.0/22\n43.254.44.0/22\n43.254.52.0/22\n43.254.64.0/22\n43.254.72.0/22\n43.254.84.0/22\n43.254.88.0/21\n43.254.100.0/22\n43.254.104.0/22\n43.254.112.0/21\n43.254.128.0/22\n43.254.136.0/21\n43.254.144.0/20\n43.254.168.0/21\n43.254.180.0/22\n43.254.184.0/21\n43.254.192.0/22\n43.254.200.0/22\n43.254.208.0/22\n43.254.220.0/22\n43.254.224.0/20\n43.254.240.0/22\n43.254.248.0/21\n43.255.0.0/21\n43.255.8.0/22\n43.255.16.0/22\n43.255.48.0/22\n43.255.64.0/20\n43.255.84.0/22\n43.255.96.0/22\n43.255.144.0/22\n43.255.176.0/22\n43.255.184.0/22\n43.255.192.0/22\n43.255.200.0/21\n43.255.208.0/21\n43.255.224.0/21\n43.255.232.0/22\n43.255.244.0/22\n45.40.192.0/20\n45.40.208.0/21\n45.40.224.0/19\n45.65.16.0/20\n45.112.132.0/22\n45.112.188.0/22\n45.112.208.0/22\n45.112.216.0/21\n45.112.228.0/22\n45.112.232.0/21\n45.113.12.0/22\n45.113.16.0/20\n45.113.40.0/22\n45.113.52.0/22\n45.113.72.0/22\n45.113.144.0/21\n45.113.168.0/22\n45.113.184.0/22\n45.113.200.0/21\n45.113.208.0/20\n45.113.240.0/22\n45.113.252.0/22\n45.114.0.0/22\n45.114.32.0/22\n45.114.52.0/22\n45.114.96.0/22\n45.114.136.0/22\n45.114.196.0/22\n45.114.200.0/22\n45.114.228.0/22\n45.114.237.0/24\n45.114.238.0/23\n45.114.252.0/22\n45.115.44.0/22\n45.115.100.0/22\n45.115.120.0/22\n45.115.132.0/22\n45.115.144.0/22\n45.115.156.0/22\n45.115.164.0/22\n45.115.200.0/22\n45.115.212.0/22\n45.115.244.0/22\n45.115.248.0/22\n45.116.16.0/22\n45.116.24.0/22\n45.116.32.0/21\n45.116.52.0/22\n45.116.96.0/21\n45.116.140.0/22\n45.116.152.0/22\n45.116.208.0/22\n45.117.8.0/22\n45.117.20.0/22\n45.117.68.0/22\n45.117.124.0/22\n45.117.252.0/22\n45.119.60.0/22\n45.119.64.0/21\n45.119.72.0/22\n45.119.104.0/22\n45.119.232.0/22\n45.120.100.0/22\n45.120.140.0/22\n45.120.164.0/22\n45.120.180.128/27\n45.120.240.0/22\n45.121.52.0/22\n45.121.64.0/21\n45.121.72.0/22\n45.121.92.0/22\n45.121.96.0/22\n45.121.172.0/22\n45.121.176.0/22\n45.121.240.0/20\n45.122.0.0/19\n45.122.32.0/21\n45.122.40.0/22\n45.122.60.0/22\n45.122.64.0/19\n45.122.96.0/20\n45.122.112.0/21\n45.122.160.0/19\n45.122.192.0/20\n45.122.208.0/21\n45.122.216.0/22\n45.123.28.0/22\n45.123.32.0/21\n45.123.44.0/22\n45.123.48.0/20\n45.123.64.0/20\n45.123.80.0/21\n45.123.120.0/22\n45.123.128.0/21\n45.123.136.0/22\n45.123.148.0/22\n45.123.152.0/21\n45.123.164.0/22\n45.123.168.0/21\n45.123.176.0/21\n45.123.184.0/22\n45.123.204.0/22\n45.123.212.0/22\n45.123.224.0/19\n45.124.0.0/22\n45.124.20.0/22\n45.124.28.0/22\n45.124.32.0/21\n45.124.44.0/22\n45.124.68.0/22\n45.124.76.0/22\n45.124.80.0/22\n45.124.100.0/22\n45.124.124.0/22\n45.124.172.0/22\n45.124.176.0/22\n45.124.208.0/22\n45.124.248.0/22\n45.125.24.0/22\n45.125.44.0/22\n45.125.52.0/22\n45.125.56.0/22\n45.125.76.0/22\n45.125.80.0/20\n45.125.96.0/21\n45.125.136.0/22\n45.126.48.0/21\n45.126.108.0/22\n45.126.112.0/21\n45.126.120.0/22\n45.126.220.0/22\n45.127.8.0/21\n45.127.128.0/22\n45.127.144.0/21\n45.127.156.0/22\n45.248.8.0/22\n45.248.80.0/22\n45.248.88.0/22\n45.248.96.0/20\n45.248.128.0/21\n45.248.204.0/22\n45.248.208.0/20\n45.248.224.0/19\n45.249.0.0/21\n45.249.12.0/22\n45.249.16.0/20\n45.249.32.0/21\n45.249.112.0/22\n45.249.188.0/22\n45.249.192.0/20\n45.249.208.0/21\n45.250.12.0/22\n45.250.16.0/22\n45.250.28.0/22\n45.250.32.0/21\n45.250.40.0/22\n45.250.76.0/22\n45.250.80.0/20\n45.250.96.0/22\n45.250.104.0/21\n45.250.112.0/20\n45.250.128.0/20\n45.250.144.0/21\n45.250.152.0/22\n45.250.164.0/22\n45.250.180.0/22\n45.250.184.0/21\n45.250.192.0/22\n45.251.0.0/22\n45.251.8.0/22\n45.251.16.0/21\n45.251.52.0/22\n45.251.84.0/22\n45.251.88.0/21\n45.251.96.0/21\n45.251.120.0/21\n45.251.137.0/24\n45.251.138.0/23\n45.251.140.0/22\n45.251.144.0/20\n45.251.160.0/19\n45.251.192.0/19\n45.251.224.0/22\n45.252.0.0/19\n45.252.32.0/20\n45.252.48.0/22\n45.252.84.0/22\n45.252.88.0/21\n45.252.96.0/19\n45.252.128.0/19\n45.252.160.0/20\n45.252.176.0/22\n45.252.192.0/19\n45.252.224.0/21\n45.252.232.0/22\n45.253.0.0/18\n45.253.64.0/20\n45.253.80.0/21\n45.253.92.0/22\n45.253.96.0/20\n45.253.112.0/21\n45.253.120.0/22\n45.253.130.0/23\n45.253.132.0/22\n45.253.136.0/21\n45.253.144.0/20\n45.253.160.0/19\n45.253.192.0/19\n45.253.224.0/20\n45.253.240.0/22\n45.254.0.0/20\n45.254.16.0/21\n45.254.28.0/22\n45.254.40.0/22\n45.254.48.0/20\n45.254.64.0/18\n45.254.128.0/18\n45.254.192.0/19\n45.254.224.0/21\n45.254.236.0/22\n45.254.240.0/22\n45.254.248.0/22\n45.255.0.0/18\n45.255.64.0/19\n45.255.96.0/20\n45.255.112.0/21\n45.255.120.0/22\n45.255.136.0/21\n45.255.144.0/20\n45.255.160.0/19\n45.255.192.0/19\n45.255.224.0/20\n45.255.240.0/21\n45.255.248.0/22\n46.248.24.0/23\n47.92.0.0/14\n47.96.0.0/11\n49.4.0.0/14\n49.51.56.0/22\n49.51.60.0/23\n49.51.110.0/23\n49.51.112.0/20\n49.52.0.0/14\n49.64.0.0/11\n49.112.0.0/13\n49.120.0.0/14\n49.128.0.0/24\n49.128.2.0/23\n49.128.4.0/22\n49.140.0.0/15\n49.152.0.0/14\n49.208.0.0/14\n49.220.0.0/14\n49.232.0.0/14\n49.239.0.0/18\n49.239.192.0/18\n52.80.0.0/14\n52.94.249.0/27\n52.130.0.0/15\n54.222.0.0/15\n54.231.208.0/20\n54.240.224.0/24\n57.92.96.0/20\n58.14.0.0/15\n58.16.0.0/13\n58.24.0.0/15\n58.30.0.0/15\n58.32.0.0/11\n58.65.232.0/21\n58.66.0.0/15\n58.68.128.0/19\n58.68.160.0/23\n58.68.163.0/24\n58.68.164.0/22\n58.68.179.0/24\n58.68.180.0/24\n58.68.200.0/21\n58.68.208.0/20\n58.68.224.0/19\n58.82.0.0/17\n58.83.0.0/16\n58.87.64.0/18\n58.99.128.0/17\n58.100.0.0/15\n58.116.0.0/14\n58.128.0.0/13\n58.144.0.0/16\n58.154.0.0/15\n58.192.0.0/11\n58.240.0.0/12\n59.32.0.0/11\n59.64.0.0/12\n59.80.0.0/15\n59.82.0.0/16\n59.83.0.0/18\n59.83.132.0/22\n59.83.136.0/21\n59.83.144.0/20\n59.83.160.0/19\n59.83.192.0/19\n59.83.224.0/20\n59.83.240.0/21\n59.83.248.0/22\n59.83.252.0/23\n59.83.254.0/24\n59.107.0.0/16\n59.108.0.0/14\n59.151.0.0/17\n59.152.16.0/20\n59.152.36.0/22\n59.152.64.0/20\n59.152.112.0/21\n59.153.4.0/22\n59.153.32.0/22\n59.153.64.0/21\n59.153.72.0/22\n59.153.92.0/22\n59.153.136.0/22\n59.153.152.0/21\n59.153.164.0/22\n59.153.168.0/21\n59.153.176.0/20\n59.153.192.0/22\n59.155.0.0/16\n59.172.0.0/14\n59.191.0.0/17\n59.192.0.0/10\n60.0.0.0/11\n60.55.0.0/16\n60.63.0.0/16\n60.160.0.0/11\n60.194.0.0/15\n60.200.0.0/13\n60.208.0.0/12\n60.232.0.0/15\n60.235.0.0/16\n60.245.128.0/17\n60.247.0.0/16\n60.252.0.0/16\n60.253.128.0/17\n60.255.0.0/16\n61.4.81.0/24\n61.4.82.0/23\n61.4.84.0/22\n61.4.88.0/21\n61.4.176.0/20\n61.8.160.0/20\n61.14.212.0/22\n61.14.216.0/21\n61.14.240.0/21\n61.28.0.0/17\n61.29.128.0/18\n61.29.192.0/19\n61.29.224.0/20\n61.45.128.0/18\n61.45.224.0/20\n61.47.128.0/18\n61.48.0.0/13\n61.87.192.0/18\n61.128.0.0/10\n61.232.0.0/14\n61.236.0.0/15\n61.240.0.0/14\n62.234.0.0/16\n68.79.0.0/18\n69.230.192.0/18\n69.231.128.0/18\n69.234.192.0/18\n69.235.128.0/18\n71.131.192.0/18\n71.132.0.0/18\n71.136.64.0/18\n71.137.0.0/18\n72.163.240.0/23\n72.163.248.0/22\n81.68.0.0/14\n81.161.63.0/24\n82.156.0.0/15\n87.254.207.0/24\n91.223.53.0/24\n91.239.190.0/24\n93.183.14.0/24\n93.183.18.0/24\n94.191.0.0/17\n101.0.0.0/22\n101.1.0.0/22\n101.2.172.0/22\n101.4.0.0/14\n101.16.0.0/12\n101.32.0.0/14\n101.36.0.0/18\n101.36.64.0/20\n101.36.88.0/21\n101.36.96.0/19\n101.36.128.0/17\n101.37.0.0/16\n101.38.0.0/15\n101.40.0.0/13\n101.48.0.0/15\n101.50.8.0/21\n101.50.56.0/22\n101.52.0.0/16\n101.53.100.0/22\n101.54.0.0/16\n101.55.224.0/21\n101.64.0.0/13\n101.72.0.0/14\n101.76.0.0/15\n101.78.0.0/22\n101.78.32.0/19\n101.80.0.0/12\n101.96.0.0/21\n101.96.8.0/22\n101.96.16.0/20\n101.96.128.0/17\n101.99.96.0/19\n101.101.64.0/19\n101.101.100.0/24\n101.101.102.0/23\n101.101.104.0/21\n101.101.112.0/20\n101.102.64.0/19\n101.102.100.0/23\n101.102.102.0/24\n101.102.104.0/21\n101.102.112.0/20\n101.104.0.0/14\n101.110.64.0/19\n101.110.96.0/20\n101.110.116.0/22\n101.110.120.0/21\n101.120.0.0/14\n101.124.0.0/15\n101.126.0.0/16\n101.128.0.0/22\n101.128.8.0/21\n101.128.16.0/20\n101.128.32.0/19\n101.129.0.0/16\n101.130.0.0/15\n101.132.0.0/15\n101.134.0.0/17\n101.134.128.0/19\n101.134.160.0/20\n101.134.176.0/21\n101.134.184.0/22\n101.134.189.0/24\n101.134.190.0/23\n101.134.192.0/18\n101.135.0.0/16\n101.144.0.0/12\n101.192.0.0/14\n101.196.0.0/16\n101.198.128.0/18\n101.198.194.0/24\n101.198.196.0/23\n101.198.200.0/22\n101.198.224.0/19\n101.199.0.0/19\n101.199.48.0/20\n101.199.64.0/18\n101.199.128.0/17\n101.200.0.0/15\n101.203.128.0/19\n101.203.160.0/21\n101.203.172.0/22\n101.203.176.0/20\n101.204.0.0/14\n101.224.0.0/13\n101.232.0.0/15\n101.234.64.0/21\n101.234.76.0/22\n101.234.80.0/20\n101.234.96.0/19\n101.236.0.0/14\n101.240.0.0/13\n101.248.0.0/15\n101.251.0.0/22\n101.251.8.0/21\n101.251.16.0/20\n101.251.32.0/19\n101.251.64.0/18\n101.251.128.0/17\n101.252.0.0/15\n101.254.0.0/16\n102.176.130.0/24\n103.1.8.0/22\n103.1.20.0/22\n103.1.24.0/22\n103.1.88.0/22\n103.1.168.0/22\n103.2.108.0/22\n103.2.156.0/22\n103.2.164.0/22\n103.2.200.0/21\n103.2.208.0/21\n103.3.84.0/22\n103.3.88.0/21\n103.3.96.0/19\n103.3.128.0/20\n103.3.148.0/22\n103.3.152.0/21\n103.4.56.0/22\n103.4.168.0/22\n103.4.184.0/22\n103.5.36.0/22\n103.5.52.0/23\n103.5.56.0/22\n103.5.152.0/22\n103.5.168.0/22\n103.5.192.0/22\n103.5.252.0/22\n103.6.76.0/22\n103.6.108.0/22\n103.6.120.0/22\n103.6.220.0/22\n103.6.228.0/22\n103.7.140.0/22\n103.7.212.0/22\n103.7.216.0/21\n103.8.0.0/21\n103.8.8.0/22\n103.8.32.0/22\n103.8.52.0/22\n103.8.68.0/22\n103.8.108.0/22\n103.8.156.0/22\n103.8.200.0/21\n103.8.220.0/22\n103.9.8.0/22\n103.9.24.0/22\n103.9.108.0/22\n103.9.152.0/22\n103.9.248.0/21\n103.10.0.0/22\n103.10.16.0/22\n103.10.84.0/22\n103.10.111.0/24\n103.10.140.0/22\n103.11.16.0/22\n103.11.168.0/22\n103.11.180.0/22\n103.12.32.0/22\n103.12.136.0/22\n103.12.184.0/22\n103.12.232.0/22\n103.13.12.0/22\n103.13.124.0/22\n103.13.144.0/22\n103.13.196.0/22\n103.13.244.0/22\n103.14.84.0/22\n103.14.132.0/22\n103.14.136.0/22\n103.14.156.0/22\n103.14.240.0/22\n103.15.4.0/22\n103.15.8.0/22\n103.15.16.0/22\n103.15.96.0/22\n103.15.200.0/22\n103.16.52.0/22\n103.16.80.0/21\n103.16.88.0/22\n103.16.108.0/22\n103.16.124.0/22\n103.17.40.0/22\n103.17.64.0/22\n103.17.120.0/23\n103.17.136.0/22\n103.17.160.0/22\n103.17.204.0/22\n103.17.228.0/22\n103.18.192.0/22\n103.18.208.0/21\n103.18.224.0/22\n103.19.12.0/22\n103.19.40.0/21\n103.19.64.0/21\n103.19.72.0/22\n103.19.232.0/22\n103.20.12.0/22\n103.20.32.0/23\n103.20.34.0/24\n103.20.68.0/22\n103.20.112.0/22\n103.20.128.0/22\n103.20.160.0/22\n103.20.248.0/22\n103.21.112.0/21\n103.21.140.0/22\n103.21.176.0/22\n103.21.240.0/22\n103.22.0.0/18\n103.22.64.0/19\n103.22.100.0/22\n103.22.104.0/21\n103.22.112.0/20\n103.22.188.0/22\n103.22.228.0/22\n103.22.252.0/22\n103.23.8.0/22\n103.23.56.0/22\n103.23.160.0/21\n103.23.176.0/22\n103.23.228.0/22\n103.24.24.0/22\n103.24.116.0/22\n103.24.128.0/22\n103.24.144.0/22\n103.24.176.0/22\n103.24.184.0/22\n103.24.228.0/22\n103.24.252.0/22\n103.25.20.0/22\n103.25.24.0/21\n103.25.32.0/21\n103.25.40.0/22\n103.25.48.0/22\n103.25.64.0/21\n103.25.148.0/22\n103.25.156.0/22\n103.25.216.0/22\n103.26.0.0/22\n103.26.64.0/22\n103.26.76.0/22\n103.26.116.0/22\n103.26.156.0/22\n103.26.160.0/22\n103.26.228.0/22\n103.26.240.0/22\n103.27.4.0/22\n103.27.12.0/22\n103.27.24.0/22\n103.27.56.0/22\n103.27.96.0/22\n103.27.240.0/22\n103.28.4.0/22\n103.28.8.0/22\n103.28.184.0/22\n103.28.204.0/22\n103.28.212.0/22\n103.29.16.0/22\n103.29.128.0/21\n103.29.136.0/22\n103.30.20.0/22\n103.30.96.0/22\n103.30.148.0/22\n103.30.202.0/23\n103.30.228.0/22\n103.30.236.0/22\n103.31.0.0/22\n103.31.48.0/21\n103.31.60.0/22\n103.31.64.0/21\n103.31.72.0/24\n103.31.148.0/22\n103.31.160.0/22\n103.31.168.0/22\n103.31.200.0/22\n103.31.236.0/22\n103.32.0.0/15\n103.34.0.0/16\n103.35.0.0/19\n103.35.32.0/20\n103.35.48.0/22\n103.35.104.0/22\n103.35.220.0/22\n103.36.28.0/22\n103.36.36.0/22\n103.36.56.0/21\n103.36.64.0/22\n103.36.72.0/22\n103.36.96.0/22\n103.36.132.0/22\n103.36.136.0/22\n103.36.160.0/19\n103.36.192.0/19\n103.36.224.0/20\n103.36.240.0/21\n103.37.12.0/22\n103.37.16.0/22\n103.37.24.0/22\n103.37.44.0/22\n103.37.52.0/22\n103.37.56.0/22\n103.37.72.0/22\n103.37.100.0/22\n103.37.104.0/22\n103.37.136.0/21\n103.37.144.0/20\n103.37.160.0/21\n103.37.172.0/22\n103.37.176.0/22\n103.37.188.0/22\n103.37.208.0/20\n103.37.252.0/22\n103.38.0.0/22\n103.38.32.0/22\n103.38.40.0/21\n103.38.76.0/22\n103.38.84.0/22\n103.38.92.0/22\n103.38.96.0/22\n103.38.116.0/22\n103.38.132.0/22\n103.38.140.0/22\n103.38.220.0/22\n103.38.224.0/21\n103.38.232.0/22\n103.38.252.0/23\n103.39.64.0/22\n103.39.88.0/22\n103.39.100.0/22\n103.39.104.0/22\n103.39.160.0/19\n103.39.200.0/21\n103.39.208.0/20\n103.39.224.0/21\n103.39.232.0/22\n103.40.12.0/22\n103.40.16.0/20\n103.40.32.0/20\n103.40.88.0/22\n103.40.192.0/22\n103.40.212.0/22\n103.40.220.0/22\n103.40.228.0/22\n103.40.232.0/21\n103.40.240.0/20\n103.41.0.0/22\n103.41.52.0/22\n103.41.140.0/22\n103.41.148.0/22\n103.41.152.0/22\n103.41.160.0/21\n103.41.220.0/22\n103.41.224.0/21\n103.41.232.0/22\n103.42.8.0/22\n103.42.24.0/22\n103.42.32.0/22\n103.42.64.0/21\n103.42.76.0/22\n103.42.232.0/22\n103.43.26.0/23\n103.43.96.0/21\n103.43.104.0/22\n103.43.124.0/22\n103.43.184.0/22\n103.43.192.0/21\n103.43.208.0/22\n103.43.220.0/22\n103.43.224.0/22\n103.43.240.0/22\n103.44.58.0/23\n103.44.80.0/22\n103.44.120.0/21\n103.44.144.0/22\n103.44.152.0/22\n103.44.168.0/22\n103.44.176.0/20\n103.44.192.0/20\n103.44.224.0/22\n103.44.236.0/22\n103.44.240.0/20\n103.45.0.0/18\n103.45.72.0/21\n103.45.80.0/20\n103.45.96.0/19\n103.45.128.0/18\n103.45.192.0/19\n103.45.224.0/22\n103.45.248.0/22\n103.46.0.0/22\n103.46.12.0/22\n103.46.16.0/20\n103.46.32.0/19\n103.46.64.0/18\n103.46.128.0/21\n103.46.136.0/22\n103.46.152.0/21\n103.46.160.0/20\n103.46.176.0/21\n103.46.244.0/22\n103.46.248.0/22\n103.47.4.0/22\n103.47.20.0/22\n103.47.36.0/22\n103.47.40.0/22\n103.47.48.0/22\n103.47.80.0/22\n103.47.96.0/22\n103.47.116.0/22\n103.47.120.0/22\n103.47.136.0/21\n103.47.212.0/22\n103.48.52.0/22\n103.48.92.0/22\n103.48.148.0/22\n103.48.152.0/22\n103.48.202.0/23\n103.48.216.0/21\n103.48.224.0/20\n103.48.240.0/21\n103.49.12.0/22\n103.49.20.0/22\n103.49.72.0/21\n103.49.96.0/22\n103.49.108.0/22\n103.49.128.0/22\n103.49.176.0/21\n103.50.36.0/22\n103.50.44.0/22\n103.50.48.0/20\n103.50.64.0/21\n103.50.72.0/22\n103.50.92.0/22\n103.50.108.0/22\n103.50.112.0/20\n103.50.132.0/22\n103.50.136.0/21\n103.50.172.0/22\n103.50.176.0/20\n103.50.192.0/21\n103.50.200.0/22\n103.50.220.0/22\n103.50.224.0/20\n103.50.240.0/21\n103.50.248.0/22\n103.52.40.0/22\n103.52.72.0/21\n103.52.80.0/21\n103.52.96.0/21\n103.52.104.0/22\n103.52.160.0/21\n103.52.172.0/22\n103.52.176.0/22\n103.52.184.0/22\n103.52.196.0/22\n103.53.64.0/21\n103.53.92.0/22\n103.53.124.0/22\n103.53.128.0/20\n103.53.144.0/22\n103.53.160.0/22\n103.53.180.0/22\n103.53.204.0/22\n103.53.208.0/21\n103.53.236.0/22\n103.53.248.0/22\n103.54.8.0/22\n103.54.48.0/22\n103.54.160.0/21\n103.54.212.0/22\n103.54.228.0/22\n103.54.240.0/22\n103.55.80.0/22\n103.55.120.0/22\n103.55.152.0/22\n103.55.172.0/22\n103.55.204.0/22\n103.55.208.0/22\n103.55.228.0/22\n103.55.236.0/22\n103.55.240.0/22\n103.56.20.0/22\n103.56.32.0/22\n103.56.56.0/21\n103.56.72.0/21\n103.56.140.0/22\n103.56.152.0/22\n103.56.184.0/22\n103.56.200.0/22\n103.57.12.0/22\n103.57.52.0/22\n103.57.56.0/22\n103.57.76.0/22\n103.57.136.0/22\n103.57.196.0/22\n103.58.24.0/22\n103.59.76.0/22\n103.59.112.0/21\n103.59.120.0/24\n103.59.123.0/24\n103.59.124.0/22\n103.59.128.0/22\n103.59.148.0/22\n103.60.32.0/22\n103.60.44.0/22\n103.60.164.0/22\n103.60.228.0/22\n103.60.236.0/22\n103.61.60.0/24\n103.61.104.0/22\n103.61.140.0/22\n103.61.152.0/21\n103.61.160.0/22\n103.61.172.0/22\n103.61.176.0/22\n103.62.24.0/22\n103.62.72.0/21\n103.62.80.0/21\n103.62.88.0/22\n103.62.96.0/19\n103.62.128.0/21\n103.62.156.0/22\n103.62.160.0/19\n103.62.192.0/22\n103.62.204.0/22\n103.62.208.0/20\n103.62.224.0/22\n103.63.32.0/19\n103.63.64.0/20\n103.63.80.0/21\n103.63.88.0/22\n103.63.140.0/22\n103.63.144.0/22\n103.63.152.0/22\n103.63.160.0/20\n103.63.176.0/21\n103.63.184.0/22\n103.63.192.0/20\n103.63.208.0/22\n103.63.240.0/20\n103.64.0.0/21\n103.64.24.0/21\n103.64.32.0/19\n103.64.64.0/18\n103.64.140.0/22\n103.64.144.0/22\n103.64.152.0/21\n103.64.160.0/19\n103.64.192.0/18\n103.65.0.0/21\n103.65.12.0/22\n103.65.16.0/22\n103.65.48.0/20\n103.65.64.0/19\n103.65.100.0/22\n103.65.104.0/21\n103.65.112.0/20\n103.65.128.0/21\n103.65.136.0/22\n103.65.144.0/20\n103.65.160.0/20\n103.66.32.0/22\n103.66.40.0/22\n103.66.108.0/22\n103.66.200.0/22\n103.66.240.0/20\n103.67.0.0/21\n103.67.8.0/22\n103.67.40.0/21\n103.67.48.0/20\n103.67.64.0/18\n103.67.128.0/20\n103.67.144.0/21\n103.67.172.0/24\n103.67.175.0/24\n103.67.192.0/22\n103.67.212.0/22\n103.68.88.0/22\n103.68.100.0/22\n103.68.128.0/22\n103.69.16.0/22\n103.69.212.0/23\n103.70.8.0/22\n103.70.148.0/22\n103.70.236.0/22\n103.70.252.0/22\n103.71.0.0/22\n103.71.68.0/22\n103.71.72.0/22\n103.71.80.0/21\n103.71.88.0/22\n103.71.120.0/21\n103.71.128.0/22\n103.71.196.0/22\n103.71.200.0/22\n103.71.232.0/22\n103.72.12.0/22\n103.72.16.0/20\n103.72.32.0/20\n103.72.48.0/21\n103.72.112.0/21\n103.72.124.0/22\n103.72.128.0/21\n103.72.149.0/24\n103.72.150.0/23\n103.72.172.0/22\n103.72.180.0/22\n103.72.224.0/19\n103.73.0.0/19\n103.73.48.0/22\n103.73.116.0/22\n103.73.120.0/22\n103.73.128.0/20\n103.73.168.0/22\n103.73.176.0/22\n103.73.204.0/22\n103.73.208.0/22\n103.73.240.0/23\n103.73.244.0/22\n103.73.248.0/22\n103.74.24.0/21\n103.74.32.0/20\n103.74.48.0/22\n103.74.56.0/21\n103.74.80.0/22\n103.74.124.0/22\n103.74.148.0/22\n103.74.152.0/21\n103.74.204.0/22\n103.74.232.0/22\n103.75.87.0/24\n103.75.88.0/21\n103.75.104.0/21\n103.75.112.0/22\n103.75.120.0/22\n103.75.128.0/22\n103.75.144.0/22\n103.75.152.0/22\n103.76.60.0/22\n103.76.64.0/21\n103.76.72.0/22\n103.76.92.0/22\n103.76.216.0/21\n103.76.224.0/22\n103.77.28.0/22\n103.77.52.0/22\n103.77.56.0/22\n103.77.88.0/22\n103.77.132.0/22\n103.77.148.0/22\n103.77.220.0/22\n103.78.56.0/21\n103.78.64.0/22\n103.78.124.0/22\n103.78.172.0/22\n103.78.176.0/22\n103.78.196.0/22\n103.78.228.0/22\n103.79.24.0/21\n103.79.36.0/22\n103.79.40.0/21\n103.79.56.0/21\n103.79.64.0/21\n103.79.80.0/21\n103.79.136.0/22\n103.79.188.0/22\n103.79.192.0/20\n103.79.208.0/21\n103.79.243.0/24\n103.80.44.0/22\n103.80.72.0/22\n103.80.176.0/21\n103.80.184.0/22\n103.80.192.0/22\n103.80.200.0/22\n103.80.232.0/22\n103.81.4.0/22\n103.81.44.0/22\n103.81.48.0/22\n103.81.96.0/22\n103.81.120.0/22\n103.81.148.0/22\n103.81.164.0/22\n103.81.200.0/22\n103.81.232.0/22\n103.82.60.0/22\n103.82.68.0/22\n103.82.84.0/22\n103.82.104.0/22\n103.82.224.0/22\n103.82.236.0/22\n103.83.44.0/22\n103.83.52.0/22\n103.83.60.0/22\n103.83.72.0/22\n103.83.112.0/22\n103.83.132.0/22\n103.83.180.0/22\n103.84.0.0/22\n103.84.12.0/22\n103.84.20.0/22\n103.84.24.0/21\n103.84.48.0/22\n103.84.56.0/22\n103.84.64.0/22\n103.84.72.0/22\n103.85.44.0/22\n103.85.48.0/21\n103.85.56.0/22\n103.85.84.0/22\n103.85.136.0/22\n103.85.144.0/22\n103.85.164.0/22\n103.85.168.0/21\n103.85.176.0/22\n103.86.28.0/22\n103.86.32.0/22\n103.86.60.0/22\n103.86.129.0/24\n103.86.204.0/22\n103.86.208.0/20\n103.86.224.0/19\n103.87.0.0/21\n103.87.20.0/22\n103.87.32.0/22\n103.87.96.0/22\n103.87.132.0/22\n103.87.180.0/22\n103.87.224.0/22\n103.88.4.0/22\n103.88.8.0/21\n103.88.16.0/21\n103.88.32.0/21\n103.88.60.0/22\n103.88.64.0/22\n103.88.72.0/22\n103.88.96.0/21\n103.88.152.0/23\n103.88.164.0/22\n103.88.212.0/22\n103.89.28.0/22\n103.89.96.0/20\n103.89.112.0/22\n103.89.148.0/22\n103.89.172.0/22\n103.89.184.0/21\n103.89.192.0/19\n103.89.224.0/21\n103.90.52.0/22\n103.90.92.0/22\n103.90.100.0/22\n103.90.104.0/21\n103.90.112.0/20\n103.90.128.0/21\n103.90.152.0/22\n103.90.168.0/22\n103.90.173.0/24\n103.90.176.0/22\n103.90.188.0/22\n103.90.192.0/22\n103.91.36.0/22\n103.91.40.0/22\n103.91.108.0/22\n103.91.152.0/22\n103.91.176.0/22\n103.91.200.0/22\n103.91.208.0/21\n103.91.236.0/22\n103.92.48.0/20\n103.92.64.0/20\n103.92.80.0/22\n103.92.88.0/22\n103.92.108.0/22\n103.92.124.0/22\n103.92.132.0/22\n103.92.156.0/22\n103.92.164.0/22\n103.92.168.0/21\n103.92.176.0/20\n103.92.192.0/22\n103.92.236.0/22\n103.92.240.0/20\n103.93.0.0/21\n103.93.28.0/22\n103.93.84.0/22\n103.93.152.0/22\n103.93.180.0/22\n103.93.204.0/22\n103.94.12.0/22\n103.94.20.0/22\n103.94.28.0/22\n103.94.32.0/20\n103.94.72.0/22\n103.94.88.0/22\n103.94.116.0/22\n103.94.160.0/22\n103.94.182.0/24\n103.94.200.0/22\n103.95.31.0/24\n103.95.52.0/22\n103.95.70.0/23\n103.95.88.0/21\n103.95.136.0/21\n103.95.144.0/22\n103.95.152.0/22\n103.95.216.0/21\n103.95.224.0/22\n103.95.236.0/22\n103.95.240.0/20\n103.96.8.0/22\n103.96.124.0/22\n103.96.136.0/22\n103.96.152.0/21\n103.96.160.0/19\n103.96.192.0/20\n103.96.208.0/21\n103.96.216.0/22\n103.97.40.0/22\n103.97.60.0/23\n103.97.112.0/21\n103.97.148.0/22\n103.97.188.0/22\n103.97.192.0/22\n103.98.40.0/21\n103.98.48.0/22\n103.98.56.0/22\n103.98.80.0/22\n103.98.88.0/22\n103.98.100.0/22\n103.98.124.0/24\n103.98.126.0/23\n103.98.136.0/21\n103.98.144.0/22\n103.98.164.0/22\n103.98.168.0/22\n103.98.180.0/22\n103.98.196.0/22\n103.98.216.0/21\n103.98.224.0/21\n103.98.232.0/22\n103.98.240.0/21\n103.98.248.0/23\n103.98.250.0/24\n103.98.252.0/22\n103.99.56.0/22\n103.99.104.0/22\n103.99.116.0/22\n103.99.120.0/22\n103.99.132.0/22\n103.99.136.0/21\n103.99.144.0/22\n103.99.152.0/22\n103.99.220.0/22\n103.99.232.0/21\n103.100.0.0/22\n103.100.32.0/22\n103.100.40.0/22\n103.100.48.0/22\n103.100.56.0/22\n103.100.64.0/22\n103.100.88.0/22\n103.100.116.0/22\n103.100.144.0/22\n103.100.240.0/22\n103.100.248.0/21\n103.101.4.0/22\n103.101.8.0/21\n103.101.60.0/22\n103.101.121.0/24\n103.101.122.0/23\n103.101.124.0/24\n103.101.126.0/23\n103.101.144.0/21\n103.101.180.0/22\n103.101.184.0/22\n103.102.76.0/22\n103.102.80.0/22\n103.102.168.0/21\n103.102.180.0/22\n103.102.184.0/21\n103.102.192.0/22\n103.102.196.0/24\n103.102.200.0/22\n103.102.208.0/21\n103.103.12.0/22\n103.103.16.0/22\n103.103.36.0/22\n103.103.72.0/22\n103.103.188.0/22\n103.103.204.0/22\n103.104.36.0/22\n103.104.40.0/22\n103.104.64.0/22\n103.104.152.0/22\n103.104.252.0/22\n103.105.0.0/21\n103.105.12.0/22\n103.105.16.0/22\n103.105.60.0/22\n103.105.116.0/22\n103.105.180.0/22\n103.105.184.0/22\n103.105.200.0/21\n103.105.220.0/22\n103.106.36.0/22\n103.106.40.0/21\n103.106.60.0/22\n103.106.68.0/22\n103.106.96.0/22\n103.106.120.0/22\n103.106.128.0/21\n103.106.190.0/23\n103.106.196.0/22\n103.106.212.0/22\n103.106.252.0/22\n103.107.0.0/22\n103.107.28.0/22\n103.107.32.0/22\n103.107.44.0/22\n103.107.72.0/22\n103.107.164.0/22\n103.107.168.0/22\n103.107.188.0/22\n103.107.192.0/22\n103.107.208.0/20\n103.108.52.0/22\n103.108.160.0/21\n103.108.194.0/24\n103.108.196.0/22\n103.108.208.0/21\n103.108.224.0/22\n103.108.244.0/22\n103.108.251.0/24\n103.109.20.0/22\n103.109.48.0/22\n103.109.88.0/22\n103.109.106.0/23\n103.109.248.0/22\n103.110.32.0/22\n103.110.92.0/22\n103.110.119.0/24\n103.110.127.0/24\n103.110.128.0/23\n103.110.131.0/24\n103.110.132.0/22\n103.110.136.0/22\n103.110.156.0/22\n103.110.188.0/22\n103.110.204.0/22\n103.111.64.0/22\n103.111.172.0/22\n103.111.252.0/22\n103.112.72.0/22\n103.112.88.0/21\n103.112.108.0/22\n103.112.112.0/22\n103.112.140.0/22\n103.113.4.0/22\n103.113.144.0/22\n103.113.220.0/22\n103.113.232.0/21\n103.114.4.0/22\n103.114.68.0/22\n103.114.100.0/22\n103.114.148.0/22\n103.114.156.0/23\n103.114.159.0/24\n103.114.212.0/22\n103.114.236.0/22\n103.114.240.0/22\n103.115.52.0/22\n103.115.68.0/22\n103.115.92.0/22\n103.115.120.0/22\n103.115.148.0/22\n103.115.248.0/22\n103.116.76.0/22\n103.116.92.0/22\n103.116.120.0/22\n103.116.128.0/22\n103.116.150.0/23\n103.116.184.0/22\n103.116.220.0/22\n103.116.224.0/21\n103.117.16.0/22\n103.117.88.0/22\n103.117.188.0/22\n103.117.220.0/22\n103.118.19.0/24\n103.118.52.0/22\n103.118.56.0/21\n103.118.64.0/21\n103.118.72.0/22\n103.118.88.0/22\n103.118.173.0/24\n103.119.115.0/24\n103.119.156.0/22\n103.119.180.0/22\n103.119.200.0/22\n103.119.224.0/22\n103.120.52.0/22\n103.120.72.0/22\n103.120.76.0/24\n103.120.88.0/22\n103.120.96.0/22\n103.120.140.0/22\n103.120.196.0/22\n103.120.224.0/22\n103.121.52.0/22\n103.121.160.0/21\n103.121.250.0/24\n103.121.252.0/22\n103.122.48.0/22\n103.122.178.0/23\n103.122.192.0/22\n103.122.240.0/23\n103.122.242.0/24\n103.123.4.0/22\n103.123.56.0/22\n103.123.88.0/21\n103.123.116.0/22\n103.123.176.0/22\n103.123.200.0/21\n103.123.208.0/21\n103.124.24.0/22\n103.124.48.0/22\n103.124.64.0/22\n103.124.212.0/22\n103.124.216.0/22\n103.125.20.0/22\n103.125.44.0/22\n103.125.132.0/22\n103.125.164.0/22\n103.125.196.0/22\n103.125.236.0/22\n103.126.0.0/22\n103.126.16.0/23\n103.126.44.0/22\n103.126.124.0/22\n103.126.128.0/22\n103.129.53.0/24\n103.129.54.0/23\n103.129.148.0/22\n103.130.132.0/22\n103.130.160.0/22\n103.130.228.0/22\n103.131.20.0/22\n103.131.36.0/22\n103.131.152.0/22\n103.131.168.0/22\n103.131.224.0/21\n103.131.240.0/22\n103.132.60.0/22\n103.132.64.0/20\n103.132.80.0/22\n103.132.104.0/21\n103.132.112.0/21\n103.132.120.0/22\n103.132.188.0/22\n103.132.208.0/21\n103.133.12.0/22\n103.133.40.0/22\n103.133.128.0/22\n103.133.232.0/22\n103.134.196.0/22\n103.135.80.0/22\n103.135.124.0/22\n103.135.148.0/22\n103.135.156.0/22\n103.135.160.0/21\n103.135.176.0/22\n103.135.184.0/22\n103.135.192.0/21\n103.135.236.0/22\n103.136.128.0/22\n103.136.232.0/22\n103.137.58.0/23\n103.137.60.0/24\n103.137.136.0/23\n103.137.149.0/24\n103.137.180.0/22\n103.137.236.0/22\n103.138.2.0/23\n103.138.134.0/23\n103.138.208.0/23\n103.138.220.0/23\n103.138.248.0/23\n103.139.22.0/23\n103.139.134.0/23\n103.139.136.0/23\n103.139.172.0/23\n103.139.204.0/23\n103.139.212.0/23\n103.140.14.0/23\n103.140.46.0/23\n103.140.140.0/23\n103.140.144.0/23\n103.140.192.0/23\n103.141.10.0/23\n103.141.58.0/23\n103.141.128.0/23\n103.141.186.0/23\n103.141.242.0/23\n103.142.0.0/23\n103.142.28.0/23\n103.142.58.0/23\n103.142.82.0/23\n103.142.96.0/23\n103.142.122.0/23\n103.142.128.0/23\n103.142.154.0/23\n103.142.156.0/23\n103.142.180.0/23\n103.142.186.0/23\n103.142.220.0/23\n103.142.230.0/24\n103.142.234.0/23\n103.142.238.0/23\n103.143.16.0/22\n103.143.31.0/24\n103.143.74.0/23\n103.143.124.0/23\n103.143.132.0/22\n103.143.174.0/23\n103.143.228.0/23\n103.144.66.0/23\n103.144.70.0/23\n103.144.72.0/23\n103.144.136.0/23\n103.144.158.0/23\n103.145.40.0/22\n103.145.73.0/24\n103.145.80.0/23\n103.145.90.0/23\n103.145.92.0/22\n103.145.98.0/23\n103.145.107.0/24\n103.145.188.0/23\n103.146.6.0/23\n103.146.72.0/23\n103.146.90.0/23\n103.146.126.0/23\n103.146.138.0/23\n103.146.236.0/23\n103.146.252.0/23\n103.147.124.0/23\n103.147.198.0/23\n103.147.206.0/23\n103.148.174.0/23\n103.192.0.0/19\n103.192.48.0/21\n103.192.56.0/22\n103.192.84.0/22\n103.192.88.0/21\n103.192.96.0/20\n103.192.112.0/22\n103.192.128.0/20\n103.192.144.0/22\n103.192.164.0/22\n103.192.188.0/22\n103.192.208.0/21\n103.192.216.0/22\n103.192.252.0/22\n103.193.40.0/21\n103.193.120.0/22\n103.193.140.0/22\n103.193.160.0/22\n103.193.188.0/22\n103.193.192.0/22\n103.193.212.0/22\n103.193.216.0/21\n103.193.224.0/20\n103.194.16.0/22\n103.194.230.0/23\n103.195.112.0/22\n103.195.152.0/22\n103.195.160.0/22\n103.196.64.0/22\n103.196.72.0/22\n103.196.88.0/21\n103.196.96.0/22\n103.196.168.0/22\n103.196.185.0/24\n103.196.186.0/23\n103.197.181.0/24\n103.197.183.0/24\n103.197.228.0/22\n103.197.253.0/24\n103.197.254.0/23\n103.198.20.0/22\n103.198.60.0/22\n103.198.64.0/22\n103.198.72.0/22\n103.198.124.0/22\n103.198.156.0/22\n103.198.180.0/22\n103.198.196.0/22\n103.198.200.0/22\n103.198.216.0/21\n103.198.224.0/20\n103.198.240.0/21\n103.199.164.0/22\n103.199.196.0/22\n103.199.228.0/22\n103.199.252.0/22\n103.200.52.0/22\n103.200.64.0/21\n103.200.136.0/21\n103.200.144.0/20\n103.200.160.0/19\n103.200.192.0/22\n103.200.220.0/22\n103.200.224.0/19\n103.201.0.0/20\n103.201.16.0/21\n103.201.28.0/22\n103.201.32.0/19\n103.201.64.0/22\n103.201.76.0/22\n103.201.80.0/20\n103.201.96.0/20\n103.201.112.0/21\n103.201.120.0/22\n103.201.152.0/21\n103.201.160.0/19\n103.201.192.0/18\n103.202.0.0/19\n103.202.32.0/20\n103.202.56.0/21\n103.202.64.0/18\n103.202.128.0/20\n103.202.144.0/22\n103.202.152.0/21\n103.202.160.0/19\n103.202.192.0/20\n103.202.212.0/22\n103.202.228.0/22\n103.202.236.0/22\n103.202.240.0/20\n103.203.0.0/19\n103.203.32.0/22\n103.203.96.0/19\n103.203.128.0/22\n103.203.140.0/22\n103.203.164.0/22\n103.203.168.0/22\n103.203.192.0/22\n103.203.200.0/22\n103.203.212.0/22\n103.203.216.0/22\n103.204.24.0/22\n103.204.88.0/22\n103.204.112.0/22\n103.204.136.0/21\n103.204.144.0/21\n103.204.152.0/22\n103.204.196.0/22\n103.204.232.0/21\n103.205.4.0/22\n103.205.40.0/21\n103.205.52.0/22\n103.205.108.0/22\n103.205.116.0/22\n103.205.120.0/24\n103.205.136.0/22\n103.205.162.0/24\n103.205.188.0/22\n103.205.192.0/21\n103.205.200.0/22\n103.205.236.0/22\n103.205.248.0/21\n103.206.0.0/22\n103.206.44.0/22\n103.206.148.0/22\n103.207.104.0/22\n103.207.184.0/21\n103.207.192.0/20\n103.207.208.0/21\n103.207.220.0/22\n103.207.228.0/22\n103.207.232.0/22\n103.208.12.0/22\n103.208.16.0/22\n103.208.28.0/22\n103.208.48.0/22\n103.208.148.0/22\n103.209.112.0/22\n103.209.136.0/22\n103.209.200.0/22\n103.209.208.0/22\n103.209.216.0/22\n103.210.0.0/22\n103.210.96.0/22\n103.210.156.0/22\n103.210.160.0/19\n103.210.217.0/24\n103.210.218.0/23\n103.211.44.0/22\n103.211.96.0/23\n103.211.98.0/24\n103.211.100.0/22\n103.211.156.0/22\n103.211.165.0/24\n103.211.168.0/22\n103.211.220.0/22\n103.211.248.0/22\n103.212.0.0/20\n103.212.44.0/22\n103.212.48.0/22\n103.212.84.0/22\n103.212.100.0/22\n103.212.148.0/22\n103.212.164.0/22\n103.212.196.0/22\n103.212.200.0/22\n103.212.252.0/22\n103.213.40.0/21\n103.213.48.0/20\n103.213.64.0/19\n103.213.96.0/22\n103.213.132.0/22\n103.213.136.0/21\n103.213.144.0/20\n103.213.160.0/19\n103.213.252.0/22\n103.214.48.0/22\n103.214.84.0/22\n103.214.212.0/22\n103.214.240.0/21\n103.215.28.0/22\n103.215.32.0/21\n103.215.44.0/22\n103.215.100.0/23\n103.215.108.0/22\n103.215.116.0/22\n103.215.120.0/22\n103.215.140.0/22\n103.216.4.0/22\n103.216.8.0/21\n103.216.16.0/20\n103.216.32.0/20\n103.216.64.0/22\n103.216.108.0/22\n103.216.136.0/22\n103.216.152.0/22\n103.216.224.0/21\n103.216.240.0/20\n103.217.0.0/18\n103.217.168.0/22\n103.217.180.0/22\n103.217.184.0/21\n103.217.192.0/20\n103.218.8.0/21\n103.218.16.0/21\n103.218.29.0/24\n103.218.30.0/23\n103.218.32.0/19\n103.218.64.0/19\n103.218.192.0/20\n103.218.208.0/21\n103.218.216.0/22\n103.219.24.0/21\n103.219.32.0/21\n103.219.64.0/22\n103.219.84.0/22\n103.219.88.0/21\n103.219.96.0/21\n103.219.176.0/22\n103.219.184.0/22\n103.220.48.0/20\n103.220.64.0/22\n103.220.92.0/22\n103.220.96.0/22\n103.220.104.0/21\n103.220.116.0/22\n103.220.120.0/21\n103.220.128.0/20\n103.220.144.0/21\n103.220.152.0/22\n103.220.160.0/19\n103.220.192.0/21\n103.220.200.0/22\n103.220.240.0/20\n103.221.0.0/19\n103.221.32.0/21\n103.221.88.0/21\n103.221.96.0/19\n103.221.128.0/18\n103.221.192.0/20\n103.222.0.0/20\n103.222.16.0/22\n103.222.24.0/21\n103.222.33.0/24\n103.222.34.0/23\n103.222.36.0/22\n103.222.40.0/21\n103.222.48.0/20\n103.222.64.0/18\n103.222.128.0/18\n103.222.192.0/19\n103.222.224.0/21\n103.222.232.0/22\n103.222.240.0/21\n103.223.16.0/20\n103.223.32.0/19\n103.223.64.0/19\n103.223.96.0/20\n103.223.112.0/21\n103.223.124.0/22\n103.223.128.0/21\n103.223.140.0/22\n103.223.144.0/20\n103.223.160.0/20\n103.223.176.0/21\n103.223.188.0/22\n103.223.192.0/18\n103.224.0.0/22\n103.224.40.0/21\n103.224.60.0/22\n103.224.220.0/22\n103.224.224.0/21\n103.224.232.0/22\n103.226.40.0/22\n103.226.56.0/21\n103.226.80.0/22\n103.226.116.0/22\n103.226.132.0/22\n103.226.156.0/22\n103.226.180.0/22\n103.226.196.0/22\n103.227.48.0/22\n103.227.72.0/21\n103.227.80.0/22\n103.227.100.0/22\n103.227.120.0/22\n103.227.132.0/22\n103.227.136.0/22\n103.227.196.0/22\n103.227.204.0/23\n103.227.206.0/24\n103.227.212.0/22\n103.227.228.0/22\n103.228.12.0/22\n103.228.88.0/22\n103.228.136.0/22\n103.228.160.0/22\n103.228.176.0/22\n103.228.204.0/22\n103.228.208.0/22\n103.228.228.0/22\n103.228.232.0/22\n103.229.20.0/22\n103.229.136.0/22\n103.229.148.0/22\n103.229.172.0/22\n103.229.212.0/22\n103.229.216.0/21\n103.229.228.0/22\n103.229.236.0/22\n103.229.240.0/22\n103.230.0.0/22\n103.230.28.0/22\n103.230.40.0/21\n103.230.96.0/22\n103.230.196.0/22\n103.230.200.0/21\n103.230.212.0/22\n103.230.236.0/22\n103.231.16.0/21\n103.231.64.0/21\n103.231.144.0/22\n103.231.180.0/22\n103.231.244.0/22\n103.232.4.0/22\n103.232.17.168/29\n103.232.144.0/22\n103.233.4.0/22\n103.233.44.0/22\n103.233.52.0/22\n103.233.104.0/22\n103.233.128.0/22\n103.233.136.0/22\n103.233.228.0/22\n103.234.0.0/22\n103.234.20.0/22\n103.234.56.0/22\n103.234.124.0/22\n103.234.128.0/22\n103.234.172.0/22\n103.234.180.0/22\n103.235.56.0/21\n103.235.80.0/22\n103.235.85.0/24\n103.235.86.0/23\n103.235.128.0/20\n103.235.144.0/21\n103.235.184.0/22\n103.235.192.0/22\n103.235.200.0/22\n103.235.220.0/22\n103.235.224.0/19\n103.236.0.0/18\n103.236.64.0/19\n103.236.96.0/22\n103.236.120.0/22\n103.236.184.0/22\n103.236.240.0/20\n103.237.0.0/20\n103.237.24.0/21\n103.237.68.0/22\n103.237.88.0/22\n103.237.152.0/22\n103.237.176.0/20\n103.237.192.0/18\n103.238.0.0/21\n103.238.18.0/23\n103.238.20.0/22\n103.238.24.0/21\n103.238.32.0/20\n103.238.48.0/21\n103.238.56.0/22\n103.238.88.0/21\n103.238.96.0/22\n103.238.132.0/22\n103.238.140.0/22\n103.238.144.0/22\n103.238.160.0/22\n103.238.165.0/24\n103.238.166.0/23\n103.238.168.0/21\n103.238.176.0/20\n103.238.196.0/22\n103.238.204.0/22\n103.238.252.0/22\n103.239.0.0/22\n103.239.44.0/22\n103.239.68.0/22\n103.239.152.0/21\n103.239.180.0/22\n103.239.184.0/22\n103.239.192.0/21\n103.239.204.0/22\n103.239.208.0/22\n103.239.224.0/22\n103.239.244.0/22\n103.240.16.0/22\n103.240.36.0/22\n103.240.72.0/22\n103.240.84.0/22\n103.240.124.0/22\n103.240.172.0/22\n103.240.188.0/22\n103.240.244.0/22\n103.241.12.0/22\n103.241.92.0/22\n103.241.96.0/22\n103.241.160.0/22\n103.241.184.0/21\n103.241.220.0/22\n103.242.64.0/23\n103.242.128.0/23\n103.242.160.0/22\n103.242.168.0/21\n103.242.176.0/22\n103.242.200.0/22\n103.242.212.0/22\n103.242.220.0/22\n103.242.240.0/22\n103.243.136.0/22\n103.243.252.0/22\n103.244.16.0/22\n103.244.58.0/23\n103.244.60.0/22\n103.244.64.0/20\n103.244.80.0/21\n103.244.116.0/22\n103.244.164.0/22\n103.244.232.0/22\n103.244.252.0/22\n103.245.23.0/24\n103.245.52.0/22\n103.245.60.0/22\n103.245.80.0/22\n103.245.124.0/22\n103.245.128.0/22\n103.246.8.0/21\n103.246.120.0/21\n103.246.132.0/22\n103.246.152.0/22\n103.247.168.0/21\n103.247.176.0/22\n103.247.200.0/22\n103.247.212.0/22\n103.248.64.0/23\n103.248.100.0/22\n103.248.124.0/22\n103.248.152.0/22\n103.248.168.0/22\n103.248.192.0/22\n103.248.212.0/22\n103.248.224.0/21\n103.249.8.0/21\n103.249.52.0/22\n103.249.128.0/22\n103.249.136.0/22\n103.249.144.0/22\n103.249.164.0/22\n103.249.168.0/21\n103.249.176.0/22\n103.249.188.0/22\n103.249.192.0/22\n103.249.244.0/22\n103.249.252.0/22\n103.250.32.0/22\n103.250.104.0/22\n103.250.124.0/22\n103.250.180.0/22\n103.250.192.0/22\n103.250.216.0/22\n103.250.224.0/22\n103.250.236.0/22\n103.250.248.0/21\n103.251.32.0/22\n103.251.84.0/22\n103.251.96.0/22\n103.251.124.0/22\n103.251.160.0/22\n103.251.192.0/22\n103.251.204.0/22\n103.251.240.0/22\n103.252.28.0/22\n103.252.36.0/22\n103.252.64.0/22\n103.252.96.0/22\n103.252.104.0/22\n103.252.172.0/22\n103.252.204.0/22\n103.252.208.0/22\n103.252.232.0/22\n103.252.248.0/22\n103.253.4.0/22\n103.253.60.0/22\n103.253.204.0/22\n103.253.220.0/22\n103.253.224.0/22\n103.253.232.0/22\n103.254.8.0/22\n103.254.20.0/22\n103.254.64.0/21\n103.254.76.0/22\n103.254.112.0/22\n103.254.176.0/22\n103.254.188.0/22\n103.255.68.0/22\n103.255.88.0/21\n103.255.136.0/21\n103.255.184.0/22\n103.255.200.0/22\n103.255.208.0/22\n103.255.228.0/22\n104.222.196.0/24\n106.0.0.0/24\n106.0.2.0/23\n106.0.4.0/22\n106.0.8.0/21\n106.0.16.0/20\n106.0.44.0/22\n106.0.64.0/18\n106.2.0.0/23\n106.2.3.0/24\n106.2.4.0/22\n106.2.8.0/21\n106.2.16.0/20\n106.2.32.0/19\n106.2.64.0/18\n106.2.128.0/17\n106.3.16.0/20\n106.3.32.0/19\n106.3.64.0/20\n106.3.80.0/22\n106.3.88.0/21\n106.3.96.0/19\n106.3.128.0/19\n106.3.164.0/22\n106.3.168.0/21\n106.3.176.0/20\n106.3.192.0/18\n106.4.0.0/14\n106.8.0.0/15\n106.11.0.0/16\n106.12.0.0/14\n106.16.0.0/12\n106.32.0.0/12\n106.48.0.0/21\n106.48.8.0/22\n106.48.16.0/20\n106.48.32.0/20\n106.48.57.0/24\n106.48.60.0/24\n106.48.63.0/24\n106.48.64.0/18\n106.48.128.0/17\n106.49.1.0/24\n106.49.2.0/23\n106.49.4.0/22\n106.49.8.0/21\n106.49.16.0/20\n106.49.32.0/19\n106.49.64.0/19\n106.49.96.0/24\n106.49.98.0/23\n106.49.100.0/22\n106.49.104.0/21\n106.49.112.0/20\n106.49.128.0/17\n106.50.0.0/16\n106.52.0.0/14\n106.56.0.0/13\n106.74.0.0/16\n106.75.0.0/17\n106.75.128.0/18\n106.75.201.0/24\n106.75.204.0/22\n106.75.208.0/20\n106.75.224.0/19\n106.80.0.0/12\n106.108.0.0/14\n106.112.0.0/12\n106.224.0.0/12\n109.71.4.0/24\n109.244.0.0/16\n110.6.0.0/15\n110.16.0.0/14\n110.34.40.0/21\n110.40.0.0/15\n110.42.0.0/16\n110.43.0.0/18\n110.43.64.0/21\n110.43.72.0/22\n110.43.76.0/23\n110.43.80.0/20\n110.43.96.0/19\n110.43.128.0/17\n110.44.12.0/22\n110.44.144.0/20\n110.48.0.0/16\n110.51.0.0/16\n110.52.0.0/15\n110.56.0.0/13\n110.64.0.0/15\n110.72.0.0/15\n110.75.0.0/16\n110.76.0.0/20\n110.76.16.0/22\n110.76.20.0/24\n110.76.22.0/24\n110.76.24.0/21\n110.76.32.0/19\n110.76.132.0/22\n110.76.156.0/22\n110.76.184.0/22\n110.76.192.0/18\n110.77.0.0/17\n110.80.0.0/13\n110.88.0.0/14\n110.92.68.0/22\n110.93.32.0/19\n110.94.0.0/15\n110.96.0.0/11\n110.152.0.0/14\n110.156.0.0/15\n110.166.0.0/15\n110.172.192.0/18\n110.173.0.0/19\n110.173.32.0/20\n110.173.64.0/19\n110.173.192.0/19\n110.176.0.0/12\n110.192.0.0/11\n110.228.0.0/14\n110.232.32.0/19\n110.236.0.0/15\n110.240.0.0/12\n111.0.0.0/10\n111.66.0.0/16\n111.67.192.0/20\n111.68.64.0/19\n111.72.0.0/13\n111.85.0.0/16\n111.91.192.0/19\n111.92.248.0/21\n111.112.0.0/14\n111.116.0.0/15\n111.118.200.0/21\n111.119.64.0/18\n111.119.128.0/19\n111.120.0.0/14\n111.124.0.0/16\n111.126.0.0/15\n111.128.0.0/11\n111.160.0.0/13\n111.170.0.0/16\n111.172.0.0/14\n111.176.0.0/13\n111.186.0.0/15\n111.192.0.0/12\n111.208.0.0/13\n111.221.28.0/24\n111.221.128.0/17\n111.222.0.0/16\n111.223.4.0/22\n111.223.8.0/21\n111.223.16.0/22\n111.223.240.0/22\n111.223.249.0/24\n111.223.250.0/23\n111.224.0.0/13\n111.235.96.0/19\n111.235.156.0/22\n111.235.160.0/21\n111.235.170.0/23\n111.235.172.0/22\n111.235.176.0/20\n112.0.0.0/10\n112.64.0.0/14\n112.73.64.0/18\n112.74.0.0/16\n112.80.0.0/12\n112.96.0.0/13\n112.109.128.0/17\n112.111.0.0/16\n112.112.0.0/14\n112.116.0.0/15\n112.122.0.0/15\n112.124.0.0/14\n112.128.0.0/14\n112.132.0.0/16\n112.137.48.0/21\n112.192.0.0/14\n112.224.0.0/11\n113.0.0.0/13\n113.8.0.0/15\n113.11.192.0/19\n113.12.0.0/14\n113.16.0.0/15\n113.18.0.0/16\n113.21.232.0/21\n113.24.0.0/14\n113.31.0.0/16\n113.44.0.0/14\n113.48.0.0/14\n113.52.160.0/19\n113.52.228.0/22\n113.54.0.0/15\n113.56.0.0/15\n113.58.0.0/16\n113.59.0.0/17\n113.59.224.0/22\n113.62.0.0/15\n113.64.0.0/10\n113.128.0.0/15\n113.130.96.0/20\n113.130.112.0/21\n113.132.0.0/14\n113.136.0.0/13\n113.194.0.0/15\n113.197.100.0/23\n113.197.102.0/24\n113.197.104.0/22\n113.200.0.0/15\n113.202.0.0/16\n113.204.0.0/14\n113.208.96.0/19\n113.208.128.0/17\n113.209.0.0/16\n113.212.0.0/18\n113.212.100.0/22\n113.212.184.0/21\n113.213.0.0/17\n113.214.0.0/15\n113.218.0.0/15\n113.220.0.0/14\n113.224.0.0/12\n113.240.0.0/13\n113.248.0.0/14\n114.28.0.0/17\n114.28.128.0/18\n114.28.192.0/19\n114.28.232.0/22\n114.28.236.0/23\n114.28.240.0/20\n114.31.64.0/21\n114.54.0.0/15\n114.60.0.0/14\n114.64.0.0/14\n114.68.0.0/16\n114.79.64.0/18\n114.80.0.0/12\n114.96.0.0/13\n114.104.0.0/14\n114.110.0.0/20\n114.110.64.0/18\n114.111.0.0/19\n114.111.160.0/19\n114.112.4.0/22\n114.112.8.0/22\n114.112.24.0/21\n114.112.32.0/19\n114.112.64.0/19\n114.112.96.0/20\n114.112.116.0/22\n114.112.120.0/21\n114.112.136.0/21\n114.112.144.0/20\n114.112.160.0/19\n114.112.192.0/19\n114.113.0.0/17\n114.113.128.0/21\n114.113.140.0/22\n114.113.144.0/20\n114.113.160.0/19\n114.113.196.0/22\n114.113.200.0/21\n114.113.208.0/20\n114.113.224.0/20\n114.114.0.0/15\n114.116.0.0/15\n114.118.0.0/16\n114.119.0.0/17\n114.119.192.0/18\n114.132.0.0/16\n114.135.0.0/16\n114.138.0.0/15\n114.141.64.0/21\n114.141.80.0/21\n114.141.128.0/18\n114.196.0.0/15\n114.198.248.0/21\n114.208.0.0/12\n114.224.0.0/11\n115.24.0.0/14\n115.28.0.0/15\n115.31.64.0/20\n115.32.0.0/14\n115.42.56.0/22\n115.44.0.0/14\n115.48.0.0/12\n115.69.64.0/20\n115.84.0.0/18\n115.84.192.0/19\n115.85.192.0/18\n115.100.0.0/14\n115.104.0.0/14\n115.120.0.0/14\n115.124.16.0/20\n115.148.0.0/14\n115.152.0.0/13\n115.166.64.0/19\n115.168.0.0/16\n115.169.0.0/23\n115.169.3.0/24\n115.169.6.0/24\n115.169.9.0/24\n115.169.14.0/23\n115.169.16.0/20\n115.169.39.0/24\n115.169.42.0/23\n115.169.44.0/22\n115.169.48.0/20\n115.169.64.0/18\n115.169.128.0/17\n115.170.0.0/15\n115.172.0.0/14\n115.180.0.0/14\n115.187.0.0/20\n115.190.0.0/15\n115.192.0.0/11\n115.224.0.0/12\n116.0.8.0/21\n116.0.24.0/21\n116.1.0.0/16\n116.2.0.0/15\n116.4.0.0/14\n116.8.0.0/14\n116.13.0.0/16\n116.16.0.0/12\n116.50.0.0/20\n116.52.0.0/14\n116.56.0.0/15\n116.58.128.0/20\n116.58.208.0/20\n116.60.0.0/14\n116.66.0.0/18\n116.66.64.0/19\n116.66.96.0/20\n116.66.120.0/22\n116.68.136.0/21\n116.68.176.0/21\n116.69.0.0/16\n116.70.0.0/17\n116.76.0.0/14\n116.85.0.0/17\n116.85.128.0/18\n116.85.192.0/19\n116.85.224.0/20\n116.85.240.0/21\n116.85.248.0/23\n116.85.250.0/24\n116.85.252.0/22\n116.89.144.0/20\n116.90.80.0/20\n116.90.184.0/21\n116.95.0.0/16\n116.112.0.0/14\n116.116.0.0/15\n116.128.0.0/10\n116.192.0.0/16\n116.193.16.0/20\n116.193.32.0/19\n116.193.176.0/21\n116.194.0.0/15\n116.196.0.0/21\n116.196.8.0/22\n116.196.12.0/23\n116.196.16.0/20\n116.196.32.0/19\n116.196.64.0/18\n116.196.128.0/18\n116.196.192.0/21\n116.196.200.0/23\n116.196.203.0/24\n116.196.204.0/22\n116.196.208.0/20\n116.196.224.0/19\n116.197.160.0/21\n116.197.180.0/23\n116.198.0.0/16\n116.199.0.0/17\n116.199.128.0/19\n116.204.0.0/17\n116.204.232.0/22\n116.205.0.0/16\n116.207.0.0/16\n116.208.0.0/14\n116.212.160.0/20\n116.213.64.0/18\n116.213.128.0/17\n116.214.32.0/19\n116.214.64.0/20\n116.214.128.0/17\n116.215.0.0/16\n116.216.0.0/14\n116.224.0.0/12\n116.242.0.0/15\n116.244.0.0/14\n116.248.0.0/15\n116.252.0.0/15\n116.254.104.0/21\n116.254.129.0/24\n116.254.130.0/23\n116.254.132.0/22\n116.254.136.0/21\n116.254.144.0/20\n116.254.160.0/19\n116.254.192.0/18\n116.255.128.0/17\n117.8.0.0/13\n117.21.0.0/16\n117.22.0.0/15\n117.24.0.0/13\n117.32.0.0/13\n117.40.0.0/14\n117.44.0.0/15\n117.48.0.0/15\n117.50.0.0/16\n117.51.128.0/23\n117.51.131.0/24\n117.51.132.0/22\n117.51.136.0/21\n117.51.144.0/20\n117.51.160.0/19\n117.51.192.0/18\n117.53.48.0/20\n117.53.176.0/20\n117.57.0.0/16\n117.58.0.0/18\n117.59.0.0/16\n117.60.0.0/14\n117.64.0.0/13\n117.72.0.0/15\n117.74.64.0/19\n117.74.128.0/17\n117.75.0.0/16\n117.76.0.0/14\n117.80.0.0/12\n117.100.0.0/15\n117.103.16.0/20\n117.103.40.0/21\n117.103.72.0/21\n117.103.128.0/20\n117.104.168.0/21\n117.106.0.0/15\n117.112.0.0/13\n117.120.64.0/18\n117.120.128.0/17\n117.121.0.0/19\n117.121.32.0/21\n117.121.40.0/22\n117.121.44.0/23\n117.121.46.0/24\n117.121.48.0/20\n117.121.64.0/18\n117.121.128.0/20\n117.121.148.0/22\n117.121.152.0/21\n117.121.160.0/19\n117.121.192.0/21\n117.122.128.0/17\n117.124.0.0/14\n117.128.0.0/10\n118.24.0.0/15\n118.26.0.0/19\n118.26.36.0/22\n118.26.40.0/21\n118.26.48.0/20\n118.26.64.0/19\n118.26.104.0/21\n118.26.112.0/20\n118.26.128.0/17\n118.28.0.0/15\n118.30.0.0/20\n118.30.16.0/21\n118.30.24.0/22\n118.30.32.0/19\n118.30.64.0/18\n118.30.128.0/17\n118.31.0.0/16\n118.64.0.0/15\n118.66.0.0/16\n118.67.112.0/20\n118.72.0.0/13\n118.80.0.0/15\n118.84.0.0/15\n118.88.32.0/19\n118.88.64.0/18\n118.88.128.0/17\n118.89.0.0/16\n118.102.16.0/20\n118.102.32.0/21\n118.103.164.0/22\n118.103.168.0/21\n118.103.176.0/22\n118.103.245.0/24\n118.103.246.0/23\n118.112.0.0/13\n118.120.0.0/14\n118.124.0.0/15\n118.126.1.0/24\n118.126.2.0/23\n118.126.4.0/22\n118.126.8.0/21\n118.126.16.0/23\n118.126.18.0/24\n118.126.32.0/19\n118.126.64.0/18\n118.126.128.0/17\n118.127.128.0/19\n118.132.0.0/14\n118.144.0.0/14\n118.178.0.0/16\n118.180.0.0/14\n118.184.5.0/24\n118.184.10.0/24\n118.184.115.0/24\n118.184.116.0/22\n118.184.120.0/23\n118.184.122.0/24\n118.184.128.0/18\n118.184.192.0/19\n118.184.240.0/20\n118.186.0.0/15\n118.188.0.0/16\n118.190.0.0/16\n118.191.0.0/20\n118.191.24.0/21\n118.191.32.0/19\n118.191.64.0/18\n118.191.144.0/21\n118.191.153.0/24\n118.191.154.0/23\n118.191.156.0/22\n118.191.160.0/19\n118.191.192.0/20\n118.191.209.0/24\n118.191.210.0/23\n118.191.212.0/22\n118.191.248.0/21\n118.192.0.0/16\n118.193.0.0/22\n118.193.32.0/20\n118.193.56.0/21\n118.193.68.0/22\n118.193.72.0/24\n118.193.77.0/24\n118.193.96.0/19\n118.194.0.0/17\n118.194.128.0/18\n118.194.192.0/19\n118.194.232.0/21\n118.194.240.0/20\n118.195.0.0/16\n118.196.0.0/14\n118.202.0.0/15\n118.204.0.0/14\n118.212.0.0/15\n118.215.192.0/18\n118.224.0.0/14\n118.228.0.0/17\n118.228.128.0/20\n118.228.144.0/21\n118.228.156.0/22\n118.228.160.0/19\n118.228.192.0/18\n118.229.0.0/16\n118.230.0.0/16\n118.239.0.0/16\n118.242.0.0/16\n118.244.0.0/14\n118.248.0.0/13\n119.0.0.0/15\n119.2.0.0/19\n119.2.128.0/17\n119.3.0.0/16\n119.4.0.0/14\n119.10.0.0/17\n119.15.136.0/21\n119.16.0.0/16\n119.18.192.0/20\n119.18.208.0/21\n119.18.224.0/19\n119.19.0.0/16\n119.20.0.0/14\n119.27.64.0/18\n119.27.128.0/17\n119.28.28.0/24\n119.29.0.0/16\n119.30.48.0/20\n119.31.192.0/19\n119.32.0.0/14\n119.36.0.0/15\n119.38.0.0/17\n119.38.128.0/18\n119.38.192.0/20\n119.38.208.0/22\n119.38.212.0/23\n119.38.214.0/27\n119.38.214.56/29\n119.38.214.64/26\n119.38.214.128/25\n119.38.215.0/24\n119.38.216.0/21\n119.39.0.0/16\n119.40.0.0/18\n119.40.64.0/20\n119.40.128.0/17\n119.41.0.0/16\n119.42.0.0/19\n119.42.52.0/22\n119.42.128.0/20\n119.42.224.0/19\n119.44.0.0/15\n119.48.0.0/13\n119.57.0.0/16\n119.58.0.0/16\n119.59.128.0/17\n119.60.0.0/15\n119.62.0.0/16\n119.63.32.0/19\n119.75.208.0/20\n119.78.0.0/15\n119.80.0.0/16\n119.82.208.0/20\n119.84.0.0/14\n119.88.0.0/16\n119.89.0.0/17\n119.89.128.0/21\n119.89.136.0/23\n119.89.139.0/24\n119.89.140.0/22\n119.89.144.0/20\n119.89.160.0/20\n119.89.176.0/22\n119.89.180.0/23\n119.89.183.0/24\n119.89.184.0/21\n119.89.192.0/23\n119.89.194.0/24\n119.89.196.0/22\n119.89.200.0/21\n119.89.208.0/21\n119.89.217.0/24\n119.89.218.0/23\n119.89.220.0/22\n119.89.224.0/19\n119.90.0.0/15\n119.96.0.0/13\n119.108.0.0/15\n119.112.0.0/12\n119.128.0.0/12\n119.144.0.0/14\n119.148.160.0/19\n119.151.192.0/18\n119.160.200.0/21\n119.161.120.0/21\n119.161.128.0/21\n119.161.160.0/19\n119.161.192.0/18\n119.162.0.0/15\n119.164.0.0/14\n119.176.0.0/12\n119.232.0.0/15\n119.235.128.0/19\n119.235.160.0/20\n119.235.184.0/22\n119.248.0.0/14\n119.252.96.0/21\n119.252.240.0/21\n119.252.249.0/24\n119.252.252.0/23\n119.253.0.0/16\n119.254.0.0/15\n120.0.0.0/12\n120.24.0.0/14\n120.30.0.0/15\n120.32.0.0/12\n120.48.0.0/15\n120.52.0.0/14\n120.64.0.0/13\n120.72.32.0/19\n120.72.128.0/17\n120.76.0.0/14\n120.80.0.0/13\n120.88.8.0/21\n120.90.0.0/15\n120.92.0.0/17\n120.92.128.0/18\n120.92.192.0/22\n120.92.198.0/23\n120.92.200.0/21\n120.92.208.0/20\n120.92.224.0/19\n120.94.0.0/15\n120.128.0.0/13\n120.136.16.0/21\n120.136.128.0/18\n120.137.0.0/17\n120.143.128.0/19\n120.192.0.0/10\n121.0.8.0/21\n121.0.16.0/20\n121.4.0.0/15\n121.8.0.0/13\n121.16.0.0/12\n121.32.0.0/13\n121.40.0.0/14\n121.46.0.0/18\n121.46.76.0/22\n121.46.128.0/17\n121.47.0.0/16\n121.48.0.0/15\n121.50.8.0/21\n121.51.0.0/16\n121.52.160.0/19\n121.52.208.0/20\n121.52.224.0/19\n121.54.176.0/21\n121.55.0.0/18\n121.56.0.0/15\n121.58.0.0/17\n121.58.136.0/21\n121.58.144.0/20\n121.58.160.0/21\n121.59.0.0/16\n121.60.0.0/14\n121.68.0.0/14\n121.76.0.0/15\n121.79.128.0/18\n121.89.0.0/16\n121.100.128.0/17\n121.101.0.0/18\n121.101.208.0/20\n121.192.0.0/13\n121.200.192.0/21\n121.201.0.0/16\n121.204.0.0/14\n121.224.0.0/12\n121.248.0.0/14\n121.255.0.0/16\n122.0.64.0/18\n122.0.128.0/17\n122.4.0.0/14\n122.10.132.0/23\n122.10.136.0/23\n122.10.196.0/23\n122.10.216.0/22\n122.10.228.0/22\n122.10.232.0/21\n122.10.240.0/21\n122.10.248.0/22\n122.11.0.0/17\n122.12.0.0/15\n122.14.0.0/17\n122.14.192.0/18\n122.48.0.0/16\n122.49.0.0/18\n122.51.0.0/16\n122.64.0.0/11\n122.96.0.0/15\n122.98.144.0/20\n122.98.160.0/21\n122.98.172.0/22\n122.98.176.0/20\n122.98.192.0/21\n122.98.232.0/21\n122.98.240.0/20\n122.102.0.0/20\n122.102.64.0/19\n122.112.0.0/18\n122.112.64.0/19\n122.112.96.0/22\n122.112.107.0/24\n122.112.118.0/24\n122.112.122.0/24\n122.112.125.0/24\n122.112.128.0/17\n122.113.0.0/16\n122.114.0.0/16\n122.115.0.0/18\n122.115.80.0/20\n122.115.96.0/19\n122.115.128.0/17\n122.119.0.0/16\n122.128.100.0/22\n122.128.120.0/21\n122.136.0.0/13\n122.144.128.0/17\n122.152.192.0/18\n122.156.0.0/14\n122.188.0.0/14\n122.192.0.0/14\n122.198.0.0/16\n122.200.40.0/21\n122.200.64.0/18\n122.201.48.0/20\n122.204.0.0/14\n122.224.0.0/12\n122.240.0.0/13\n122.248.24.0/21\n122.248.48.0/20\n122.255.64.0/21\n123.0.128.0/21\n123.0.136.0/23\n123.0.139.0/24\n123.0.140.0/22\n123.0.144.0/20\n123.0.160.0/19\n123.4.0.0/14\n123.8.0.0/13\n123.49.130.0/23\n123.49.132.0/22\n123.49.136.0/22\n123.49.152.0/21\n123.49.160.0/19\n123.49.192.0/18\n123.50.160.0/19\n123.52.0.0/14\n123.56.0.0/15\n123.58.0.0/18\n123.58.64.0/20\n123.58.80.0/21\n123.58.88.0/22\n123.58.96.0/19\n123.58.128.0/17\n123.59.0.0/16\n123.61.0.0/16\n123.62.0.0/16\n123.64.0.0/11\n123.96.0.0/15\n123.98.0.0/17\n123.99.128.0/17\n123.100.0.0/19\n123.100.232.0/24\n123.101.0.0/16\n123.103.0.0/20\n123.103.16.0/21\n123.103.24.0/22\n123.103.28.0/23\n123.103.30.0/24\n123.103.32.0/19\n123.103.64.0/18\n123.108.134.0/24\n123.108.138.0/23\n123.108.140.0/24\n123.108.142.0/24\n123.108.208.0/20\n123.112.0.0/12\n123.128.0.0/13\n123.137.0.0/16\n123.138.0.0/15\n123.144.0.0/12\n123.160.0.0/12\n123.176.60.0/22\n123.176.80.0/20\n123.177.0.0/16\n123.178.0.0/15\n123.180.0.0/14\n123.184.0.0/13\n123.196.0.0/15\n123.199.128.0/17\n123.206.0.0/15\n123.232.0.0/14\n123.242.0.0/17\n123.242.192.0/21\n123.244.0.0/14\n123.249.0.0/16\n123.253.109.0/24\n123.253.110.0/24\n123.253.240.0/22\n123.254.96.0/21\n124.6.64.0/18\n124.14.0.0/15\n124.16.0.0/15\n124.20.0.0/14\n124.28.192.0/18\n124.29.0.0/17\n124.31.0.0/16\n124.40.112.0/20\n124.40.128.0/18\n124.40.192.0/19\n124.40.240.0/22\n124.42.0.0/16\n124.47.0.0/18\n124.64.0.0/15\n124.66.0.0/17\n124.67.0.0/16\n124.68.0.0/17\n124.68.128.0/18\n124.68.192.0/19\n124.68.224.0/20\n124.68.240.0/23\n124.68.242.0/24\n124.68.244.0/23\n124.68.254.0/23\n124.69.0.0/16\n124.70.0.0/15\n124.72.0.0/13\n124.88.0.0/13\n124.108.8.0/21\n124.108.40.0/21\n124.109.96.0/21\n124.112.0.0/14\n124.116.0.0/15\n124.118.0.0/16\n124.119.0.0/17\n124.119.128.0/18\n124.119.192.0/19\n124.119.224.0/20\n124.119.240.0/22\n124.119.244.0/23\n124.119.246.0/25\n124.119.246.128/26\n124.119.246.192/27\n124.119.246.224/28\n124.119.246.240/29\n124.119.246.248/30\n124.119.246.254/31\n124.119.247.0/24\n124.119.248.0/21\n124.126.0.0/15\n124.128.0.0/13\n124.147.128.0/17\n124.150.137.0/24\n124.151.0.0/16\n124.152.0.0/16\n124.160.0.0/13\n124.172.0.0/14\n124.192.0.0/15\n124.196.0.0/16\n124.200.0.0/13\n124.220.0.0/14\n124.224.0.0/12\n124.240.0.0/17\n124.240.128.0/18\n124.242.0.0/16\n124.243.192.0/18\n124.248.0.0/17\n124.249.0.0/16\n124.250.0.0/15\n124.254.0.0/18\n125.31.192.0/18\n125.32.0.0/12\n125.58.128.0/17\n125.61.128.0/17\n125.62.0.0/18\n125.64.0.0/11\n125.96.0.0/15\n125.98.0.0/16\n125.104.0.0/13\n125.112.0.0/12\n125.169.0.0/16\n125.171.0.0/16\n125.208.0.0/19\n125.208.37.0/24\n125.208.40.0/24\n125.208.45.0/24\n125.208.46.0/23\n125.208.48.0/20\n125.210.0.0/15\n125.213.0.0/17\n125.214.96.0/19\n125.215.0.0/18\n125.216.0.0/13\n125.254.128.0/17\n128.108.0.0/16\n129.28.0.0/16\n129.204.0.0/16\n129.211.0.0/16\n129.223.254.0/24\n129.227.99.0/24\n130.36.146.0/23\n130.214.218.0/23\n131.228.96.0/24\n131.253.12.0/29\n131.253.12.80/28\n131.253.12.240/29\n132.232.0.0/16\n132.237.134.0/24\n132.237.150.0/24\n134.175.0.0/16\n135.159.208.0/20\n135.244.80.0/20\n137.59.59.0/24\n137.59.88.0/22\n138.32.244.0/22\n139.5.56.0/21\n139.5.80.0/22\n139.5.92.0/22\n139.5.128.0/22\n139.5.160.0/22\n139.5.192.0/22\n139.5.204.0/22\n139.5.244.0/22\n139.9.0.0/16\n139.129.0.0/16\n139.138.238.0/28\n139.148.0.0/16\n139.155.0.0/16\n139.159.0.0/19\n139.159.32.0/21\n139.159.40.0/22\n139.159.52.0/22\n139.159.56.0/21\n139.159.64.0/19\n139.159.96.0/20\n139.159.112.0/22\n139.159.116.0/23\n139.159.120.0/21\n139.159.128.0/17\n139.170.0.0/16\n139.176.0.0/16\n139.183.0.0/16\n139.186.0.0/16\n139.189.0.0/16\n139.196.0.0/15\n139.198.0.0/21\n139.198.8.0/23\n139.198.11.0/24\n139.198.12.0/22\n139.198.16.0/20\n139.198.32.0/19\n139.198.66.0/23\n139.198.68.0/22\n139.198.72.0/21\n139.198.80.0/20\n139.198.96.0/20\n139.198.113.0/24\n139.198.114.0/23\n139.198.116.0/22\n139.198.122.0/23\n139.198.124.0/22\n139.198.128.0/17\n139.199.0.0/16\n139.200.0.0/13\n139.208.0.0/13\n139.217.0.0/16\n139.219.0.0/16\n139.220.0.0/17\n139.220.128.0/18\n139.220.192.0/22\n139.220.196.0/23\n139.220.200.0/21\n139.220.208.0/23\n139.220.212.0/22\n139.220.216.0/21\n139.220.224.0/19\n139.221.0.0/16\n139.224.0.0/16\n139.226.0.0/15\n140.75.0.0/16\n140.101.208.0/24\n140.143.0.0/16\n140.179.0.0/16\n140.205.0.0/18\n140.205.64.0/19\n140.205.96.0/20\n140.205.112.0/21\n140.205.120.0/23\n140.205.123.0/24\n140.205.124.0/22\n140.205.128.0/17\n140.206.0.0/15\n140.210.0.0/16\n140.224.0.0/16\n140.237.0.0/16\n140.240.0.0/16\n140.242.223.0/24\n140.242.224.0/24\n140.243.0.0/16\n140.246.0.0/16\n140.249.0.0/16\n140.250.0.0/16\n140.255.0.0/16\n144.0.0.0/16\n144.7.0.0/16\n144.12.0.0/16\n144.36.146.0/23\n144.48.64.0/22\n144.48.88.0/22\n144.48.156.0/22\n144.48.180.0/22\n144.48.184.0/22\n144.48.204.0/22\n144.48.208.0/21\n144.52.0.0/16\n144.123.0.0/16\n144.211.80.0/24\n144.211.138.0/24\n144.255.0.0/16\n146.56.192.0/18\n146.196.56.0/22\n146.196.68.0/22\n146.196.92.0/22\n146.196.112.0/21\n146.196.124.0/22\n146.217.137.0/24\n146.222.79.0/24\n146.222.81.0/24\n146.222.94.0/24\n147.243.13.32/27\n147.243.13.64/27\n147.243.14.32/27\n148.70.0.0/16\n150.0.0.0/16\n150.115.0.0/16\n150.121.0.0/16\n150.122.0.0/16\n150.129.136.0/22\n150.129.192.0/22\n150.129.252.0/22\n150.138.0.0/15\n150.158.0.0/16\n150.222.88.0/23\n150.223.0.0/16\n150.242.0.0/21\n150.242.8.0/22\n150.242.28.0/22\n150.242.44.0/22\n150.242.48.0/21\n150.242.56.0/22\n150.242.76.0/22\n150.242.80.0/22\n150.242.92.0/22\n150.242.96.0/22\n150.242.112.0/21\n150.242.120.0/22\n150.242.152.0/22\n150.242.158.0/24\n150.242.160.0/21\n150.242.168.0/22\n150.242.184.0/21\n150.242.192.0/22\n150.242.224.0/22\n150.242.232.0/21\n150.242.240.0/21\n150.242.248.0/22\n150.255.0.0/16\n152.32.178.0/23\n152.104.128.0/17\n152.136.0.0/16\n153.0.0.0/16\n153.3.0.0/16\n153.34.0.0/15\n153.36.0.0/15\n153.99.0.0/16\n153.101.0.0/16\n153.118.0.0/15\n154.8.128.0/17\n155.126.176.0/23\n156.107.160.0/24\n156.107.170.0/24\n156.107.179.0/24\n156.107.181.0/24\n156.154.62.0/23\n157.0.0.0/16\n157.18.0.0/16\n157.61.0.0/16\n157.119.8.0/21\n157.119.16.0/22\n157.119.28.0/22\n157.119.132.0/22\n157.119.136.0/21\n157.119.144.0/20\n157.119.160.0/21\n157.119.172.0/22\n157.119.192.0/21\n157.119.240.0/22\n157.119.252.0/22\n157.122.0.0/16\n157.133.186.0/23\n157.133.192.0/21\n157.133.212.0/24\n157.133.236.0/24\n157.148.0.0/16\n157.156.0.0/16\n157.255.0.0/16\n159.75.0.0/16\n159.221.232.0/22\n159.226.0.0/16\n160.19.208.0/21\n160.19.216.0/22\n160.20.48.0/22\n160.62.10.0/24\n160.83.109.0/24\n160.83.110.0/23\n160.202.60.0/23\n160.202.62.0/24\n160.202.148.0/22\n160.202.152.0/22\n160.202.212.0/22\n160.202.216.0/21\n160.202.224.0/19\n160.238.64.0/22\n161.163.0.0/21\n161.163.28.0/23\n161.163.176.0/24\n161.163.178.0/23\n161.163.180.0/22\n161.189.0.0/16\n161.207.0.0/16\n162.14.0.0/16\n162.105.0.0/16\n163.0.0.0/16\n163.47.4.0/22\n163.53.0.0/20\n163.53.36.0/22\n163.53.40.0/22\n163.53.48.0/20\n163.53.64.0/22\n163.53.88.0/21\n163.53.96.0/19\n163.53.128.0/21\n163.53.136.0/22\n163.53.160.0/20\n163.53.188.0/22\n163.53.220.0/22\n163.53.236.0/22\n163.53.240.0/22\n163.116.202.0/23\n163.125.0.0/16\n163.142.0.0/16\n163.177.0.0/16\n163.179.0.0/16\n163.204.0.0/16\n163.244.246.0/24\n164.52.80.0/24\n165.156.30.0/24\n166.111.0.0/16\n167.139.0.0/16\n167.189.0.0/16\n167.220.244.0/22\n168.159.144.0/21\n168.159.152.0/22\n168.159.156.0/23\n168.159.158.0/24\n168.160.0.0/16\n168.230.0.0/24\n170.179.0.0/16\n170.225.224.0/23\n170.252.152.0/21\n171.8.0.0/13\n171.22.147.0/24\n171.34.0.0/15\n171.36.0.0/14\n171.40.0.0/13\n171.80.0.0/12\n171.104.0.0/13\n171.112.0.0/12\n171.208.0.0/12\n172.60.2.0/24\n172.81.192.0/18\n173.39.200.0/23\n175.0.0.0/12\n175.16.0.0/13\n175.24.0.0/14\n175.30.0.0/15\n175.42.0.0/15\n175.44.0.0/16\n175.46.0.0/15\n175.48.0.0/12\n175.64.0.0/11\n175.102.0.0/16\n175.106.128.0/17\n175.111.144.0/20\n175.111.160.0/20\n175.111.184.0/22\n175.146.0.0/15\n175.148.0.0/14\n175.152.0.0/14\n175.158.96.0/22\n175.160.0.0/12\n175.176.156.0/22\n175.176.188.0/22\n175.178.0.0/16\n175.184.128.0/18\n175.185.0.0/16\n175.186.0.0/15\n175.188.0.0/14\n180.76.16.0/20\n180.76.32.0/19\n180.76.64.0/18\n180.76.128.0/18\n180.76.192.0/19\n180.76.224.0/20\n180.76.240.0/24\n180.76.242.0/23\n180.76.244.0/22\n180.76.248.0/22\n180.76.252.0/23\n180.76.255.0/24\n180.77.0.0/16\n180.78.0.0/15\n180.84.0.0/15\n180.86.0.0/16\n180.88.0.0/14\n180.94.56.0/21\n180.94.96.0/20\n180.94.120.0/21\n180.95.128.0/17\n180.96.0.0/11\n180.129.128.0/17\n180.130.0.0/16\n180.136.0.0/13\n180.148.16.0/21\n180.148.152.0/21\n180.148.216.0/21\n180.148.224.0/19\n180.149.128.0/19\n180.150.160.0/21\n180.150.176.0/20\n180.152.0.0/13\n180.160.0.0/12\n180.178.112.0/21\n180.178.192.0/18\n180.184.0.0/14\n180.188.0.0/17\n180.189.148.0/22\n180.200.252.0/22\n180.201.0.0/16\n180.202.0.0/15\n180.208.0.0/15\n180.210.212.0/22\n180.210.233.0/24\n180.210.236.0/22\n180.212.0.0/15\n180.222.224.0/19\n180.223.0.0/19\n180.223.32.0/20\n180.223.48.0/21\n180.223.57.0/24\n180.223.58.0/23\n180.223.60.0/22\n180.223.80.0/20\n180.223.96.0/19\n180.223.128.0/17\n180.233.0.0/18\n180.233.64.0/19\n180.233.144.0/22\n180.235.64.0/19\n180.235.112.0/22\n182.16.144.0/21\n182.16.192.0/19\n182.18.0.0/17\n182.23.184.0/21\n182.23.200.0/21\n182.32.0.0/12\n182.48.96.0/19\n182.49.0.0/16\n182.50.0.0/22\n182.50.8.0/21\n182.50.112.0/20\n182.51.0.0/16\n182.54.0.0/17\n182.61.0.0/18\n182.61.128.0/19\n182.61.192.0/18\n182.80.0.0/13\n182.88.0.0/14\n182.92.0.0/16\n182.96.0.0/11\n182.128.0.0/12\n182.144.0.0/13\n182.157.0.0/16\n182.160.64.0/19\n182.174.0.0/15\n182.200.0.0/13\n182.236.128.0/17\n182.237.24.0/21\n182.238.0.0/16\n182.239.0.0/19\n182.240.0.0/13\n182.254.0.0/17\n182.254.128.0/18\n182.254.192.0/19\n182.254.224.0/20\n182.254.240.0/21\n182.254.248.0/23\n182.254.251.0/24\n182.254.252.0/22\n183.0.0.0/10\n183.64.0.0/13\n183.78.160.0/21\n183.78.180.0/22\n183.81.180.0/22\n183.84.0.0/15\n183.91.128.0/22\n183.91.136.0/21\n183.91.144.0/20\n183.92.0.0/14\n183.128.0.0/11\n183.160.0.0/13\n183.168.0.0/15\n183.170.0.0/16\n183.172.0.0/14\n183.184.0.0/13\n183.192.0.0/10\n185.109.236.0/24\n185.216.118.0/24\n188.131.128.0/17\n192.11.23.0/24\n192.11.26.0/24\n192.11.39.0/24\n192.11.236.0/24\n192.23.191.0/24\n192.55.10.0/23\n192.55.40.0/24\n192.55.46.0/24\n192.55.68.0/22\n192.102.204.0/22\n192.124.154.0/24\n192.137.31.0/24\n192.139.136.0/24\n192.140.128.0/21\n192.140.136.0/22\n192.140.156.0/22\n192.140.160.0/19\n192.140.192.0/20\n192.140.208.0/21\n192.144.128.0/17\n192.163.11.0/24\n192.232.97.0/24\n193.9.22.0/24\n193.17.120.0/22\n193.20.64.0/22\n193.112.0.0/16\n193.200.196.0/24\n193.200.222.160/28\n194.138.136.0/24\n194.138.202.0/23\n194.138.245.0/24\n198.175.100.0/22\n198.208.17.0/24\n198.208.19.0/24\n199.7.72.0/24\n199.65.192.0/21\n199.244.144.0/24\n202.0.100.0/23\n202.0.122.0/23\n202.1.105.0/24\n202.1.106.0/24\n202.3.128.0/23\n202.4.128.0/19\n202.4.252.0/22\n202.5.208.0/21\n202.5.216.0/22\n202.6.6.0/23\n202.6.66.0/23\n202.6.72.0/23\n202.6.87.0/24\n202.6.88.0/23\n202.6.92.0/23\n202.6.103.0/24\n202.6.108.0/24\n202.6.110.0/23\n202.6.114.0/24\n202.6.176.0/20\n202.8.0.0/24\n202.8.2.0/23\n202.8.4.0/23\n202.8.12.0/24\n202.8.24.0/24\n202.8.77.0/24\n202.8.128.0/19\n202.8.192.0/20\n202.9.32.0/24\n202.9.34.0/23\n202.9.48.0/23\n202.9.51.0/24\n202.9.52.0/23\n202.9.54.0/24\n202.9.57.0/24\n202.9.58.0/23\n202.10.64.0/21\n202.10.74.0/23\n202.10.76.0/22\n202.10.112.0/20\n202.12.1.0/24\n202.12.2.0/24\n202.12.17.0/24\n202.12.18.0/23\n202.12.72.0/24\n202.12.84.0/23\n202.12.96.0/24\n202.12.98.0/23\n202.12.106.0/24\n202.12.111.0/24\n202.12.116.0/24\n202.14.64.0/23\n202.14.69.0/24\n202.14.73.0/24\n202.14.74.0/23\n202.14.76.0/24\n202.14.78.0/23\n202.14.88.0/24\n202.14.97.0/24\n202.14.104.0/23\n202.14.108.0/23\n202.14.111.0/24\n202.14.114.0/23\n202.14.118.0/23\n202.14.124.0/23\n202.14.127.0/24\n202.14.129.0/24\n202.14.135.0/24\n202.14.136.0/24\n202.14.149.0/24\n202.14.151.0/24\n202.14.157.0/24\n202.14.158.0/23\n202.14.169.0/24\n202.14.170.0/23\n202.14.172.0/22\n202.14.176.0/24\n202.14.184.0/23\n202.14.208.0/23\n202.14.213.0/24\n202.14.219.0/24\n202.14.220.0/24\n202.14.222.0/23\n202.14.225.0/24\n202.14.226.0/23\n202.14.231.0/24\n202.14.235.0/24\n202.14.236.0/22\n202.14.246.0/24\n202.14.251.0/24\n202.20.66.0/24\n202.20.79.0/24\n202.20.87.0/24\n202.20.88.0/23\n202.20.90.0/24\n202.20.94.0/23\n202.20.114.0/24\n202.20.117.0/24\n202.20.120.0/24\n202.20.125.0/24\n202.20.126.0/23\n202.21.48.0/20\n202.21.131.0/24\n202.21.132.0/24\n202.21.141.0/24\n202.21.142.0/24\n202.21.147.0/24\n202.21.148.0/24\n202.21.150.0/23\n202.21.152.0/23\n202.21.154.0/24\n202.21.156.0/24\n202.21.208.0/24\n202.22.248.0/21\n202.27.12.0/24\n202.27.14.0/24\n202.27.136.0/23\n202.36.226.0/24\n202.38.0.0/22\n202.38.8.0/21\n202.38.48.0/20\n202.38.64.0/18\n202.38.128.0/21\n202.38.136.0/23\n202.38.138.0/24\n202.38.140.0/22\n202.38.146.0/23\n202.38.149.0/24\n202.38.150.0/23\n202.38.152.0/22\n202.38.156.0/24\n202.38.158.0/23\n202.38.160.0/23\n202.38.164.0/22\n202.38.168.0/22\n202.38.176.0/23\n202.38.184.0/21\n202.38.192.0/18\n202.40.4.0/23\n202.40.7.0/24\n202.40.15.0/24\n202.40.135.0/24\n202.40.136.0/24\n202.40.140.0/24\n202.40.143.0/24\n202.40.144.0/23\n202.40.150.0/24\n202.40.155.0/24\n202.40.156.0/24\n202.40.158.0/23\n202.40.162.0/24\n202.41.8.0/23\n202.41.11.0/24\n202.41.12.0/23\n202.41.128.0/24\n202.41.130.0/23\n202.41.142.0/24\n202.41.152.0/21\n202.41.192.0/24\n202.41.196.0/22\n202.41.200.0/22\n202.41.240.0/20\n202.43.76.0/22\n202.43.144.0/20\n202.44.16.0/20\n202.44.48.0/22\n202.44.67.0/24\n202.44.74.0/24\n202.44.97.0/24\n202.44.129.0/24\n202.44.132.0/23\n202.44.146.0/23\n202.45.0.0/23\n202.45.2.0/24\n202.45.15.0/24\n202.45.16.0/20\n202.46.16.0/23\n202.46.18.0/24\n202.46.20.0/23\n202.46.128.0/24\n202.46.224.0/20\n202.47.82.0/23\n202.47.96.0/20\n202.47.126.0/24\n202.47.128.0/24\n202.47.130.0/23\n202.52.34.0/24\n202.52.143.0/24\n202.53.140.0/24\n202.53.143.0/24\n202.53.202.0/24\n202.57.212.0/22\n202.57.216.0/22\n202.57.240.0/20\n202.58.0.0/24\n202.58.112.0/22\n202.59.0.0/23\n202.59.212.0/22\n202.59.236.0/24\n202.59.240.0/24\n202.60.48.0/21\n202.60.96.0/21\n202.60.112.0/20\n202.60.132.0/22\n202.60.136.0/21\n202.60.144.0/20\n202.61.68.0/22\n202.61.76.0/22\n202.61.88.0/22\n202.61.123.0/24\n202.61.127.0/24\n202.62.112.0/22\n202.62.248.0/22\n202.62.252.0/24\n202.62.255.0/24\n202.63.80.0/20\n202.63.160.0/19\n202.63.248.0/22\n202.63.253.0/24\n202.65.0.0/21\n202.65.8.0/23\n202.67.0.0/22\n202.69.4.0/23\n202.69.16.0/20\n202.70.0.0/19\n202.70.96.0/20\n202.70.192.0/20\n202.71.32.0/20\n202.72.40.0/21\n202.72.80.0/20\n202.72.112.0/20\n202.73.128.0/22\n202.73.240.0/20\n202.74.8.0/21\n202.74.36.0/24\n202.74.42.0/24\n202.74.52.0/24\n202.74.80.0/20\n202.74.254.0/23\n202.75.208.0/20\n202.75.252.0/22\n202.76.247.0/24\n202.76.252.0/22\n202.77.80.0/21\n202.77.92.0/22\n202.78.8.0/21\n202.79.224.0/21\n202.79.248.0/22\n202.80.192.0/20\n202.81.0.0/22\n202.81.176.0/20\n202.83.252.0/22\n202.84.0.0/20\n202.84.16.0/23\n202.84.22.0/24\n202.84.24.0/21\n202.85.208.0/20\n202.86.249.0/24\n202.87.80.0/20\n202.88.32.0/22\n202.89.8.0/21\n202.89.96.0/22\n202.89.108.0/22\n202.89.119.0/24\n202.89.232.0/21\n202.90.0.0/22\n202.90.16.0/20\n202.90.37.0/24\n202.90.96.0/19\n202.90.193.0/24\n202.90.196.0/24\n202.90.205.0/24\n202.90.224.0/20\n202.91.0.0/22\n202.91.96.0/20\n202.91.128.0/22\n202.91.176.0/20\n202.91.224.0/19\n202.92.0.0/22\n202.92.8.0/21\n202.92.48.0/20\n202.92.252.0/22\n202.93.0.0/22\n202.93.252.0/22\n202.94.0.0/19\n202.94.74.0/24\n202.94.81.0/24\n202.94.92.0/22\n202.95.240.0/21\n202.95.252.0/22\n202.96.0.0/12\n202.112.0.0/13\n202.120.0.0/15\n202.122.0.0/21\n202.122.32.0/21\n202.122.64.0/19\n202.122.112.0/20\n202.122.128.0/24\n202.122.132.0/24\n202.123.96.0/20\n202.123.116.0/22\n202.123.120.0/22\n202.124.16.0/21\n202.124.24.0/22\n202.125.107.0/24\n202.125.109.0/24\n202.125.112.0/20\n202.125.176.0/20\n202.127.0.0/21\n202.127.12.0/22\n202.127.16.0/20\n202.127.40.0/21\n202.127.48.0/20\n202.127.112.0/20\n202.127.128.0/19\n202.127.160.0/21\n202.127.192.0/20\n202.127.208.0/23\n202.127.212.0/22\n202.127.216.0/21\n202.127.224.0/19\n202.129.208.0/24\n202.130.0.0/19\n202.130.39.0/24\n202.130.224.0/19\n202.131.16.0/21\n202.131.59.0/24\n202.131.208.0/20\n202.133.32.0/20\n202.134.58.0/24\n202.134.128.0/20\n202.134.208.0/20\n202.136.48.0/20\n202.136.208.0/20\n202.136.224.0/20\n202.136.248.0/22\n202.136.254.0/23\n202.137.231.0/24\n202.140.140.0/22\n202.140.144.0/20\n202.141.160.0/19\n202.142.16.0/20\n202.143.4.0/22\n202.143.16.0/20\n202.143.32.0/20\n202.143.56.0/21\n202.143.100.0/22\n202.143.104.0/22\n202.146.160.0/20\n202.146.186.0/24\n202.146.188.0/22\n202.146.196.0/22\n202.146.200.0/21\n202.147.144.0/20\n202.148.32.0/20\n202.148.64.0/18\n202.149.32.0/19\n202.149.160.0/19\n202.149.224.0/19\n202.150.16.0/20\n202.150.32.0/20\n202.150.56.0/22\n202.150.192.0/20\n202.150.224.0/19\n202.151.0.0/22\n202.151.128.0/19\n202.152.176.0/20\n202.153.0.0/22\n202.153.7.0/24\n202.153.48.0/20\n202.157.192.0/19\n202.158.160.0/19\n202.158.242.0/24\n202.160.140.0/22\n202.160.156.0/22\n202.160.176.0/20\n202.162.67.0/24\n202.162.75.0/24\n202.164.0.0/20\n202.164.96.0/19\n202.165.176.0/20\n202.165.208.0/20\n202.165.239.0/24\n202.165.240.0/23\n202.165.243.0/24\n202.165.245.0/24\n202.165.251.0/24\n202.165.252.0/22\n202.166.224.0/19\n202.168.80.0/22\n202.168.128.0/20\n202.168.160.0/19\n202.170.128.0/19\n202.170.216.0/21\n202.170.224.0/19\n202.171.216.0/21\n202.171.232.0/24\n202.171.235.0/24\n202.172.0.0/22\n202.172.7.0/24\n202.173.0.0/22\n202.173.6.0/24\n202.173.8.0/21\n202.173.112.0/22\n202.173.224.0/19\n202.174.64.0/20\n202.174.124.0/22\n202.176.224.0/19\n202.179.160.0/20\n202.179.240.0/20\n202.180.128.0/19\n202.180.208.0/21\n202.181.8.0/22\n202.181.28.0/22\n202.181.112.0/20\n202.182.32.0/20\n202.182.192.0/19\n202.189.0.0/18\n202.189.80.0/20\n202.189.184.0/21\n202.191.0.0/24\n202.191.68.0/22\n202.191.72.0/21\n202.191.80.0/20\n202.192.0.0/12\n203.0.4.0/22\n203.0.10.0/23\n203.0.18.0/24\n203.0.24.0/24\n203.0.42.0/23\n203.0.45.0/24\n203.0.46.0/23\n203.0.81.0/24\n203.0.82.0/23\n203.0.90.0/23\n203.0.96.0/23\n203.0.104.0/21\n203.0.114.0/23\n203.0.122.0/24\n203.0.128.0/24\n203.0.130.0/23\n203.0.132.0/22\n203.0.137.0/24\n203.0.142.0/24\n203.0.144.0/24\n203.0.146.0/24\n203.0.148.0/24\n203.0.150.0/23\n203.0.152.0/24\n203.0.177.0/24\n203.0.224.0/24\n203.1.4.0/22\n203.1.18.0/24\n203.1.26.0/23\n203.1.65.0/24\n203.1.66.0/23\n203.1.70.0/23\n203.1.76.0/23\n203.1.90.0/24\n203.1.97.0/24\n203.1.98.0/23\n203.1.100.0/22\n203.1.108.0/24\n203.1.253.0/24\n203.1.254.0/24\n203.2.64.0/21\n203.2.73.0/24\n203.2.112.0/21\n203.2.126.0/23\n203.2.140.0/24\n203.2.150.0/24\n203.2.152.0/22\n203.2.156.0/23\n203.2.160.0/21\n203.2.180.0/23\n203.2.196.0/23\n203.2.209.0/24\n203.2.214.0/23\n203.2.226.0/23\n203.2.229.0/24\n203.2.236.0/23\n203.3.68.0/24\n203.3.72.0/23\n203.3.75.0/24\n203.3.80.0/21\n203.3.96.0/22\n203.3.105.0/24\n203.3.112.0/21\n203.3.120.0/24\n203.3.123.0/24\n203.3.135.0/24\n203.3.139.0/24\n203.3.143.0/24\n203.4.132.0/23\n203.4.134.0/24\n203.4.151.0/24\n203.4.152.0/22\n203.4.174.0/23\n203.4.180.0/24\n203.4.186.0/24\n203.4.205.0/24\n203.4.208.0/22\n203.4.227.0/24\n203.4.230.0/23\n203.5.4.0/23\n203.5.7.0/24\n203.5.8.0/23\n203.5.11.0/24\n203.5.21.0/24\n203.5.22.0/24\n203.5.44.0/24\n203.5.46.0/23\n203.5.52.0/22\n203.5.56.0/23\n203.5.60.0/23\n203.5.114.0/23\n203.5.118.0/24\n203.5.120.0/24\n203.5.172.0/24\n203.5.180.0/23\n203.5.182.0/24\n203.5.185.0/24\n203.5.186.0/24\n203.5.188.0/23\n203.5.190.0/24\n203.5.195.0/24\n203.5.214.0/23\n203.5.218.0/23\n203.6.131.0/24\n203.6.136.0/24\n203.6.138.0/23\n203.6.142.0/24\n203.6.150.0/23\n203.6.157.0/24\n203.6.159.0/24\n203.6.224.0/20\n203.6.248.0/23\n203.7.129.0/24\n203.7.138.0/23\n203.7.147.0/24\n203.7.150.0/23\n203.7.158.0/24\n203.7.192.0/23\n203.7.200.0/24\n203.8.0.0/24\n203.8.8.0/24\n203.8.23.0/24\n203.8.70.0/24\n203.8.82.0/24\n203.8.86.0/23\n203.8.91.0/24\n203.8.110.0/23\n203.8.115.0/24\n203.8.166.0/23\n203.8.169.0/24\n203.8.173.0/24\n203.8.184.0/24\n203.8.186.0/23\n203.8.190.0/23\n203.8.192.0/24\n203.8.197.0/24\n203.8.198.0/23\n203.8.203.0/24\n203.8.209.0/24\n203.8.210.0/23\n203.8.212.0/22\n203.8.217.0/24\n203.8.220.0/24\n203.9.32.0/24\n203.9.36.0/23\n203.9.57.0/24\n203.9.63.0/24\n203.9.65.0/24\n203.9.70.0/23\n203.9.72.0/24\n203.9.75.0/24\n203.9.76.0/23\n203.9.96.0/22\n203.9.100.0/23\n203.9.108.0/24\n203.9.158.0/24\n203.10.34.0/24\n203.10.56.0/24\n203.10.74.0/23\n203.10.84.0/22\n203.10.88.0/24\n203.10.95.0/24\n203.10.125.0/24\n203.11.70.0/24\n203.11.76.0/22\n203.11.82.0/24\n203.11.84.0/22\n203.11.100.0/22\n203.11.109.0/24\n203.11.117.0/24\n203.11.122.0/24\n203.11.126.0/24\n203.11.136.0/22\n203.11.141.0/24\n203.11.142.0/23\n203.11.180.0/22\n203.11.208.0/22\n203.12.16.0/24\n203.12.19.0/24\n203.12.24.0/24\n203.12.57.0/24\n203.12.65.0/24\n203.12.66.0/24\n203.12.70.0/23\n203.12.87.0/24\n203.12.90.0/24\n203.12.92.0/22\n203.12.100.0/23\n203.12.103.0/24\n203.12.114.0/24\n203.12.118.0/24\n203.12.130.0/24\n203.12.137.0/24\n203.12.196.0/22\n203.12.211.0/24\n203.12.219.0/24\n203.12.226.0/24\n203.12.240.0/22\n203.13.18.0/24\n203.13.24.0/24\n203.13.44.0/23\n203.13.88.0/23\n203.13.92.0/22\n203.13.173.0/24\n203.13.224.0/23\n203.13.227.0/24\n203.13.233.0/24\n203.14.24.0/22\n203.14.33.0/24\n203.14.56.0/24\n203.14.61.0/24\n203.14.62.0/24\n203.14.104.0/24\n203.14.114.0/23\n203.14.118.0/24\n203.14.162.0/24\n203.14.184.0/21\n203.14.192.0/24\n203.14.194.0/23\n203.14.214.0/24\n203.14.231.0/24\n203.14.246.0/24\n203.15.0.0/20\n203.15.20.0/23\n203.15.22.0/24\n203.15.87.0/24\n203.15.88.0/23\n203.15.105.0/24\n203.15.112.0/21\n203.15.130.0/23\n203.15.149.0/24\n203.15.151.0/24\n203.15.156.0/22\n203.15.174.0/24\n203.15.227.0/24\n203.15.232.0/22\n203.15.238.0/23\n203.15.240.0/23\n203.15.246.0/24\n203.16.10.0/24\n203.16.12.0/23\n203.16.16.0/21\n203.16.27.0/24\n203.16.38.0/24\n203.16.49.0/24\n203.16.50.0/23\n203.16.58.0/24\n203.16.63.0/24\n203.16.133.0/24\n203.16.161.0/24\n203.16.162.0/24\n203.16.186.0/23\n203.16.228.0/24\n203.16.238.0/24\n203.16.240.0/24\n203.16.245.0/24\n203.17.2.0/24\n203.17.18.0/24\n203.17.28.0/24\n203.17.39.0/24\n203.17.56.0/24\n203.17.74.0/23\n203.17.88.0/23\n203.17.136.0/24\n203.17.164.0/24\n203.17.187.0/24\n203.17.190.0/23\n203.17.231.0/24\n203.17.233.0/24\n203.17.248.0/23\n203.17.255.0/24\n203.18.2.0/23\n203.18.4.0/24\n203.18.7.0/24\n203.18.31.0/24\n203.18.37.0/24\n203.18.48.0/23\n203.18.52.0/24\n203.18.72.0/22\n203.18.80.0/23\n203.18.87.0/24\n203.18.100.0/23\n203.18.105.0/24\n203.18.107.0/24\n203.18.110.0/24\n203.18.129.0/24\n203.18.131.0/24\n203.18.132.0/23\n203.18.144.0/24\n203.18.153.0/24\n203.18.199.0/24\n203.18.208.0/24\n203.18.211.0/24\n203.18.215.0/24\n203.19.1.0/24\n203.19.18.0/24\n203.19.24.0/24\n203.19.30.0/24\n203.19.41.0/24\n203.19.44.0/23\n203.19.46.0/24\n203.19.58.0/24\n203.19.60.0/23\n203.19.64.0/24\n203.19.68.0/24\n203.19.72.0/24\n203.19.101.0/24\n203.19.111.0/24\n203.19.131.0/24\n203.19.133.0/24\n203.19.144.0/24\n203.19.147.0/24\n203.19.149.0/24\n203.19.156.0/24\n203.19.176.0/24\n203.19.178.0/23\n203.19.208.0/24\n203.19.228.0/22\n203.19.233.0/24\n203.19.242.0/24\n203.19.248.0/23\n203.19.255.0/24\n203.20.17.0/24\n203.20.40.0/23\n203.20.44.0/24\n203.20.48.0/24\n203.20.61.0/24\n203.20.65.0/24\n203.20.84.0/23\n203.20.89.0/24\n203.20.106.0/23\n203.20.115.0/24\n203.20.117.0/24\n203.20.118.0/23\n203.20.122.0/24\n203.20.126.0/23\n203.20.135.0/24\n203.20.140.0/22\n203.20.150.0/24\n203.20.230.0/24\n203.20.232.0/24\n203.20.236.0/24\n203.21.0.0/23\n203.21.2.0/24\n203.21.8.0/24\n203.21.10.0/24\n203.21.18.0/24\n203.21.33.0/24\n203.21.34.0/24\n203.21.41.0/24\n203.21.44.0/24\n203.21.68.0/24\n203.21.82.0/24\n203.21.96.0/22\n203.21.124.0/24\n203.21.136.0/23\n203.21.145.0/24\n203.21.206.0/24\n203.22.24.0/24\n203.22.28.0/23\n203.22.31.0/24\n203.22.68.0/24\n203.22.76.0/24\n203.22.84.0/24\n203.22.87.0/24\n203.22.92.0/22\n203.22.99.0/24\n203.22.106.0/24\n203.22.122.0/23\n203.22.131.0/24\n203.22.163.0/24\n203.22.166.0/24\n203.22.170.0/24\n203.22.176.0/21\n203.22.194.0/24\n203.22.242.0/23\n203.22.245.0/24\n203.22.246.0/24\n203.22.252.0/23\n203.23.0.0/24\n203.23.47.0/24\n203.23.61.0/24\n203.23.62.0/23\n203.23.73.0/24\n203.23.85.0/24\n203.23.92.0/22\n203.23.98.0/24\n203.23.107.0/24\n203.23.112.0/24\n203.23.130.0/24\n203.23.140.0/23\n203.23.172.0/24\n203.23.182.0/24\n203.23.186.0/23\n203.23.192.0/24\n203.23.197.0/24\n203.23.198.0/24\n203.23.204.0/22\n203.23.224.0/24\n203.23.226.0/23\n203.23.228.0/22\n203.23.249.0/24\n203.23.251.0/24\n203.24.13.0/24\n203.24.18.0/24\n203.24.27.0/24\n203.24.43.0/24\n203.24.56.0/24\n203.24.58.0/24\n203.24.67.0/24\n203.24.74.0/24\n203.24.79.0/24\n203.24.80.0/23\n203.24.84.0/23\n203.24.86.0/24\n203.24.90.0/24\n203.24.111.0/24\n203.24.112.0/24\n203.24.116.0/24\n203.24.122.0/23\n203.24.145.0/24\n203.24.152.0/23\n203.24.157.0/24\n203.24.161.0/24\n203.24.167.0/24\n203.24.186.0/23\n203.24.199.0/24\n203.24.202.0/24\n203.24.212.0/23\n203.24.217.0/24\n203.24.219.0/24\n203.24.244.0/24\n203.25.19.0/24\n203.25.20.0/23\n203.25.46.0/24\n203.25.64.0/23\n203.25.91.0/24\n203.25.99.0/24\n203.25.100.0/24\n203.25.106.0/24\n203.25.131.0/24\n203.25.135.0/24\n203.25.138.0/24\n203.25.147.0/24\n203.25.153.0/24\n203.25.154.0/23\n203.25.164.0/24\n203.25.166.0/24\n203.25.174.0/23\n203.25.180.0/24\n203.25.182.0/24\n203.25.191.0/24\n203.25.199.0/24\n203.25.200.0/24\n203.25.202.0/23\n203.25.208.0/20\n203.25.229.0/24\n203.25.235.0/24\n203.25.236.0/24\n203.25.242.0/24\n203.26.12.0/24\n203.26.34.0/24\n203.26.49.0/24\n203.26.50.0/24\n203.26.55.0/24\n203.26.56.0/23\n203.26.60.0/24\n203.26.65.0/24\n203.26.68.0/24\n203.26.76.0/24\n203.26.80.0/24\n203.26.84.0/24\n203.26.97.0/24\n203.26.102.0/23\n203.26.115.0/24\n203.26.116.0/24\n203.26.129.0/24\n203.26.143.0/24\n203.26.144.0/24\n203.26.148.0/23\n203.26.154.0/24\n203.26.158.0/23\n203.26.161.0/24\n203.26.170.0/24\n203.26.173.0/24\n203.26.176.0/24\n203.26.185.0/24\n203.26.202.0/23\n203.26.210.0/24\n203.26.214.0/24\n203.26.222.0/24\n203.26.224.0/24\n203.26.228.0/24\n203.26.232.0/24\n203.27.0.0/24\n203.27.10.0/24\n203.27.15.0/24\n203.27.16.0/24\n203.27.20.0/24\n203.27.22.0/23\n203.27.40.0/24\n203.27.45.0/24\n203.27.53.0/24\n203.27.65.0/24\n203.27.66.0/24\n203.27.81.0/24\n203.27.88.0/24\n203.27.102.0/24\n203.27.109.0/24\n203.27.117.0/24\n203.27.121.0/24\n203.27.122.0/23\n203.27.125.0/24\n203.27.200.0/24\n203.27.202.0/24\n203.27.233.0/24\n203.27.241.0/24\n203.27.250.0/24\n203.28.10.0/24\n203.28.12.0/24\n203.28.33.0/24\n203.28.34.0/23\n203.28.43.0/24\n203.28.44.0/24\n203.28.54.0/24\n203.28.56.0/24\n203.28.73.0/24\n203.28.74.0/24\n203.28.76.0/24\n203.28.86.0/24\n203.28.88.0/24\n203.28.112.0/24\n203.28.131.0/24\n203.28.136.0/24\n203.28.140.0/24\n203.28.145.0/24\n203.28.165.0/24\n203.28.169.0/24\n203.28.170.0/24\n203.28.178.0/23\n203.28.185.0/24\n203.28.187.0/24\n203.28.196.0/24\n203.28.226.0/23\n203.28.239.0/24\n203.29.2.0/24\n203.29.8.0/23\n203.29.13.0/24\n203.29.14.0/24\n203.29.28.0/24\n203.29.46.0/24\n203.29.57.0/24\n203.29.61.0/24\n203.29.63.0/24\n203.29.69.0/24\n203.29.73.0/24\n203.29.81.0/24\n203.29.90.0/24\n203.29.95.0/24\n203.29.100.0/24\n203.29.103.0/24\n203.29.112.0/24\n203.29.120.0/22\n203.29.182.0/23\n203.29.187.0/24\n203.29.189.0/24\n203.29.190.0/24\n203.29.205.0/24\n203.29.210.0/24\n203.29.217.0/24\n203.29.227.0/24\n203.29.231.0/24\n203.29.233.0/24\n203.29.234.0/24\n203.29.248.0/24\n203.29.254.0/23\n203.30.16.0/23\n203.30.25.0/24\n203.30.29.0/24\n203.30.66.0/24\n203.30.81.0/24\n203.30.87.0/24\n203.30.111.0/24\n203.30.121.0/24\n203.30.123.0/24\n203.30.152.0/24\n203.30.156.0/24\n203.30.162.0/24\n203.30.173.0/24\n203.30.175.0/24\n203.30.187.0/24\n203.30.194.0/24\n203.30.217.0/24\n203.30.220.0/24\n203.30.222.0/24\n203.30.232.0/23\n203.30.235.0/24\n203.30.240.0/23\n203.30.246.0/24\n203.30.250.0/23\n203.31.45.0/24\n203.31.46.0/24\n203.31.49.0/24\n203.31.51.0/24\n203.31.54.0/23\n203.31.69.0/24\n203.31.72.0/24\n203.31.80.0/24\n203.31.85.0/24\n203.31.97.0/24\n203.31.105.0/24\n203.31.106.0/24\n203.31.108.0/23\n203.31.124.0/24\n203.31.162.0/24\n203.31.174.0/24\n203.31.177.0/24\n203.31.181.0/24\n203.31.187.0/24\n203.31.189.0/24\n203.31.204.0/24\n203.31.220.0/24\n203.31.222.0/23\n203.31.225.0/24\n203.31.229.0/24\n203.31.248.0/23\n203.31.253.0/24\n203.32.20.0/24\n203.32.48.0/23\n203.32.56.0/24\n203.32.60.0/24\n203.32.62.0/24\n203.32.68.0/23\n203.32.76.0/24\n203.32.81.0/24\n203.32.84.0/23\n203.32.95.0/24\n203.32.102.0/24\n203.32.105.0/24\n203.32.130.0/24\n203.32.133.0/24\n203.32.140.0/24\n203.32.152.0/24\n203.32.186.0/23\n203.32.192.0/24\n203.32.196.0/24\n203.32.203.0/24\n203.32.204.0/23\n203.32.212.0/24\n203.33.4.0/24\n203.33.7.0/24\n203.33.12.0/23\n203.33.21.0/24\n203.33.26.0/24\n203.33.32.0/24\n203.33.63.0/24\n203.33.64.0/24\n203.33.67.0/24\n203.33.68.0/24\n203.33.73.0/24\n203.33.79.0/24\n203.33.100.0/24\n203.33.122.0/24\n203.33.129.0/24\n203.33.131.0/24\n203.33.145.0/24\n203.33.156.0/24\n203.33.158.0/23\n203.33.174.0/24\n203.33.185.0/24\n203.33.200.0/24\n203.33.202.0/23\n203.33.204.0/24\n203.33.206.0/23\n203.33.214.0/23\n203.33.224.0/23\n203.33.226.0/24\n203.33.233.0/24\n203.33.243.0/24\n203.33.250.0/24\n203.34.4.0/24\n203.34.21.0/24\n203.34.27.0/24\n203.34.39.0/24\n203.34.48.0/23\n203.34.54.0/24\n203.34.56.0/23\n203.34.67.0/24\n203.34.69.0/24\n203.34.76.0/24\n203.34.92.0/24\n203.34.106.0/24\n203.34.113.0/24\n203.34.147.0/24\n203.34.150.0/24\n203.34.152.0/23\n203.34.161.0/24\n203.34.162.0/24\n203.34.187.0/24\n203.34.192.0/21\n203.34.204.0/22\n203.34.232.0/24\n203.34.240.0/24\n203.34.242.0/24\n203.34.245.0/24\n203.34.251.0/24\n203.55.2.0/23\n203.55.4.0/24\n203.55.10.0/24\n203.55.13.0/24\n203.55.22.0/24\n203.55.30.0/24\n203.55.93.0/24\n203.55.101.0/24\n203.55.109.0/24\n203.55.110.0/24\n203.55.116.0/23\n203.55.119.0/24\n203.55.128.0/23\n203.55.146.0/23\n203.55.192.0/24\n203.55.196.0/24\n203.55.218.0/23\n203.55.221.0/24\n203.55.224.0/24\n203.56.1.0/24\n203.56.4.0/24\n203.56.12.0/24\n203.56.24.0/24\n203.56.38.0/24\n203.56.40.0/24\n203.56.46.0/24\n203.56.50.0/23\n203.56.52.0/22\n203.56.68.0/23\n203.56.82.0/23\n203.56.84.0/23\n203.56.95.0/24\n203.56.110.0/24\n203.56.121.0/24\n203.56.161.0/24\n203.56.169.0/24\n203.56.172.0/23\n203.56.175.0/24\n203.56.183.0/24\n203.56.185.0/24\n203.56.187.0/24\n203.56.192.0/24\n203.56.198.0/24\n203.56.201.0/24\n203.56.208.0/23\n203.56.210.0/24\n203.56.214.0/24\n203.56.216.0/24\n203.56.227.0/24\n203.56.228.0/24\n203.56.232.0/24\n203.56.240.0/24\n203.56.252.0/24\n203.56.254.0/24\n203.57.5.0/24\n203.57.6.0/24\n203.57.12.0/23\n203.57.28.0/24\n203.57.39.0/24\n203.57.46.0/24\n203.57.58.0/24\n203.57.61.0/24\n203.57.66.0/24\n203.57.69.0/24\n203.57.70.0/23\n203.57.73.0/24\n203.57.90.0/24\n203.57.101.0/24\n203.57.109.0/24\n203.57.123.0/24\n203.57.157.0/24\n203.57.200.0/24\n203.57.202.0/24\n203.57.206.0/24\n203.57.222.0/24\n203.57.224.0/20\n203.57.246.0/23\n203.57.249.0/24\n203.57.253.0/24\n203.57.254.0/23\n203.62.2.0/24\n203.62.131.0/24\n203.62.139.0/24\n203.62.161.0/24\n203.62.197.0/24\n203.62.228.0/22\n203.62.234.0/24\n203.62.246.0/24\n203.65.240.0/22\n203.76.160.0/22\n203.76.168.0/22\n203.76.208.0/21\n203.76.216.0/22\n203.76.240.0/22\n203.77.180.0/22\n203.78.48.0/20\n203.78.156.0/22\n203.79.0.0/20\n203.80.4.0/23\n203.80.32.0/20\n203.80.57.0/24\n203.80.129.0/24\n203.80.132.0/22\n203.80.140.0/22\n203.80.144.0/20\n203.81.0.0/21\n203.81.16.0/20\n203.81.244.0/22\n203.82.0.0/23\n203.82.16.0/21\n203.82.112.0/20\n203.82.224.0/20\n203.83.0.0/22\n203.83.12.0/22\n203.83.56.0/21\n203.83.224.0/20\n203.86.0.0/18\n203.86.64.0/19\n203.86.250.0/24\n203.86.254.0/23\n203.88.32.0/19\n203.88.100.0/22\n203.88.192.0/19\n203.89.0.0/22\n203.89.100.0/22\n203.89.136.0/22\n203.89.144.0/24\n203.90.0.0/22\n203.90.8.0/21\n203.90.128.0/18\n203.90.192.0/19\n203.91.32.0/19\n203.91.96.0/20\n203.91.120.0/21\n203.92.0.0/22\n203.92.6.0/24\n203.92.160.0/19\n203.93.0.0/16\n203.94.0.0/19\n203.95.0.0/21\n203.95.96.0/19\n203.95.128.0/18\n203.95.200.0/21\n203.95.208.0/22\n203.95.224.0/19\n203.99.8.0/21\n203.99.16.0/22\n203.99.30.0/23\n203.99.80.0/20\n203.100.32.0/20\n203.100.58.0/24\n203.100.60.0/24\n203.100.63.0/24\n203.100.80.0/20\n203.100.96.0/19\n203.100.192.0/20\n203.104.32.0/20\n203.105.96.0/19\n203.105.128.0/19\n203.107.0.0/19\n203.107.32.0/20\n203.107.52.0/22\n203.107.56.0/21\n203.107.69.0/24\n203.107.70.0/23\n203.107.72.0/21\n203.107.80.0/20\n203.107.96.0/19\n203.110.160.0/19\n203.110.208.0/20\n203.110.232.0/23\n203.110.234.0/24\n203.114.80.0/20\n203.114.244.0/22\n203.118.192.0/19\n203.118.241.0/24\n203.118.248.0/22\n203.119.24.0/23\n203.119.32.0/24\n203.119.34.0/23\n203.119.80.0/22\n203.119.85.0/24\n203.119.113.0/24\n203.119.114.0/23\n203.119.116.0/22\n203.119.120.0/21\n203.119.128.0/17\n203.123.58.0/24\n203.128.32.0/19\n203.128.96.0/19\n203.128.128.0/24\n203.128.224.0/21\n203.130.32.0/20\n203.132.32.0/19\n203.134.240.0/22\n203.134.246.0/23\n203.135.96.0/19\n203.135.160.0/20\n203.142.12.0/23\n203.142.219.0/24\n203.142.224.0/19\n203.145.0.0/19\n203.148.0.0/18\n203.148.64.0/20\n203.148.80.0/22\n203.148.86.0/23\n203.149.92.0/22\n203.152.64.0/19\n203.152.128.0/19\n203.153.0.0/22\n203.156.192.0/18\n203.158.16.0/21\n203.160.129.0/24\n203.160.192.0/19\n203.161.0.0/22\n203.161.180.0/24\n203.161.183.0/24\n203.161.192.0/19\n203.166.160.0/19\n203.167.28.0/22\n203.168.0.0/19\n203.170.58.0/23\n203.171.0.0/22\n203.171.208.0/24\n203.171.224.0/20\n203.174.4.0/24\n203.174.6.0/24\n203.174.96.0/20\n203.175.128.0/19\n203.175.192.0/18\n203.176.0.0/18\n203.176.64.0/19\n203.176.168.0/21\n203.184.80.0/20\n203.187.160.0/19\n203.189.0.0/23\n203.189.6.0/23\n203.189.112.0/22\n203.189.192.0/19\n203.189.240.0/22\n203.190.96.0/20\n203.190.249.0/24\n203.191.0.0/23\n203.191.2.0/24\n203.191.5.0/24\n203.191.7.0/24\n203.191.29.0/24\n203.191.31.0/24\n203.191.64.0/18\n203.191.133.0/24\n203.191.144.0/20\n203.192.0.0/19\n203.193.224.0/19\n203.195.64.0/19\n203.195.128.0/17\n203.196.0.0/20\n203.196.28.0/22\n203.201.181.0/24\n203.201.182.0/24\n203.202.236.0/22\n203.205.64.0/19\n203.207.64.0/18\n203.207.128.0/17\n203.208.0.0/20\n203.208.16.0/22\n203.208.32.0/19\n203.209.224.0/19\n203.212.0.0/20\n203.212.80.0/20\n203.217.164.0/22\n203.223.0.0/20\n203.223.16.0/24\n203.223.22.0/24\n204.55.160.0/24\n204.74.96.0/24\n204.114.176.0/23\n206.219.44.0/23\n206.219.50.0/23\n206.219.52.0/23\n207.89.20.0/24\n210.2.0.0/23\n210.2.2.0/24\n210.2.5.0/24\n210.2.6.0/23\n210.2.8.0/21\n210.2.24.0/21\n210.5.0.0/19\n210.5.56.0/24\n210.5.60.0/24\n210.5.128.0/19\n210.7.56.0/21\n210.12.0.0/15\n210.14.64.0/19\n210.14.112.0/20\n210.14.128.0/17\n210.15.0.0/17\n210.15.128.0/18\n210.16.128.0/21\n210.16.136.0/22\n210.16.156.0/22\n210.16.160.0/19\n210.21.0.0/16\n210.22.0.0/16\n210.23.32.0/19\n210.25.0.0/16\n210.26.0.0/15\n210.28.0.0/14\n210.32.0.0/12\n210.51.0.0/16\n210.52.0.0/18\n210.52.64.0/23\n210.52.66.0/24\n210.52.68.0/22\n210.52.72.0/21\n210.52.80.0/20\n210.52.96.0/21\n210.52.104.0/22\n210.52.108.0/24\n210.52.110.0/23\n210.52.112.0/20\n210.52.128.0/17\n210.53.0.0/16\n210.56.192.0/19\n210.72.0.0/14\n210.76.0.0/15\n210.78.0.0/16\n210.79.64.0/18\n210.79.224.0/19\n210.82.0.0/15\n210.87.128.0/18\n210.185.192.0/18\n210.192.96.0/19\n211.64.0.0/13\n211.80.0.0/12\n211.96.0.0/14\n211.100.0.0/17\n211.100.128.0/19\n211.100.160.0/20\n211.100.184.0/21\n211.100.192.0/18\n211.101.0.0/16\n211.102.0.0/15\n211.136.0.0/13\n211.144.0.0/13\n211.152.0.0/17\n211.152.134.0/23\n211.152.138.0/23\n211.152.140.0/22\n211.152.150.0/23\n211.152.157.0/24\n211.152.158.0/23\n211.152.160.0/19\n211.152.192.0/18\n211.153.0.0/16\n211.154.0.0/19\n211.154.32.0/20\n211.154.48.0/21\n211.154.64.0/18\n211.154.128.0/17\n211.155.0.0/18\n211.155.67.0/24\n211.155.68.0/24\n211.155.72.0/21\n211.155.80.0/20\n211.155.97.0/24\n211.155.98.0/23\n211.155.100.0/22\n211.155.104.0/21\n211.155.113.0/24\n211.155.117.0/24\n211.155.118.0/23\n211.155.120.0/21\n211.155.128.0/17\n211.156.0.0/18\n211.156.64.0/19\n211.156.96.0/21\n211.156.104.0/22\n211.156.108.0/23\n211.156.112.0/20\n211.156.128.0/17\n211.157.0.0/16\n211.158.0.0/15\n211.160.0.0/13\n212.64.0.0/17\n212.129.128.0/17\n218.0.0.0/12\n218.16.0.0/13\n218.24.0.0/14\n218.28.0.0/15\n218.30.0.0/19\n218.30.64.0/18\n218.30.128.0/18\n218.30.192.0/19\n218.30.224.0/20\n218.30.240.0/21\n218.30.248.0/22\n218.30.252.0/25\n218.30.252.128/26\n218.30.252.194/31\n218.30.252.196/30\n218.30.252.200/29\n218.30.252.208/28\n218.30.252.224/27\n218.30.253.0/24\n218.30.254.0/23\n218.31.0.0/16\n218.56.0.0/13\n218.64.0.0/11\n218.96.0.0/15\n218.98.0.0/18\n218.98.96.0/21\n218.98.104.0/22\n218.98.108.0/23\n218.98.110.0/24\n218.98.112.0/20\n218.98.128.0/19\n218.98.192.0/18\n218.99.0.0/16\n218.100.96.0/19\n218.100.128.0/17\n218.104.0.0/14\n218.108.0.0/15\n218.185.192.0/19\n218.192.0.0/12\n218.240.0.0/14\n218.244.0.0/15\n218.246.0.0/17\n218.246.129.0/24\n218.246.131.0/24\n218.246.132.0/23\n218.246.134.0/24\n218.246.139.0/24\n218.246.144.0/20\n218.246.160.0/19\n218.246.192.0/18\n218.247.0.0/18\n218.247.96.0/19\n218.247.128.0/17\n218.249.0.0/16\n219.72.0.0/16\n219.82.0.0/16\n219.83.128.0/17\n219.90.68.0/22\n219.90.72.0/21\n219.128.0.0/11\n219.216.0.0/13\n219.224.0.0/13\n219.232.0.0/15\n219.234.0.0/21\n219.234.9.0/24\n219.234.10.0/23\n219.234.12.0/22\n219.234.32.0/19\n219.234.64.0/18\n219.234.128.0/17\n219.235.0.0/16\n219.236.0.0/14\n219.242.0.0/15\n219.244.0.0/14\n220.101.192.0/18\n220.112.0.0/14\n220.152.128.0/17\n220.154.0.0/16\n220.155.0.0/21\n220.155.9.0/24\n220.155.10.0/23\n220.155.12.0/22\n220.155.16.0/21\n220.155.24.0/22\n220.155.28.0/23\n220.155.31.0/24\n220.155.32.0/19\n220.155.64.0/18\n220.155.128.0/17\n220.158.241.0/24\n220.158.243.0/24\n220.160.0.0/11\n220.192.0.0/12\n220.231.0.0/18\n220.231.128.0/17\n220.232.64.0/18\n220.234.0.0/16\n220.242.0.0/24\n220.242.12.0/23\n220.242.14.0/24\n220.242.17.0/24\n220.242.18.0/23\n220.242.20.0/24\n220.242.32.0/20\n220.242.48.0/23\n220.242.53.0/24\n220.242.55.0/24\n220.242.56.0/22\n220.242.60.0/23\n220.242.62.0/24\n220.242.64.0/19\n220.242.96.0/20\n220.242.112.0/21\n220.242.120.0/22\n220.242.124.0/23\n220.242.126.0/24\n220.242.173.0/24\n220.242.197.0/24\n220.242.205.0/24\n220.242.207.0/24\n220.242.215.0/24\n220.242.216.0/21\n220.242.224.0/19\n220.243.0.0/17\n220.243.128.0/18\n220.243.204.0/24\n220.243.214.0/24\n220.243.217.0/24\n220.243.218.0/24\n220.243.238.0/24\n220.247.136.0/21\n220.248.0.0/14\n220.252.0.0/16\n221.0.0.0/13\n221.8.0.0/14\n221.12.0.0/17\n221.12.128.0/18\n221.13.0.0/16\n221.14.0.0/15\n221.122.0.0/15\n221.128.128.0/17\n221.129.0.0/16\n221.130.0.0/15\n221.133.224.0/19\n221.136.0.0/15\n221.172.0.0/14\n221.176.0.0/19\n221.176.32.0/20\n221.176.48.0/21\n221.176.56.0/24\n221.176.58.0/23\n221.176.60.0/22\n221.176.64.0/18\n221.176.128.0/17\n221.177.0.0/16\n221.178.0.0/15\n221.180.0.0/14\n221.192.0.0/14\n221.196.0.0/15\n221.198.0.0/16\n221.199.0.0/17\n221.199.128.0/18\n221.199.192.0/20\n221.199.224.0/19\n221.200.0.0/13\n221.208.0.0/12\n221.224.0.0/12\n222.16.0.0/12\n222.32.0.0/11\n222.64.0.0/11\n222.125.0.0/16\n222.126.128.0/19\n222.126.160.0/21\n222.126.168.0/22\n222.126.172.0/23\n222.126.174.40/29\n222.126.174.76/30\n222.126.174.88/29\n222.126.174.144/28\n222.126.178.0/23\n222.126.180.0/22\n222.126.184.0/21\n222.126.192.0/21\n222.126.200.104/29\n222.126.206.0/23\n222.126.208.0/22\n222.126.212.0/26\n222.126.212.64/27\n222.126.212.96/28\n222.126.212.112/29\n222.126.212.128/25\n222.126.213.0/24\n222.126.214.0/23\n222.126.216.0/21\n222.126.224.0/19\n222.128.0.0/12\n222.160.0.0/14\n222.168.0.0/13\n222.176.0.0/12\n222.192.0.0/11\n222.240.0.0/13\n222.248.0.0/15\n223.0.0.0/12\n223.20.0.0/15\n223.27.184.0/22\n223.29.208.0/22\n223.29.252.0/22\n223.64.0.0/11\n223.96.0.0/12\n223.112.0.0/14\n223.116.0.0/15\n223.120.0.0/13\n223.128.0.0/15\n223.144.0.0/12\n223.160.0.0/14\n223.166.0.0/15\n223.192.0.0/15\n223.198.0.0/15\n223.201.4.0/22\n223.201.8.0/21\n223.201.16.0/20\n223.201.32.0/19\n223.201.64.0/18\n223.201.128.0/17\n223.202.0.0/15\n223.208.0.0/13\n223.220.0.0/15\n223.223.176.0/20\n223.223.192.0/20\n223.240.0.0/13\n223.248.0.0/14\n223.252.128.0/19\n223.252.192.0/18\n223.254.0.0/16\n223.255.0.0/17\n223.255.236.0/22\n223.255.252.0/23\n"
  },
  {
    "path": "acl/gfwlist.acl",
    "content": "# gfw list rules for shadowsocks-libev $\n# updated on 2020-04-18 01:30:05$\n[bypass_all]\n\n[proxy_list]\n# Telegram IPs$\n149.154.167.99/32\n149.154.175.10/32\n149.154.167.40/32\n149.154.167.42/32\n149.154.175.117/32\n149.154.175.50/32\n149.154.167.50/32\n149.154.167.51/32\n149.154.175.100/32\n149.154.167.91/32\n149.154.167.90/32\n149.154.165.120/32\n149.154.166.120/32\n149.154.164.250/32\n149.154.167.117/32\n149.154.167.118/32\n149.154.167.192/27\n149.154.164.8/29\n91.108.8.0/27\n91.108.12.0/27\n91.108.16.0/27\n91.108.56.0/24\n91.108.4.0/24\n149.154.160.0/22\n149.154.164.0/22\n149.154.168.0/22\n149.154.172.0/22\n91.108.56.0/22\n91.108.4.0/22\n91.108.8.0/22\n91.108.16.0/22\n91.108.12.0/22\n149.154.160.0/20\n2001:b28:f23d:f001::e/128\n2001:67c:4e8:f002::e/128\n2001:b28:f23d:f003::e/128\n2001:b28:f23d:f001::a/128\n2001:67c:4e8:f002::a/128\n2001:b28:f23d:f003::a/128\n2001:67c:4e8:f004::a/128\n2001:b28:f23f:f005::a/128\n2001:67c:4e8:fa60::/64\n2001:b28:f23d::/48\n2001:b28:f23f::/48\n2001:67c:4e8::/48\n(^|\\.)030buy\\.com$\n(^|\\.)0rz\\.tw$\n(^|\\.)1000giri\\.net$\n(^|\\.)100ke\\.org$\n(^|\\.)10conditionsoflove\\.com$\n(^|\\.)10musume\\.com$\n(^|\\.)10\\.tt$\n(^|\\.)123rf\\.com$\n(^|\\.)12bet\\.com$\n(^|\\.)12vpn\\.com$\n(^|\\.)12vpn\\.net$\n(^|\\.)138\\.com$\n(^|\\.)141hongkong\\.com$\n(^|\\.)141jj\\.com$\n(^|\\.)141tube\\.com$\n(^|\\.)1688\\.com\\.au$\n(^|\\.)173ng\\.com$\n(^|\\.)177pic\\.info$\n(^|\\.)17t17p\\.com$\n(^|\\.)18board\\.com$\n(^|\\.)18board\\.info$\n(^|\\.)18onlygirls\\.com$\n(^|\\.)18p2p\\.com$\n(^|\\.)18virginsex\\.com$\n(^|\\.)1949er\\.org$\n(^|\\.)1984bbs\\.com$\n(^|\\.)1984bbs\\.org$\n(^|\\.)1989report\\.hkja\\.org\\.hk$\n(^|\\.)1991way\\.com$\n(^|\\.)1998cdp\\.org$\n(^|\\.)1-apple\\.com\\.tw$\n(^|\\.)1bao\\.org$\n(^|\\.)1dumb\\.com$\n(^|\\.)1e100\\.net$\n(^|\\.)1eew\\.com$\n(^|\\.)1mobile\\.com$\n(^|\\.)1mobile\\.tw$\n(^|\\.)1pondo\\.tv$\n(^|\\.)2000fun\\.com$\n(^|\\.)2008xianzhang\\.info$\n(^|\\.)2017\\.hk$\n(^|\\.)21andy\\.com$\n(^|\\.)21join\\.com$\n(^|\\.)21pron\\.com$\n(^|\\.)21sextury\\.com$\n(^|\\.)228\\.net\\.tw$\n(^|\\.)233abc\\.com$\n(^|\\.)24hrs\\.ca$\n(^|\\.)24smile\\.org$\n(^|\\.)25u\\.com$\n(^|\\.)2-hand\\.info$\n(^|\\.)2lipstube\\.com$\n(^|\\.)2shared\\.com$\n(^|\\.)2waky\\.com$\n(^|\\.)30boxes\\.com$\n(^|\\.)315lz\\.com$\n(^|\\.)32red\\.com$\n(^|\\.)36rain\\.com$\n(^|\\.)3a5a\\.com$\n(^|\\.)3-a\\.net$\n(^|\\.)3arabtv\\.com$\n(^|\\.)3boys2girls\\.com$\n(^|\\.)3d-game\\.com$\n(^|\\.)3proxy\\.ru$\n(^|\\.)3ren\\.ca$\n(^|\\.)3tui\\.net$\n(^|\\.)43110\\.cf$\n(^|\\.)466453\\.com$\n(^|\\.)4bluestones\\.biz$\n(^|\\.)4chan\\.com$\n(^|\\.)4dq\\.com$\n(^|\\.)4everproxy\\.com$\n(^|\\.)4irc\\.com$\n(^|\\.)4mydomain\\.com$\n(^|\\.)4pu\\.com$\n(^|\\.)4rbtv\\.com$\n(^|\\.)4shared\\.com$\n(^|\\.)4sqi\\.net$\n(^|\\.)51\\.ca$\n(^|\\.)51jav\\.org$\n(^|\\.)51luoben\\.com$\n(^|\\.)5278\\.cc$\n(^|\\.)5299\\.tv$\n(^|\\.)56cun04\\.jigsy\\.com$\n(^|\\.)5aimiku\\.com$\n(^|\\.)5i01\\.com$\n(^|\\.)5isotoi5\\.org$\n(^|\\.)5maodang\\.com$\n(^|\\.)63i\\.com$\n(^|\\.)64museum\\.org$\n(^|\\.)64tianwang\\.com$\n(^|\\.)64wiki\\.com$\n(^|\\.)666kb\\.com$\n(^|\\.)66\\.ca$\n(^|\\.)6park\\.com$\n(^|\\.)6parker\\.com$\n(^|\\.)6parknews\\.com$\n(^|\\.)7capture\\.com$\n(^|\\.)7cow\\.com$\n(^|\\.)85cc\\.net$\n(^|\\.)85cc\\.us$\n(^|\\.)85st\\.com$\n(^|\\.)881903\\.com$\n(^|\\.)888\\.com$\n(^|\\.)888poker\\.com$\n(^|\\.)89\\.64\\.charter\\.constitutionalism\\.solutions$\n(^|\\.)89-64\\.org$\n(^|\\.)8-d\\.com$\n(^|\\.)8news\\.com\\.tw$\n(^|\\.)8z1\\.net$\n(^|\\.)9001700\\.com$\n(^|\\.)908taiwan\\.org$\n(^|\\.)91porn\\.com$\n(^|\\.)91vps\\.club$\n(^|\\.)92ccav\\.com$\n(^|\\.)991\\.com$\n(^|\\.)99btgc01\\.com$\n(^|\\.)99cn\\.info$\n(^|\\.)9bis\\.com$\n(^|\\.)9bis\\.net$\n(^|\\.)9gag\\.com$\n(^|\\.)a248\\.e\\.akamai\\.net$\n(^|\\.)a5\\.com\\.ru$\n(^|\\.)aamacau\\.com$\n(^|\\.)abc\\.com$\n(^|\\.)abchinese\\.com$\n(^|\\.)abclite\\.net$\n(^|\\.)abc\\.net\\.au$\n(^|\\.)abc\\.pp\\.ru$\n(^|\\.)abc\\.xyz$\n(^|\\.)abebooks\\.com$\n(^|\\.)abematv\\.akamaized\\.net$\n(^|\\.)abitno\\.linpie\\.com$\n(^|\\.)ablwang\\.com$\n(^|\\.)aboluowang\\.com$\n(^|\\.)aboutgfw\\.com$\n(^|\\.)about\\.google$\n(^|\\.)abs\\.edu$\n(^|\\.)accim\\.org$\n(^|\\.)aceros-de-hispania\\.com$\n(^|\\.)acevpn\\.com$\n(^|\\.)acg18\\.me$\n(^|\\.)acgkj\\.com$\n(^|\\.)ac\\.jiruan\\.net$\n(^|\\.)acmedia365\\.com$\n(^|\\.)acmetoy\\.com$\n(^|\\.)acnw\\.com\\.au$\n(^|\\.)actfortibet\\.org$\n(^|\\.)actimes\\.com\\.au$\n(^|\\.)activpn\\.com$\n(^|\\.)aculo\\.us$\n(^|\\.)adcex\\.com$\n(^|\\.)addictedtocoffee\\.de$\n(^|\\.)adelaidebbs\\.com$\n(^|\\.)admin\\.recaptcha\\.net$\n(^|\\.)admob\\.com$\n(^|\\.)adpl\\.org\\.hk$\n(^|\\.)adsense\\.com$\n(^|\\.)ads-twitter\\.com$\n(^|\\.)adult\\.friendfinder\\.com$\n(^|\\.)adultfriendfinder\\.com$\n(^|\\.)adultkeep\\.net$\n(^|\\.)adult-sex-games\\.com$\n(^|\\.)advanscene\\.com$\n(^|\\.)advertfan\\.com$\n(^|\\.)ae\\.hao123\\.com$\n(^|\\.)aenhancers\\.com$\n(^|\\.)ae\\.org$\n(^|\\.)aex\\.com$\n(^|\\.)afantibbs\\.com$\n(^|\\.)af\\.mil$\n(^|\\.)agnesb\\.fr$\n(^|\\.)agoogleaday\\.com$\n(^|\\.)agro\\.hk$\n(^|\\.)ai\\.binwang\\.me$\n(^|\\.)ai\\.google$\n(^|\\.)ai-kan\\.net$\n(^|\\.)aiph\\.net$\n(^|\\.)airasia\\.com$\n(^|\\.)airconsole\\.com$\n(^|\\.)airvpn\\.org$\n(^|\\.)aisex\\.com$\n(^|\\.)aiss\\.anws\\.gov\\.tw$\n(^|\\.)ait\\.org\\.tw$\n(^|\\.)aiweiweiblog\\.com$\n(^|\\.)aiweiwei\\.com$\n(^|\\.)ai-wen\\.net$\n(^|\\.)akademiye\\.org$\n(^|\\.)akamaihd\\.net$\n(^|\\.)akiba-online\\.com$\n(^|\\.)akiba-web\\.com$\n(^|\\.)akow\\.org$\n(^|\\.)alabout\\.com$\n(^|\\.)alanhou\\.com$\n(^|\\.)alarab\\.qa$\n(^|\\.)alasbarricadas\\.org$\n(^|\\.)alexlur\\.org$\n(^|\\.)alforattv\\.net$\n(^|\\.)alhayat\\.com$\n(^|\\.)alicejapan\\.co\\.jp$\n(^|\\.)aliengu\\.com$\n(^|\\.)al-islam\\.com$\n(^|\\.)alkasir\\.com$\n(^|\\.)allcoin\\.com$\n(^|\\.)allconnected\\.co$\n(^|\\.)alldrawnsex\\.com$\n(^|\\.)allervpn\\.com$\n(^|\\.)allfinegirls\\.com$\n(^|\\.)allgirlmassage\\.com$\n(^|\\.)allgirlsallowed\\.org$\n(^|\\.)allgravure\\.com$\n(^|\\.)alliance\\.org\\.hk$\n(^|\\.)allinfa\\.com$\n(^|\\.)alljackpotscasino\\.com$\n(^|\\.)allmovie\\.com$\n(^|\\.)allowed\\.org$\n(^|\\.)almasdarnews\\.com$\n(^|\\.)almostmy\\.com$\n(^|\\.)alphaporno\\.com$\n(^|\\.)al-qimmah\\.net$\n(^|\\.)alternate-tools\\.com$\n(^|\\.)alternativeto\\.net$\n(^|\\.)altrec\\.com$\n(^|\\.)alvinalexander\\.com$\n(^|\\.)alwaysdata\\.com$\n(^|\\.)alwaysdata\\.net$\n(^|\\.)alwaysvpn\\.com$\n(^|\\.)am730\\.com\\.hk$\n(^|\\.)amazon\\.co\\.jp$\n(^|\\.)amazon\\.com$\n(^|\\.)ameblo\\.jp$\n(^|\\.)americangreencard\\.com$\n(^|\\.)americanunfinished\\.com$\n(^|\\.)amiblockedornot\\.com$\n(^|\\.)amigobbs\\.net$\n(^|\\.)amitabhafoundation\\.us$\n(^|\\.)amnesty\\.org$\n(^|\\.)amnesty\\.org\\.hk$\n(^|\\.)amnesty\\.tw$\n(^|\\.)amnestyusa\\.org$\n(^|\\.)amnyemachen\\.org$\n(^|\\.)amoiist\\.com$\n(^|\\.)ampproject\\.org$\n(^|\\.)amtb-taipei\\.org$\n(^|\\.)anchorfree\\.com$\n(^|\\.)ancsconf\\.org$\n(^|\\.)andfaraway\\.net$\n(^|\\.)android\\.com$\n(^|\\.)androidify\\.com$\n(^|\\.)androidplus\\.co$\n(^|\\.)androidtv\\.com$\n(^|\\.)android-x86\\.org$\n(^|\\.)andygod\\.com$\n(^|\\.)angela-merkel\\.de$\n(^|\\.)angelfire\\.com$\n(^|\\.)angola\\.org$\n(^|\\.)angularjs\\.org$\n(^|\\.)animecrazy\\.net$\n(^|\\.)animeshippuuden\\.com$\n(^|\\.)aniscartujo\\.com$\n(^|\\.)annatam\\.com$\n(^|\\.)anobii\\.com$\n(^|\\.)anontext\\.com$\n(^|\\.)anonymise\\.us$\n(^|\\.)anonymitynetwork\\.com$\n(^|\\.)anonymizer\\.com$\n(^|\\.)anonymouse\\.org$\n(^|\\.)a-normal-day\\.com$\n(^|\\.)anpopo\\.com$\n(^|\\.)answering-islam\\.org$\n(^|\\.)anthonycalzadilla\\.com$\n(^|\\.)anti1984\\.com$\n(^|\\.)antichristendom\\.com$\n(^|\\.)antiwave\\.net$\n(^|\\.)anyporn\\.com$\n(^|\\.)anysex\\.com$\n(^|\\.)aobo\\.com\\.au$\n(^|\\.)aofriend\\.com$\n(^|\\.)aofriend\\.com\\.au$\n(^|\\.)aojiao\\.org$\n(^|\\.)aolchannels\\.aol\\.com$\n(^|\\.)aomiwang\\.com$\n(^|\\.)apartmentratings\\.com$\n(^|\\.)apartments\\.com$\n(^|\\.)apetube\\.com$\n(^|\\.)api\\.ai$\n(^|\\.)apiary\\.io$\n(^|\\.)apidocs\\.linksalpha\\.com$\n(^|\\.)api\\.dropboxapi\\.com$\n(^|\\.)apigee\\.com$\n(^|\\.)api\\.linksalpha\\.com$\n(^|\\.)api\\.proxlet\\.com$\n(^|\\.)api\\.pureapk\\.com$\n(^|\\.)api\\.recaptcha\\.net$\n(^|\\.)api-secure\\.recaptcha\\.net$\n(^|\\.)api-verify\\.recaptcha\\.net$\n(^|\\.)apk-dl\\.com$\n(^|\\.)apkdler\\.com$\n(^|\\.)apkmirror\\.com$\n(^|\\.)apkmonk\\.com$\n(^|\\.)apkplz\\.com$\n(^|\\.)apkpure\\.com$\n(^|\\.)aplusvpn\\.com$\n(^|\\.)app\\.box\\.com$\n(^|\\.)appdownloader\\.net$\n(^|\\.)app\\.heywire\\.com$\n(^|\\.)appledaily\\.com$\n(^|\\.)appledaily\\.com\\.hk$\n(^|\\.)appledaily\\.com\\.tw$\n(^|\\.)appshopper\\.com$\n(^|\\.)app\\.smartmailcloud\\.com$\n(^|\\.)appsocks\\.net$\n(^|\\.)appspot\\.com$\n(^|\\.)appsto\\.re$\n(^|\\.)app\\.tutanota\\.com$\n(^|\\.)aptoide\\.com$\n(^|\\.)archive\\.fo$\n(^|\\.)archive\\.is$\n(^|\\.)archive\\.li$\n(^|\\.)archive\\.org$\n(^|\\.)archives\\.gov$\n(^|\\.)archives\\.gov\\.tw$\n(^|\\.)archive\\.today$\n(^|\\.)arctosia\\.com$\n(^|\\.)areca-backup\\.org$\n(^|\\.)arena\\.taipei$\n(^|\\.)arethusa\\.su$\n(^|\\.)ar\\.hao123\\.com$\n(^|\\.)arlingtoncemetery\\.mil$\n(^|\\.)army\\.mil$\n(^|\\.)art4tibet1998\\.org$\n(^|\\.)arte\\.tv$\n(^|\\.)artofpeacefoundation\\.org$\n(^|\\.)artstation\\.com$\n(^|\\.)artsy\\.net$\n(^|\\.)asacp\\.org$\n(^|\\.)asdfg\\.jp$\n(^|\\.)asg\\.to$\n(^|\\.)asia-gaming\\.com$\n(^|\\.)asiaharvest\\.org$\n(^|\\.)asianews\\.it$\n(^|\\.)asiansexdiary\\.com$\n(^|\\.)asianspiss\\.com$\n(^|\\.)asianwomensfilm\\.de$\n(^|\\.)asiatgp\\.com$\n(^|\\.)asiatoday\\.us$\n(^|\\.)askstudent\\.com$\n(^|\\.)askynz\\.net$\n(^|\\.)assembla\\.com$\n(^|\\.)assets\\.bwbx\\.io$\n(^|\\.)assimp\\.org$\n(^|\\.)astrill\\.com$\n(^|\\.)atchinese\\.com$\n(^|\\.)atc\\.org\\.au$\n(^|\\.)atdmt\\.com$\n(^|\\.)atgfw\\.org$\n(^|\\.)athenaeizou\\.com$\n(^|\\.)atlanta168\\.com$\n(^|\\.)atlaspost\\.com$\n(^|\\.)atnext\\.com$\n(^|\\.)authorizeddns\\.net$\n(^|\\.)authorizeddns\\.org$\n(^|\\.)authorizeddns\\.us$\n(^|\\.)autodraw\\.com$\n(^|\\.)avaaz\\.org$\n(^|\\.)avbody\\.tv$\n(^|\\.)avcity\\.tv$\n(^|\\.)av\\.com$\n(^|\\.)avcool\\.com$\n(^|\\.)avdb\\.in$\n(^|\\.)avdb\\.tv$\n(^|\\.)av-e-body\\.com$\n(^|\\.)avfantasy\\.com$\n(^|\\.)avg\\.com$\n(^|\\.)avgle\\.com$\n(^|\\.)avidemux\\.org$\n(^|\\.)avmoo\\.com$\n(^|\\.)avmoo\\.net$\n(^|\\.)avmoo\\.pw$\n(^|\\.)avmo\\.pw$\n(^|\\.)av\\.movie$\n(^|\\.)av\\.nightlife141\\.com$\n(^|\\.)avoision\\.com$\n(^|\\.)avyahoo\\.com$\n(^|\\.)axureformac\\.com$\n(^|\\.)azerbaycan\\.tv$\n(^|\\.)azerimix\\.com$\n(^|\\.)azubu\\.tv$\n(^|\\.)azurewebsites\\.net$\n(^|\\.)b0ne\\.com$\n(^|\\.)babynet\\.com\\.hk$\n(^|\\.)backchina\\.com$\n(^|\\.)backpackers\\.com\\.tw$\n(^|\\.)backtotiananmen\\.com$\n(^|\\.)badiucao\\.com$\n(^|\\.)badjojo\\.com$\n(^|\\.)badoo\\.com$\n(^|\\.)bahamut\\.com\\.tw$\n(^|\\.)baidu\\.jp$\n(^|\\.)baijie\\.org$\n(^|\\.)bailandaily\\.com$\n(^|\\.)baixing\\.me$\n(^|\\.)bakgeekhome\\.tk$\n(^|\\.)banana-vpn\\.com$\n(^|\\.)band\\.us$\n(^|\\.)bandwagonhost\\.com$\n(^|\\.)bangbrosnetwork\\.com$\n(^|\\.)bangchen\\.net$\n(^|\\.)bangdream\\.space$\n(^|\\.)bangyoulater\\.com$\n(^|\\.)bankmobilevibe\\.com$\n(^|\\.)bannedbook\\.org$\n(^|\\.)bannednews\\.org$\n(^|\\.)banorte\\.com$\n(^|\\.)baramangaonline\\.com$\n(^|\\.)barenakedislam\\.com$\n(^|\\.)barnabu\\.co\\.uk$\n(^|\\.)barton\\.de$\n(^|\\.)bartvpn\\.com$\n(^|\\.)bash-hackers\\.org$\n(^|\\.)bastillepost\\.com$\n(^|\\.)bayvoice\\.net$\n(^|\\.)bbcchinese\\.com$\n(^|\\.)bbc\\.com$\n(^|\\.)bbc\\.co\\.uk$\n(^|\\.)bb-chat\\.tv$\n(^|\\.)bbchat\\.tv$\n(^|\\.)bbci\\.co\\.uk$\n(^|\\.)bbc\\.in$\n(^|\\.)bbg\\.gov$\n(^|\\.)bbkz\\.com$\n(^|\\.)bbnradio\\.org$\n(^|\\.)bbs\\.brockbbs\\.com$\n(^|\\.)bbs\\.cantonese\\.asia$\n(^|\\.)bbsdigest\\.com$\n(^|\\.)bbs\\.ecstart\\.com$\n(^|\\.)bbsfeed\\.com$\n(^|\\.)bbs\\.hanminzu\\.org$\n(^|\\.)bbs\\.hasi\\.wang$\n(^|\\.)bbs\\.huasing\\.org$\n(^|\\.)bbs\\.junglobal\\.net$\n(^|\\.)bbs\\.kimy\\.com\\.tw$\n(^|\\.)bbsland\\.com$\n(^|\\.)bbs\\.mikocon\\.com$\n(^|\\.)bbsmo\\.com$\n(^|\\.)bbs\\.morbell\\.com$\n(^|\\.)bbs\\.mychat\\.to$\n(^|\\.)bbs\\.netbig\\.com$\n(^|\\.)bbsone\\.com$\n(^|\\.)bbs\\.ozchinese\\.com$\n(^|\\.)bbs\\.qmzdd\\.com$\n(^|\\.)bbs\\.sina\\.com$\n(^|\\.)bbs\\.skykiwi\\.com$\n(^|\\.)bbs\\.sou-tong\\.org$\n(^|\\.)bbs\\.tuitui\\.info$\n(^|\\.)bbs-tw\\.com$\n(^|\\.)bbtoystore\\.com$\n(^|\\.)bb\\.ttv\\.com\\.tw$\n(^|\\.)bcast\\.co\\.nz$\n(^|\\.)bcc\\.com\\.tw$\n(^|\\.)bcchinese\\.net$\n(^|\\.)bcex\\.ca$\n(^|\\.)bcmorning\\.com$\n(^|\\.)bdsmvideos\\.net$\n(^|\\.)beaconevents\\.com$\n(^|\\.)bebo\\.com$\n(^|\\.)beeg\\.com$\n(^|\\.)beevpn\\.com$\n(^|\\.)behance\\.net$\n(^|\\.)behindkink\\.com$\n(^|\\.)beijing1989\\.com$\n(^|\\.)beijingspring\\.com$\n(^|\\.)beijingzx\\.org$\n(^|\\.)belamionline\\.com$\n(^|\\.)bell\\.wiki$\n(^|\\.)bemywife\\.cc$\n(^|\\.)beric\\.me$\n(^|\\.)berlintwitterwall\\.com$\n(^|\\.)berm\\.co\\.nz$\n(^|\\.)bestforchina\\.org$\n(^|\\.)bestgore\\.com$\n(^|\\.)bestpornstardb\\.com$\n(^|\\.)bestvpnanalysis\\.com$\n(^|\\.)bestvpn\\.com$\n(^|\\.)bestvpnserver\\.com$\n(^|\\.)bestvpnservice\\.com$\n(^|\\.)bestvpnusa\\.com$\n(^|\\.)bet365\\.com$\n(^|\\.)betfair\\.com$\n(^|\\.)betternet\\.co$\n(^|\\.)bettervpn\\.com$\n(^|\\.)bettween\\.com$\n(^|\\.)betvictor\\.com$\n(^|\\.)bewww\\.net$\n(^|\\.)beyondfirewall\\.com$\n(^|\\.)bfnn\\.org$\n(^|\\.)bfsh\\.hk$\n(^|\\.)bgvpn\\.com$\n(^|\\.)bianlei\\.com$\n(^|\\.)biantailajiao\\.com$\n(^|\\.)biantailajiao\\.in$\n(^|\\.)biblesforamerica\\.org$\n(^|\\.)bibox\\.com$\n(^|\\.)bic2011\\.org$\n(^|\\.)bigfools\\.com$\n(^|\\.)bigjapanesesex\\.com$\n(^|\\.)bigmoney\\.biz$\n(^|\\.)bignews\\.org$\n(^|\\.)big\\.one$\n(^|\\.)bigsound\\.org$\n(^|\\.)biliworld\\.com$\n(^|\\.)billypan\\.com$\n(^|\\.)binance\\.com$\n(^|\\.)binux\\.me$\n(^|\\.)bipic\\.net$\n(^|\\.)bird\\.so$\n(^|\\.)bitc\\.bme\\.emory\\.edu$\n(^|\\.)bitcointalk\\.org$\n(^|\\.)bitcoinworld\\.com$\n(^|\\.)bit\\.do$\n(^|\\.)bitfinex\\.com$\n(^|\\.)bithumb\\.com$\n(^|\\.)bitinka\\.com\\.ar$\n(^|\\.)bit\\.ly$\n(^|\\.)bitmex\\.com$\n(^|\\.)bitshare\\.com$\n(^|\\.)bitsnoop\\.com$\n(^|\\.)bitvise\\.com$\n(^|\\.)bit-z\\.com$\n(^|\\.)bizhat\\.com$\n(^|\\.)bjnewlife\\.org$\n(^|\\.)bjs\\.org$\n(^|\\.)bjzc\\.org$\n(^|\\.)blacklogic\\.com$\n(^|\\.)blackvpn\\.com$\n(^|\\.)bl-doujinsouko\\.com$\n(^|\\.)blewpass\\.com$\n(^|\\.)blinkx\\.com$\n(^|\\.)blinw\\.com$\n(^|\\.)blip\\.tv$\n(^|\\.)blockcn\\.com$\n(^|\\.)blockless\\.com$\n(^|\\.)blogblog\\.com$\n(^|\\.)blog\\.calibre-ebook\\.com$\n(^|\\.)blogcatalog\\.com$\n(^|\\.)blogcity\\.me$\n(^|\\.)blog\\.cnyes\\.com$\n(^|\\.)blog\\.daum\\.net$\n(^|\\.)blog\\.de$\n(^|\\.)blogdns\\.org$\n(^|\\.)blog\\.exblog\\.co\\.jp$\n(^|\\.)blog\\.excite\\.co\\.jp$\n(^|\\.)blog\\.expofutures\\.com$\n(^|\\.)blog\\.fizzik\\.com$\n(^|\\.)blog\\.foolsmountain\\.com$\n(^|\\.)blog\\.fuckgfw233\\.org$\n(^|\\.)blogger\\.com$\n(^|\\.)blog\\.google$\n(^|\\.)blog\\.goo\\.ne\\.jp$\n(^|\\.)blogimg\\.jp$\n(^|\\.)blog\\.inoreader\\.com$\n(^|\\.)blog\\.istef\\.info$\n(^|\\.)blog\\.jackjia\\.com$\n(^|\\.)blog\\.jp$\n(^|\\.)blog\\.kangye\\.org$\n(^|\\.)blog\\.lester850\\.info$\n(^|\\.)bloglines\\.com$\n(^|\\.)bloglovin\\.com$\n(^|\\.)blog\\.martinoei\\.com$\n(^|\\.)blog\\.pathtosharepoint\\.com$\n(^|\\.)blog\\.pentalogic\\.net$\n(^|\\.)blog\\.qooza\\.hk$\n(^|\\.)blog\\.ranxiang\\.com$\n(^|\\.)blogs\\.icerocket\\.com$\n(^|\\.)blog\\.sina\\.com\\.tw$\n(^|\\.)blogs\\.libraryinformationtechnology\\.com$\n(^|\\.)blog\\.sogoo\\.org$\n(^|\\.)blog\\.soylent\\.com$\n(^|\\.)blogspot\\.ae$\n(^|\\.)blogspot\\.al$\n(^|\\.)blogspot\\.am$\n(^|\\.)blogspot\\.ba$\n(^|\\.)blogspot\\.be$\n(^|\\.)blogspot\\.bg$\n(^|\\.)blogspot\\.ca$\n(^|\\.)blogspot\\.cat$\n(^|\\.)blogspot\\.ch$\n(^|\\.)blogspot\\.cl$\n(^|\\.)blogspot\\.com$\n(^|\\.)blogspot\\.com\\.ar$\n(^|\\.)blogspot\\.com\\.au$\n(^|\\.)blogspot\\.com\\.br$\n(^|\\.)blogspot\\.com\\.by$\n(^|\\.)blogspot\\.com\\.co$\n(^|\\.)blogspot\\.com\\.cy$\n(^|\\.)blogspot\\.com\\.ee$\n(^|\\.)blogspot\\.com\\.eg$\n(^|\\.)blogspot\\.com\\.es$\n(^|\\.)blogspot\\.com\\.mt$\n(^|\\.)blogspot\\.com\\.ng$\n(^|\\.)blogspot\\.com\\.tr$\n(^|\\.)blogspot\\.com\\.uy$\n(^|\\.)blogspot\\.co\\.uk$\n(^|\\.)blogspot\\.cz$\n(^|\\.)blogspot\\.de$\n(^|\\.)blogspot\\.dk$\n(^|\\.)blogspot\\.fi$\n(^|\\.)blogspot\\.fr$\n(^|\\.)blogspot\\.gr$\n(^|\\.)blogspot\\.hk$\n(^|\\.)blogspot\\.hr$\n(^|\\.)blogspot\\.hu$\n(^|\\.)blogspot\\.ie$\n(^|\\.)blogspot\\.in$\n(^|\\.)blogspot\\.is$\n(^|\\.)blogspot\\.it$\n(^|\\.)blogspot\\.jp$\n(^|\\.)blogspot\\.kr$\n(^|\\.)blogspot\\.li$\n(^|\\.)blogspot\\.lt$\n(^|\\.)blogspot\\.lu$\n(^|\\.)blogspot\\.md$\n(^|\\.)blogspot\\.mk$\n(^|\\.)blogspot\\.mx$\n(^|\\.)blogspot\\.my$\n(^|\\.)blogspot\\.nl$\n(^|\\.)blogspot\\.no$\n(^|\\.)blogspot\\.pe$\n(^|\\.)blogspot\\.pt$\n(^|\\.)blogspot\\.qa$\n(^|\\.)blogspot\\.ro$\n(^|\\.)blogspot\\.ru$\n(^|\\.)blogspot\\.se$\n(^|\\.)blogspot\\.sg$\n(^|\\.)blogspot\\.si$\n(^|\\.)blogspot\\.sk$\n(^|\\.)blogspot\\.sn$\n(^|\\.)blogspot\\.tw$\n(^|\\.)blogspot\\.ug$\n(^|\\.)blogs\\.tampabay\\.com$\n(^|\\.)blogs\\.yahoo\\.co\\.jp$\n(^|\\.)blog\\.syx86\\.cn$\n(^|\\.)blog\\.syx86\\.com$\n(^|\\.)blog\\.taragana\\.com$\n(^|\\.)blogtd\\.net$\n(^|\\.)blogtd\\.org$\n(^|\\.)blog\\.tiney\\.com$\n(^|\\.)blog\\.workflow\\.is$\n(^|\\.)blog\\.xuite\\.net$\n(^|\\.)blog\\.youthwant\\.com\\.tw$\n(^|\\.)blog\\.youxu\\.info$\n(^|\\.)bloodshed\\.net$\n(^|\\.)bloomberg\\.cn$\n(^|\\.)bloomberg\\.com$\n(^|\\.)bloomberg\\.de$\n(^|\\.)bloombergview\\.com$\n(^|\\.)bloomfortune\\.com$\n(^|\\.)blueangellive\\.com$\n(^|\\.)bmfinn\\.com$\n(^|\\.)bnews\\.co$\n(^|\\.)bnn\\.co$\n(^|\\.)bnrmetal\\.com$\n(^|\\.)boardreader\\.com$\n(^|\\.)bod\\.asia$\n(^|\\.)bodog88\\.com$\n(^|\\.)bolehvpn\\.net$\n(^|\\.)bolin\\.netfirms\\.com$\n(^|\\.)bonbonme\\.com$\n(^|\\.)bonbonsex\\.com$\n(^|\\.)bonfoundation\\.org$\n(^|\\.)bongacams\\.com$\n(^|\\.)boobstagram\\.com$\n(^|\\.)book\\.com\\.tw$\n(^|\\.)bookepub\\.com$\n(^|\\.)books\\.com\\.tw$\n(^|\\.)booktopia\\.com\\.au$\n(^|\\.)book\\.zi5\\.me$\n(^|\\.)boomssr\\.com$\n(^|\\.)botanwang\\.com$\n(^|\\.)bot\\.nu$\n(^|\\.)bowenpress\\.com$\n(^|\\.)boxpn\\.com$\n(^|\\.)boxunblog\\.com$\n(^|\\.)boxunclub\\.com$\n(^|\\.)boxun\\.com$\n(^|\\.)boxun\\.tv$\n(^|\\.)boyangu\\.com$\n(^|\\.)boyfriendtv\\.com$\n(^|\\.)boysfood\\.com$\n(^|\\.)boysmaster\\.com$\n(^|\\.)brainyquote\\.com$\n(^|\\.)brandonhutchinson\\.com$\n(^|\\.)braumeister\\.org$\n(^|\\.)bravotube\\.net$\n(^|\\.)brazzers\\.com$\n(^|\\.)break\\.com$\n(^|\\.)breakgfw\\.com$\n(^|\\.)breaking911\\.com$\n(^|\\.)breakingtweets\\.com$\n(^|\\.)breakwall\\.net$\n(^|\\.)br\\.hao123\\.com$\n(^|\\.)briefdream\\.com$\n(^|\\.)briian\\.com$\n(^|\\.)brizzly\\.com$\n(^|\\.)brkmd\\.com$\n(^|\\.)broadbook\\.com$\n(^|\\.)broadpressinc\\.com$\n(^|\\.)br\\.st$\n(^|\\.)brucewang\\.net$\n(^|\\.)brutaltgp\\.com$\n(^|\\.)bt2mag\\.com$\n(^|\\.)bt95\\.com$\n(^|\\.)btaia\\.com$\n(^|\\.)btbtav\\.com$\n(^|\\.)btc98\\.com$\n(^|\\.)btcbank\\.bank$\n(^|\\.)btctrade\\.im$\n(^|\\.)btdigg\\.org$\n(^|\\.)btku\\.me$\n(^|\\.)btku\\.org$\n(^|\\.)btspread\\.com$\n(^|\\.)btsynckeys\\.com$\n(^|\\.)budaedu\\.org$\n(^|\\.)buddhanet\\.com\\.tw$\n(^|\\.)buddhistchannel\\.tv$\n(^|\\.)buffered\\.com$\n(^|\\.)bullogger\\.com$\n(^|\\.)bullog\\.org$\n(^|\\.)bunbunhk\\.com$\n(^|\\.)busayari\\.com$\n(^|\\.)businessinsider\\.com$\n(^|\\.)businesstoday\\.com\\.tw$\n(^|\\.)businessweek\\.com$\n(^|\\.)busu\\.org$\n(^|\\.)busytrade\\.com$\n(^|\\.)buugaa\\.com$\n(^|\\.)buy\\.yahoo\\.com\\.tw$\n(^|\\.)buzzhand\\.com$\n(^|\\.)buzzhand\\.net$\n(^|\\.)buzzorange\\.com$\n(^|\\.)bvpn\\.com$\n(^|\\.)bwgyhw\\.com$\n(^|\\.)bwh1\\.net$\n(^|\\.)bwsj\\.hk$\n(^|\\.)bx\\.in\\.th$\n(^|\\.)bx\\.tl$\n(^|\\.)bynet\\.co\\.il$\n(^|\\.)c100tibet\\.org$\n(^|\\.)c1522\\.mooo\\.com$\n(^|\\.)c2cx\\.com$\n(^|\\.)cablegatesearch\\.net$\n(^|\\.)cachinese\\.com$\n(^|\\.)cacnw\\.com$\n(^|\\.)cactusvpn\\.com$\n(^|\\.)cafepress\\.com$\n(^|\\.)cahr\\.org\\.tw$\n(^|\\.)calameo\\.com$\n(^|\\.)calebelston\\.com$\n(^|\\.)calgarychinese\\.ca$\n(^|\\.)calgarychinese\\.com$\n(^|\\.)calgarychinese\\.net$\n(^|\\.)cam4\\.com$\n(^|\\.)cam4\\.jp$\n(^|\\.)cam4\\.sg$\n(^|\\.)camfrog\\.com$\n(^|\\.)cams\\.com$\n(^|\\.)cams\\.org\\.sg$\n(^|\\.)canadameet\\.com$\n(^|\\.)canalporno\\.com$\n(^|\\.)canyu\\.org$\n(^|\\.)caobian\\.info$\n(^|\\.)caochangqing\\.com$\n(^|\\.)cao\\.im$\n(^|\\.)cap\\.org\\.hk$\n(^|\\.)carabinasypistolas\\.com$\n(^|\\.)cardinalkungfoundation\\.org$\n(^|\\.)carfax\\.com$\n(^|\\.)caribbeancom\\.com$\n(^|\\.)cari\\.com\\.my$\n(^|\\.)carmotorshow\\.com$\n(^|\\.)cartoonmovement\\.com$\n(^|\\.)casadeltibetbcn\\.org$\n(^|\\.)casatibet\\.org\\.mx$\n(^|\\.)casinobellini\\.com$\n(^|\\.)casinoking\\.com$\n(^|\\.)casinoriva\\.com$\n(^|\\.)casino\\.williamhill\\.com$\n(^|\\.)castbox\\.fm$\n(^|\\.)catch22\\.net$\n(^|\\.)catchgod\\.com$\n(^|\\.)catfightpayperview\\.xxx$\n(^|\\.)catholic\\.org\\.hk$\n(^|\\.)catholic\\.org\\.tw$\n(^|\\.)cathvoice\\.org\\.tw$\n(^|\\.)cattt\\.com$\n(^|\\.)cbc\\.ca$\n(^|\\.)cbsnews\\.com$\n(^|\\.)cbs\\.ntu\\.edu\\.tw$\n(^|\\.)cbtc\\.org\\.hk$\n(^|\\.)cccat\\.cc$\n(^|\\.)cccat\\.co$\n(^|\\.)ccdtr\\.org$\n(^|\\.)cchere\\.com$\n(^|\\.)ccim\\.org$\n(^|\\.)cclife\\.ca$\n(^|\\.)cclifefl\\.org$\n(^|\\.)cclife\\.org$\n(^|\\.)ccthere\\.com$\n(^|\\.)ccthere\\.net$\n(^|\\.)cctmweb\\.net$\n(^|\\.)cctongbao\\.com$\n(^|\\.)ccue\\.ca$\n(^|\\.)ccue\\.com$\n(^|\\.)ccvoice\\.ca$\n(^|\\.)ccw\\.org\\.tw$\n(^|\\.)cdbook\\.org$\n(^|\\.)cdcparty\\.com$\n(^|\\.)cdef\\.org$\n(^|\\.)cdig\\.info$\n(^|\\.)cdjp\\.org$\n(^|\\.)cdn1\\.lp\\.saboom\\.com$\n(^|\\.)cdn-apple\\.com$\n(^|\\.)cdn\\.assets\\.lfpcontent\\.com$\n(^|\\.)cdnews\\.com\\.tw$\n(^|\\.)cdn\\.helixstudios\\.net$\n(^|\\.)cdn-images\\.mailchimp\\.com$\n(^|\\.)cdninstagram\\.com$\n(^|\\.)cdn\\.printfriendly\\.com$\n(^|\\.)cdn\\.seatguru\\.com$\n(^|\\.)cdn\\.softlayer\\.net$\n(^|\\.)cdp1989\\.org$\n(^|\\.)cdp1998\\.org$\n(^|\\.)cdp2006\\.org$\n(^|\\.)cdpa\\.url\\.tw$\n(^|\\.)cdpeu\\.org$\n(^|\\.)cdpusa\\.org$\n(^|\\.)cdpweb\\.org$\n(^|\\.)cdpwu\\.org$\n(^|\\.)cdw\\.com$\n(^|\\.)cecc\\.gov$\n(^|\\.)cellulo\\.info$\n(^|\\.)cenews\\.eu$\n(^|\\.)centauro\\.com\\.br$\n(^|\\.)centerforhumanreprod\\.com$\n(^|\\.)centralnation\\.com$\n(^|\\.)centurys\\.net$\n(^|\\.)certificate\\.revocationcheck\\.com$\n(^|\\.)certificate-transparency\\.org$\n(^|\\.)c-est-simple\\.com$\n(^|\\.)cfhks\\.org\\.hk$\n(^|\\.)cfos\\.de$\n(^|\\.)cftfc\\.com$\n(^|\\.)cgdepot\\.org$\n(^|\\.)cgst\\.edu$\n(^|\\.)changeip\\.name$\n(^|\\.)changeip\\.net$\n(^|\\.)changeip\\.org$\n(^|\\.)change\\.org$\n(^|\\.)changp\\.com$\n(^|\\.)changsa\\.net$\n(^|\\.)channel8news\\.sg$\n(^|\\.)chaoex\\.com$\n(^|\\.)chapm25\\.com$\n(^|\\.)chatnook\\.com$\n(^|\\.)chaturbate\\.com$\n(^|\\.)chengmingmag\\.com$\n(^|\\.)chenguangcheng\\.com$\n(^|\\.)chenpokong\\.com$\n(^|\\.)chenpokong\\.net$\n(^|\\.)chenshan20042005\\.wordpress\\.com$\n(^|\\.)cherrysave\\.com$\n(^|\\.)chhongbi\\.org$\n(^|\\.)chicagoncmtv\\.com$\n(^|\\.)china101\\.com$\n(^|\\.)china18\\.org$\n(^|\\.)china21\\.com$\n(^|\\.)china21\\.org$\n(^|\\.)china5000\\.us$\n(^|\\.)chinaaffairs\\.org$\n(^|\\.)chinaaid\\.me$\n(^|\\.)chinaaid\\.net$\n(^|\\.)chinaaid\\.org$\n(^|\\.)chinaaid\\.us$\n(^|\\.)chinachange\\.org$\n(^|\\.)chinachannel\\.hk$\n(^|\\.)chinacitynews\\.be$\n(^|\\.)chinacomments\\.org$\n(^|\\.)chinadialogue\\.net$\n(^|\\.)chinadigitaltimes\\.net$\n(^|\\.)chinaelections\\.org$\n(^|\\.)chinaeweekly\\.com$\n(^|\\.)chinafreepress\\.org$\n(^|\\.)chinagate\\.com$\n(^|\\.)chinageeks\\.org$\n(^|\\.)chinagfw\\.org$\n(^|\\.)chinagonet\\.com$\n(^|\\.)chinagreenparty\\.org$\n(^|\\.)china\\.hket\\.com$\n(^|\\.)chinahorizon\\.org$\n(^|\\.)chinahush\\.com$\n(^|\\.)chinainperspective\\.com$\n(^|\\.)chinainterimgov\\.org$\n(^|\\.)chinalaborwatch\\.org$\n(^|\\.)chinalawandpolicy\\.com$\n(^|\\.)chinalawtranslate\\.com$\n(^|\\.)china-mmm\\.jp\\.net$\n(^|\\.)china-mmm\\.net$\n(^|\\.)china-mmm\\.sa\\.com$\n(^|\\.)chinamule\\.com$\n(^|\\.)chinamz\\.org$\n(^|\\.)chinanewscenter\\.com$\n(^|\\.)chinapost\\.com\\.tw$\n(^|\\.)chinapress\\.com\\.my$\n(^|\\.)china-review\\.com\\.ua$\n(^|\\.)chinarightsia\\.org$\n(^|\\.)chinasmile\\.net$\n(^|\\.)chinasocialdemocraticparty\\.com$\n(^|\\.)chinasoul\\.org$\n(^|\\.)chinasucks\\.net$\n(^|\\.)chinatimes\\.com$\n(^|\\.)chinatopsex\\.com$\n(^|\\.)chinatown\\.com\\.au$\n(^|\\.)chinatweeps\\.com$\n(^|\\.)china\\.ucanews\\.com$\n(^|\\.)chinaview\\.wordpress\\.com$\n(^|\\.)chinaway\\.org$\n(^|\\.)china-week\\.com$\n(^|\\.)chinaworker\\.info$\n(^|\\.)chinaxchina\\.com$\n(^|\\.)chinayouth\\.org\\.hk$\n(^|\\.)chinayuanmin\\.org$\n(^|\\.)chinesedaily\\.com$\n(^|\\.)chinesedailynews\\.com$\n(^|\\.)chinesedemocracy\\.com$\n(^|\\.)chinese\\.donga\\.com$\n(^|\\.)chinese\\.engadget\\.com$\n(^|\\.)chinesegay\\.org$\n(^|\\.)chinese-hermit\\.net$\n(^|\\.)chinese\\.irib\\.ir$\n(^|\\.)chinese-leaders\\.org$\n(^|\\.)chinese-memorial\\.org$\n(^|\\.)chinesen\\.de$\n(^|\\.)chinesenews\\.net\\.au$\n(^|\\.)chinesepen\\.org$\n(^|\\.)chinese\\.soifind\\.com$\n(^|\\.)chinesetalks\\.net$\n(^|\\.)chineseupress\\.com$\n(^|\\.)chingcheong\\.com$\n(^|\\.)chinman\\.net$\n(^|\\.)chithu\\.org$\n(^|\\.)chn\\.chosun\\.com$\n(^|\\.)chobit\\.cc$\n(^|\\.)chrdnet\\.com$\n(^|\\.)christianfreedom\\.org$\n(^|\\.)christianstudy\\.com$\n(^|\\.)christiantimes\\.org\\.hk$\n(^|\\.)christusrex\\.org$\n(^|\\.)chrlawyers\\.hk$\n(^|\\.)chromecast\\.com$\n(^|\\.)chrome\\.com$\n(^|\\.)chromeexperiments\\.com$\n(^|\\.)chromercise\\.com$\n(^|\\.)chromestatus\\.com$\n(^|\\.)chromium\\.org$\n(^|\\.)ch\\.shvoong\\.com$\n(^|\\.)chuang-yen\\.org$\n(^|\\.)chubold\\.com$\n(^|\\.)chubun\\.com$\n(^|\\.)chuizi\\.net$\n(^|\\.)churchinhongkong\\.org$\n(^|\\.)chushigangdrug\\.ch$\n(^|\\.)cienen\\.com$\n(^|\\.)cineastentreff\\.de$\n(^|\\.)cipfg\\.org$\n(^|\\.)circlethebayfortibet\\.org$\n(^|\\.)cirosantilli\\.com$\n(^|\\.)citizencn\\.com$\n(^|\\.)citizenlab\\.org$\n(^|\\.)citizenscommission\\.hk$\n(^|\\.)citizensradio\\.org$\n(^|\\.)city365\\.ca$\n(^|\\.)city9x\\.com$\n(^|\\.)citypopulation\\.de$\n(^|\\.)citytalk\\.tw$\n(^|\\.)civicparty\\.hk$\n(^|\\.)civildisobediencemovement\\.org$\n(^|\\.)civilhrfront\\.org$\n(^|\\.)civiliangunner\\.com$\n(^|\\.)civilmedia\\.tw$\n(^|\\.)ck101\\.com$\n(^|\\.)clarionproject\\.org$\n(^|\\.)classicalguitarblog\\.net$\n(^|\\.)clb\\.org\\.hk$\n(^|\\.)cl\\.d0z\\.net$\n(^|\\.)cldr\\.unicode\\.org$\n(^|\\.)cleansite\\.biz$\n(^|\\.)cleansite\\.info$\n(^|\\.)cleansite\\.us$\n(^|\\.)clearharmony\\.net$\n(^|\\.)clearsurance\\.com$\n(^|\\.)clearwisdom\\.net$\n(^|\\.)clementine-player\\.org$\n(^|\\.)cling\\.omy\\.sg$\n(^|\\.)clinica-tibet\\.ru$\n(^|\\.)clipfish\\.de$\n(^|\\.)cloakpoint\\.com$\n(^|\\.)cloud\\.feedly\\.com$\n(^|\\.)cloud\\.mail\\.ru$\n(^|\\.)club1069\\.com$\n(^|\\.)clyp\\.it$\n(^|\\.)cmcn\\.org$\n(^|\\.)cmi\\.org\\.tw$\n(^|\\.)cmp\\.hku\\.hk$\n(^|\\.)cms\\.gov$\n(^|\\.)cmule\\.com$\n(^|\\.)cmule\\.org$\n(^|\\.)cmx\\.im$\n(^|\\.)cn2\\.streetvoice\\.com$\n(^|\\.)cn6\\.eu$\n(^|\\.)cnabc\\.com$\n(^|\\.)cna\\.com\\.tw$\n(^|\\.)cnbbnews\\.wordpress\\.com$\n(^|\\.)cn\\.calameo\\.com$\n(^|\\.)cn\\.dayabook\\.com$\n(^|\\.)cnd\\.org$\n(^|\\.)cnex\\.org\\.cn$\n(^|\\.)cn\\.fmnnow\\.com$\n(^|\\.)cn\\.freeones\\.com$\n(^|\\.)cn\\.giganews\\.com$\n(^|\\.)cn\\.ibtimes\\.com$\n(^|\\.)cnineu\\.com$\n(^|\\.)cnn\\.com$\n(^|\\.)cnnews\\.chosun\\.com$\n(^|\\.)cn\\.nytstyle\\.com$\n(^|\\.)cnpolitics\\.org$\n(^|\\.)cn-proxy\\.com$\n(^|\\.)cnproxy\\.com$\n(^|\\.)cn\\.sandscotaicentral\\.com$\n(^|\\.)cn\\.shafaqna\\.com$\n(^|\\.)cn\\.streetvoice\\.com$\n(^|\\.)cn\\.thegay\\.com$\n(^|\\.)cn\\.uncyclopedia\\.wikia\\.com$\n(^|\\.)cn\\.uptodown\\.com$\n(^|\\.)cn\\.voa\\.mobi$\n(^|\\.)coat\\.co\\.jp$\n(^|\\.)cobinhood\\.com$\n(^|\\.)cochina\\.co$\n(^|\\.)cochina\\.org$\n(^|\\.)code1984\\.com$\n(^|\\.)codeshare\\.io$\n(^|\\.)codeskulptor\\.org$\n(^|\\.)coin2co\\.in$\n(^|\\.)coinbene\\.com$\n(^|\\.)coinegg\\.com$\n(^|\\.)coinex\\.com$\n(^|\\.)coingi\\.com$\n(^|\\.)coinrail\\.co\\.kr$\n(^|\\.)cointiger\\.com$\n(^|\\.)cointobe\\.com$\n(^|\\.)coinut\\.com$\n(^|\\.)collateralmurder\\.com$\n(^|\\.)collateralmurder\\.org$\n(^|\\.)comefromchina\\.com$\n(^|\\.)com\\.google$\n(^|\\.)comic-mega\\.me$\n(^|\\.)commandarms\\.com$\n(^|\\.)commentshk\\.com$\n(^|\\.)communistcrimes\\.org$\n(^|\\.)communitychoicecu\\.com$\n(^|\\.)community\\.windy\\.com$\n(^|\\.)compileheart\\.com$\n(^|\\.)compress\\.to$\n(^|\\.)co\\.ng\\.mil$\n(^|\\.)connect\\.facebook\\.net$\n(^|\\.)conoha\\.jp$\n(^|\\.)contactmagazine\\.net$\n(^|\\.)contests\\.twilio\\.com$\n(^|\\.)convio\\.net$\n(^|\\.)coobay\\.com$\n(^|\\.)coolaler\\.com$\n(^|\\.)coolder\\.com$\n(^|\\.)coolloud\\.org\\.tw$\n(^|\\.)coolncute\\.com$\n(^|\\.)coolstuffinc\\.com$\n(^|\\.)corumcollege\\.com$\n(^|\\.)cosmic\\.monar\\.ch$\n(^|\\.)cos-moe\\.com$\n(^|\\.)cosplayjav\\.pl$\n(^|\\.)costco\\.com$\n(^|\\.)cotweet\\.com$\n(^|\\.)counter\\.social$\n(^|\\.)coursehero\\.com$\n(^|\\.)cpj\\.org$\n(^|\\.)cq99\\.us$\n(^|\\.)crackle\\.com$\n(^|\\.)crazys\\.cc$\n(^|\\.)crazyshit\\.com$\n(^|\\.)crbug\\.com$\n(^|\\.)crchina\\.org$\n(^|\\.)crd-net\\.org$\n(^|\\.)creaders\\.net$\n(^|\\.)creadersnet\\.com$\n(^|\\.)creativelab5\\.com$\n(^|\\.)crisisresponse\\.google$\n(^|\\.)cristyli\\.com$\n(^|\\.)crocotube\\.com$\n(^|\\.)crossfire\\.co\\.kr$\n(^|\\.)crossthewall\\.net$\n(^|\\.)crossvpn\\.net$\n(^|\\.)crrev\\.com$\n(^|\\.)crucial\\.com$\n(^|\\.)csdparty\\.com$\n(^|\\.)c-spanvideo\\.org$\n(^|\\.)css\\.pixnet\\.in$\n(^|\\.)csuchen\\.de$\n(^|\\.)csw\\.org\\.uk$\n(^|\\.)ctao\\.org$\n(^|\\.)ctfriend\\.net$\n(^|\\.)cthlo\\.github\\.io$\n(^|\\.)ctitv\\.com\\.tw$\n(^|\\.)ct\\.org\\.tw$\n(^|\\.)cts\\.com\\.tw$\n(^|\\.)cuhkacs\\.org$\n(^|\\.)cuihua\\.org$\n(^|\\.)cuiweiping\\.net$\n(^|\\.)culture\\.tw$\n(^|\\.)cumlouder\\.com$\n(^|\\.)curvefish\\.com$\n(^|\\.)cusu\\.hk$\n(^|\\.)cutscenes\\.net$\n(^|\\.)cw\\.com\\.tw$\n(^|\\.)cyberghost\\.natado\\.com$\n(^|\\.)cyberghostvpn\\.com$\n(^|\\.)cynscribe\\.com$\n(^|\\.)cytode\\.us$\n(^|\\.)d100\\.net$\n(^|\\.)d1b183sg0nvnuh\\.cloudfront\\.net$\n(^|\\.)d1c37gjwa26taa\\.cloudfront\\.net$\n(^|\\.)d2bay\\.com$\n(^|\\.)d2pass\\.com$\n(^|\\.)d3c33hcgiwev3\\.cloudfront\\.net$\n(^|\\.)d3rhr7kgmtrq1v\\.cloudfront\\.net$\n(^|\\.)dabr\\.co\\.uk$\n(^|\\.)dabr\\.eu$\n(^|\\.)dabr\\.me$\n(^|\\.)dabr\\.mobi$\n(^|\\.)dadazim\\.com$\n(^|\\.)dadi360\\.com$\n(^|\\.)dafabet\\.com$\n(^|\\.)dafagood\\.com$\n(^|\\.)dafahao\\.com$\n(^|\\.)dafoh\\.org$\n(^|\\.)daftporn\\.com$\n(^|\\.)dagelijksestandaard\\.nl$\n(^|\\.)daidostup\\.ru$\n(^|\\.)dailidaili\\.com$\n(^|\\.)dailymotion\\.com$\n(^|\\.)dailynews\\.sina\\.com$\n(^|\\.)dailyview\\.tw$\n(^|\\.)daiphapinfo\\.net$\n(^|\\.)dajiyuan\\.com$\n(^|\\.)dajiyuan\\.de$\n(^|\\.)dajiyuan\\.eu$\n(^|\\.)dajusha\\.baywords\\.com$\n(^|\\.)dalailama80\\.org$\n(^|\\.)dalailama-archives\\.org$\n(^|\\.)dalailamacenter\\.org$\n(^|\\.)dalailama\\.com$\n(^|\\.)dalailamafellows\\.org$\n(^|\\.)dalailamafilm\\.com$\n(^|\\.)dalailamafoundation\\.org$\n(^|\\.)dalailamahindi\\.com$\n(^|\\.)dalailamainaustralia\\.org$\n(^|\\.)dalailamajapanese\\.com$\n(^|\\.)dalailama\\.mn$\n(^|\\.)dalailamaprotesters\\.info$\n(^|\\.)dalailamaquotes\\.org$\n(^|\\.)dalailama\\.ru$\n(^|\\.)dalailamatrust\\.org$\n(^|\\.)dalailama\\.usc\\.edu$\n(^|\\.)dalailamavisit\\.org\\.nz$\n(^|\\.)dalailamaworld\\.com$\n(^|\\.)dalianmeng\\.org$\n(^|\\.)daliulian\\.org$\n(^|\\.)danbooru\\.donmai\\.us$\n(^|\\.)danke4china\\.net$\n(^|\\.)danwei\\.org$\n(^|\\.)daodu14\\.jigsy\\.com$\n(^|\\.)daolan\\.net$\n(^|\\.)daozhongxing\\.org$\n(^|\\.)darktech\\.org$\n(^|\\.)darktoy\\.net$\n(^|\\.)darpa\\.mil$\n(^|\\.)dastrassi\\.org$\n(^|\\.)data\\.flurry\\.com$\n(^|\\.)data\\.gov\\.tw$\n(^|\\.)data-vocabulary\\.org$\n(^|\\.)daum\\.net$\n(^|\\.)david-kilgour\\.com$\n(^|\\.)dawangidc\\.com$\n(^|\\.)daxa\\.cn$\n(^|\\.)daylife\\.com$\n(^|\\.)dbc\\.hk$\n(^|\\.)db\\.tt$\n(^|\\.)dcard\\.tw$\n(^|\\.)dcmilitary\\.com$\n(^|\\.)ddc\\.com\\.tw$\n(^|\\.)ddhw\\.info$\n(^|\\.)ddns\\.info$\n(^|\\.)ddns\\.me\\.uk$\n(^|\\.)ddns\\.mobi$\n(^|\\.)ddns\\.ms$\n(^|\\.)ddns\\.name$\n(^|\\.)ddns\\.net$\n(^|\\.)ddns\\.us$\n(^|\\.)deaftone\\.com$\n(^|\\.)debug\\.com$\n(^|\\.)deck\\.ly$\n(^|\\.)decodet\\.co$\n(^|\\.)deepmind\\.com$\n(^|\\.)deezer\\.com$\n(^|\\.)definebabe\\.com$\n(^|\\.)deja\\.com$\n(^|\\.)delcamp\\.net$\n(^|\\.)delicious\\.com$\n(^|\\.)democrats\\.org$\n(^|\\.)demo\\.opera-mini\\.net$\n(^|\\.)demosisto\\.hk$\n(^|\\.)depositphotos\\.com$\n(^|\\.)derekhsu\\.homeip\\.net$\n(^|\\.)de-sci\\.org$\n(^|\\.)desc\\.se$\n(^|\\.)design\\.google$\n(^|\\.)desipro\\.de$\n(^|\\.)dessci\\.com$\n(^|\\.)destiny\\.xfiles\\.to$\n(^|\\.)destroy-china\\.jp$\n(^|\\.)deutsche-welle\\.de$\n(^|\\.)developers\\.box\\.net$\n(^|\\.)devio\\.us$\n(^|\\.)devpn\\.com$\n(^|\\.)dfas\\.mil$\n(^|\\.)dfn\\.org$\n(^|\\.)d-fukyu\\.com$\n(^|\\.)dharamsalanet\\.com$\n(^|\\.)dharmakara\\.net$\n(^|\\.)dhcp\\.biz$\n(^|\\.)diaoyuislands\\.org$\n(^|\\.)dictionary\\.goo\\.ne\\.jp$\n(^|\\.)difangwenge\\.org$\n(^|\\.)digiland\\.tw$\n(^|\\.)digisfera\\.com$\n(^|\\.)digitalnomadsproject\\.org$\n(^|\\.)diigo\\.com$\n(^|\\.)dilber\\.se$\n(^|\\.)dingchin\\.com\\.tw$\n(^|\\.)dipity\\.com$\n(^|\\.)directcreative\\.com$\n(^|\\.)discoins\\.com$\n(^|\\.)disconnect\\.me$\n(^|\\.)discordapp\\.com$\n(^|\\.)discordapp\\.net$\n(^|\\.)discuss4u\\.com$\n(^|\\.)discuss\\.com\\.hk$\n(^|\\.)dish\\.com$\n(^|\\.)disp\\.cc$\n(^|\\.)disqus\\.com$\n(^|\\.)dit-inc\\.us$\n(^|\\.)dizhidizhi\\.com$\n(^|\\.)dizhuzhishang\\.com$\n(^|\\.)djangosnippets\\.org$\n(^|\\.)djorz\\.com$\n(^|\\.)dl\\.box\\.net$\n(^|\\.)dl-laby\\.jp$\n(^|\\.)dlsite\\.com$\n(^|\\.)dlyoutube\\.com$\n(^|\\.)dm530\\.net$\n(^|\\.)dmcdn\\.net$\n(^|\\.)dmhy\\.org$\n(^|\\.)dmm\\.co\\.jp$\n(^|\\.)dns04\\.com$\n(^|\\.)dns05\\.com$\n(^|\\.)dns1\\.us$\n(^|\\.)dns2go\\.com$\n(^|\\.)dns2\\.us$\n(^|\\.)dnscrypt\\.org$\n(^|\\.)dns-dns\\.com$\n(^|\\.)dnset\\.com$\n(^|\\.)dns\\.google$\n(^|\\.)dnsrd\\.com$\n(^|\\.)dnssec\\.net$\n(^|\\.)dns-stuff\\.com$\n(^|\\.)dnvod\\.tv$\n(^|\\.)doctorvoice\\.org$\n(^|\\.)documentingreality\\.com$\n(^|\\.)dogfartnetwork\\.com$\n(^|\\.)dojin\\.com$\n(^|\\.)dok-forum\\.net$\n(^|\\.)dolc\\.de$\n(^|\\.)dolf\\.org\\.hk$\n(^|\\.)dollf\\.com$\n(^|\\.)domain\\.club\\.tw$\n(^|\\.)domainhelp\\.search\\.com$\n(^|\\.)domains\\.google$\n(^|\\.)domaintoday\\.com\\.au$\n(^|\\.)dongtaiwang\\.com$\n(^|\\.)dongtaiwang\\.net$\n(^|\\.)dongyangjing\\.com$\n(^|\\.)dontfilter\\.us$\n(^|\\.)dontmovetochina\\.com$\n(^|\\.)dorjeshugden\\.com$\n(^|\\.)dotplane\\.com$\n(^|\\.)dotsub\\.com$\n(^|\\.)dotvpn\\.com$\n(^|\\.)doubibackup\\.com$\n(^|\\.)doub\\.io$\n(^|\\.)doubmirror\\.cf$\n(^|\\.)dougscripts\\.com$\n(^|\\.)douhokanko\\.net$\n(^|\\.)doujincafe\\.com$\n(^|\\.)dowei\\.org$\n(^|\\.)download\\.aircrack-ng\\.org$\n(^|\\.)download\\.cnet\\.com$\n(^|\\.)download\\.ithome\\.com\\.tw$\n(^|\\.)dphk\\.org$\n(^|\\.)dpp\\.org\\.tw$\n(^|\\.)dpr\\.info$\n(^|\\.)dragonex\\.io$\n(^|\\.)dragonsprings\\.org$\n(^|\\.)dreamamateurs\\.com$\n(^|\\.)drepung\\.org$\n(^|\\.)drgan\\.net$\n(^|\\.)drmingxia\\.org$\n(^|\\.)dropbooks\\.tv$\n(^|\\.)dropbox\\.com$\n(^|\\.)dropboxusercontent\\.com$\n(^|\\.)drsunacademy\\.com$\n(^|\\.)drtuber\\.com$\n(^|\\.)dscn\\.info$\n(^|\\.)dsmtp\\.com$\n(^|\\.)dstk\\.dk$\n(^|\\.)dtdns\\.net$\n(^|\\.)dtiblog\\.com$\n(^|\\.)dtic\\.mil$\n(^|\\.)dtwang\\.org$\n(^|\\.)duanzhihu\\.com$\n(^|\\.)duck\\.com$\n(^|\\.)duckdns\\.org$\n(^|\\.)duckduckgo\\.com$\n(^|\\.)duckduckgo-owned-server\\.yahoo\\.net$\n(^|\\.)duckload\\.com$\n(^|\\.)duckmylife\\.com$\n(^|\\.)duga\\.jp$\n(^|\\.)duihuahrjournal\\.org$\n(^|\\.)duihua\\.org$\n(^|\\.)dumb1\\.com$\n(^|\\.)dunyabulteni\\.net$\n(^|\\.)duoweitimes\\.com$\n(^|\\.)duping\\.net$\n(^|\\.)duplicati\\.com$\n(^|\\.)dupola\\.com$\n(^|\\.)dupola\\.net$\n(^|\\.)dushi\\.ca$\n(^|\\.)dvdpac\\.com$\n(^|\\.)dvorak\\.org$\n(^|\\.)dw\\.com$\n(^|\\.)dw\\.de$\n(^|\\.)dwnews\\.com$\n(^|\\.)dwnews\\.net$\n(^|\\.)dw-world\\.com$\n(^|\\.)dw-world\\.de$\n(^|\\.)dynamicdns\\.biz$\n(^|\\.)dynamicdns\\.co\\.uk$\n(^|\\.)dynamicdns\\.me\\.uk$\n(^|\\.)dynamic-dns\\.net$\n(^|\\.)dynamicdns\\.org\\.uk$\n(^|\\.)dynawebinc\\.com$\n(^|\\.)dyndns-ip\\.com$\n(^|\\.)dyndns\\.org$\n(^|\\.)dyndns-pics\\.com$\n(^|\\.)dyndns\\.pro$\n(^|\\.)dynssl\\.com$\n(^|\\.)dynu\\.com$\n(^|\\.)dynu\\.net$\n(^|\\.)dynupdate\\.no-ip\\.com$\n(^|\\.)dysfz\\.cc$\n(^|\\.)dzze\\.com$\n(^|\\.)e123\\.hk$\n(^|\\.)earlytibet\\.com$\n(^|\\.)earthcam\\.com$\n(^|\\.)earthvpn\\.com$\n(^|\\.)eastern-ark\\.com$\n(^|\\.)easternlightning\\.org$\n(^|\\.)eastturkestan\\.com$\n(^|\\.)eastturkistancc\\.org$\n(^|\\.)eastturkistangovernmentinexile\\.us$\n(^|\\.)eastturkistan-gov\\.org$\n(^|\\.)easyca\\.ca$\n(^|\\.)easypic\\.com$\n(^|\\.)ebony-beauty\\.com$\n(^|\\.)ebookbrowse\\.com$\n(^|\\.)ebookee\\.com$\n(^|\\.)ebook\\.hyread\\.com\\.tw$\n(^|\\.)ebtcbank\\.com$\n(^|\\.)ecfa\\.org\\.tw$\n(^|\\.)echofon\\.com$\n(^|\\.)ecimg\\.tw$\n(^|\\.)e-classical\\.com\\.tw$\n(^|\\.)ecministry\\.net$\n(^|\\.)economist\\.com$\n(^|\\.)ecsm\\.vs\\.com$\n(^|\\.)edgecastcdn\\.net$\n(^|\\.)edicypages\\.com$\n(^|\\.)edmontonchina\\.cn$\n(^|\\.)edmontonservice\\.com$\n(^|\\.)edns\\.biz$\n(^|\\.)edoors\\.com$\n(^|\\.)edubridge\\.com$\n(^|\\.)edupro\\.org$\n(^|\\.)eeas\\.europa\\.eu$\n(^|\\.)eesti\\.ee$\n(^|\\.)eevpn\\.com$\n(^|\\.)efcc\\.org\\.hk$\n(^|\\.)effers\\.com$\n(^|\\.)efksoft\\.com$\n(^|\\.)efukt\\.com$\n(^|\\.)e-gold\\.com$\n(^|\\.)e-hentaidb\\.com$\n(^|\\.)e-hentai\\.org$\n(^|\\.)eic-av\\.com$\n(^|\\.)e-info\\.org\\.tw$\n(^|\\.)eireinikotaerukai\\.com$\n(^|\\.)eisbb\\.com$\n(^|\\.)eksisozluk\\.com$\n(^|\\.)electionsmeter\\.com$\n(^|\\.)elgoog\\.im$\n(^|\\.)ellawine\\.org$\n(^|\\.)elpais\\.com$\n(^|\\.)eltondisney\\.com$\n(^|\\.)emaga\\.com$\n(^|\\.)emanna\\.com$\n(^|\\.)embr\\.in$\n(^|\\.)emilylau\\.org\\.hk$\n(^|\\.)empfil\\.com$\n(^|\\.)emule-ed2k\\.com$\n(^|\\.)emulefans\\.com$\n(^|\\.)emuparadise\\.me$\n(^|\\.)enanyang\\.my$\n(^|\\.)encyclopedia\\.com$\n(^|\\.)enewstree\\.com$\n(^|\\.)enfal\\.de$\n(^|\\.)en\\.favotter\\.net$\n(^|\\.)engagedaily\\.org$\n(^|\\.)englishforeveryone\\.org$\n(^|\\.)englishfromengland\\.co\\.uk$\n(^|\\.)englishpen\\.org$\n(^|\\.)en\\.hao123\\.com$\n(^|\\.)enlighten\\.org\\.tw$\n(^|\\.)entermap\\.com$\n(^|\\.)entnt\\.com$\n(^|\\.)environment\\.google$\n(^|\\.)epac\\.to$\n(^|\\.)epa\\.gov\\.tw$\n(^|\\.)episcopalchurch\\.org$\n(^|\\.)epochhk\\.com$\n(^|\\.)epochtimes-bg\\.com$\n(^|\\.)epochtimes\\.co\\.il$\n(^|\\.)epochtimes\\.co\\.kr$\n(^|\\.)epochtimes\\.com$\n(^|\\.)epochtimes\\.cz$\n(^|\\.)epochtimes\\.de$\n(^|\\.)epochtimes\\.fr$\n(^|\\.)epochtimes\\.ie$\n(^|\\.)epochtimes\\.it$\n(^|\\.)epochtimes\\.jp$\n(^|\\.)epochtimes-romania\\.com$\n(^|\\.)epochtimes\\.ru$\n(^|\\.)epochtimes\\.se$\n(^|\\.)epochtimestr\\.com$\n(^|\\.)epochweek\\.com$\n(^|\\.)epochweekly\\.com$\n(^|\\.)eporner\\.com$\n(^|\\.)equinenow\\.com$\n(^|\\.)erabaru\\.net$\n(^|\\.)eracom\\.com\\.tw$\n(^|\\.)eraysoft\\.com\\.tr$\n(^|\\.)erepublik\\.com$\n(^|\\.)erights\\.net$\n(^|\\.)eriversoft\\.com$\n(^|\\.)erktv\\.com$\n(^|\\.)ernestmandel\\.org$\n(^|\\.)erodaizensyu\\.com$\n(^|\\.)erodoujinlog\\.com$\n(^|\\.)erodoujinworld\\.com$\n(^|\\.)eromangadouzin\\.com$\n(^|\\.)eromanga-kingdom\\.com$\n(^|\\.)eromon\\.net$\n(^|\\.)eroprofile\\.com$\n(^|\\.)eroticsaloon\\.net$\n(^|\\.)eslite\\.com$\n(^|\\.)esmtp\\.biz$\n(^|\\.)esurance\\.com$\n(^|\\.)etaa\\.org\\.au$\n(^|\\.)etadult\\.com$\n(^|\\.)etaiwannews\\.com$\n(^|\\.)etherdelta\\.com$\n(^|\\.)etizer\\.org$\n(^|\\.)etokki\\.com$\n(^|\\.)etools\\.ncol\\.com$\n(^|\\.)etowns\\.net$\n(^|\\.)etowns\\.org$\n(^|\\.)e-traderland\\.net$\n(^|\\.)ettoday\\.net$\n(^|\\.)etvonline\\.hk$\n(^|\\.)eucasino\\.com$\n(^|\\.)eulam\\.com$\n(^|\\.)eu\\.org$\n(^|\\.)eurekavpt\\.com$\n(^|\\.)euronews\\.com$\n(^|\\.)evchk\\.wikia\\.com$\n(^|\\.)evschool\\.net$\n(^|\\.)exblog\\.jp$\n(^|\\.)exchristian\\.hk$\n(^|\\.)exmo\\.com$\n(^|\\.)exmormon\\.org$\n(^|\\.)expatshield\\.com$\n(^|\\.)expecthim\\.com$\n(^|\\.)expekt\\.com$\n(^|\\.)experts-univers\\.com$\n(^|\\.)exploader\\.net$\n(^|\\.)expressvpn\\.com$\n(^|\\.)exrates\\.me$\n(^|\\.)extmatrix\\.com$\n(^|\\.)extremetube\\.com$\n(^|\\.)exx\\.com$\n(^|\\.)eyevio\\.jp$\n(^|\\.)eyny\\.com$\n(^|\\.)e-zone\\.com\\.hk$\n(^|\\.)ezpc\\.tk$\n(^|\\.)ezpeer\\.com$\n(^|\\.)ezua\\.com$\n(^|\\.)facebook\\.br$\n(^|\\.)facebook\\.com$\n(^|\\.)facebook\\.design$\n(^|\\.)facebook\\.hu$\n(^|\\.)facebook\\.in$\n(^|\\.)facebookmail\\.com$\n(^|\\.)facebook\\.nl$\n(^|\\.)facebookquotes4u\\.com$\n(^|\\.)facebook\\.se$\n(^|\\.)faceless\\.me$\n(^|\\.)facesofnyfw\\.com$\n(^|\\.)facesoftibetanselfimmolators\\.info$\n(^|\\.)fa\\.gov\\.tw$\n(^|\\.)fail\\.hk$\n(^|\\.)faith100\\.org$\n(^|\\.)faithfuleye\\.com$\n(^|\\.)faiththedog\\.info$\n(^|\\.)fakku\\.net$\n(^|\\.)falsefire\\.com$\n(^|\\.)falunart\\.org$\n(^|\\.)falunasia\\.info$\n(^|\\.)falunau\\.org$\n(^|\\.)falunaz\\.net$\n(^|\\.)falun\\.caltech\\.edu$\n(^|\\.)falun-co\\.org$\n(^|\\.)falundafa-dc\\.org$\n(^|\\.)falundafa-florida\\.org$\n(^|\\.)falundafaindia\\.org$\n(^|\\.)falundafamuseum\\.org$\n(^|\\.)falundafa-nc\\.org$\n(^|\\.)falundafa\\.org$\n(^|\\.)falundafa-pa\\.net$\n(^|\\.)falundafa-sacramento\\.org$\n(^|\\.)falungong\\.club$\n(^|\\.)falungong\\.de$\n(^|\\.)falungong\\.org\\.uk$\n(^|\\.)falunhr\\.org$\n(^|\\.)faluninfo\\.de$\n(^|\\.)faluninfo\\.net$\n(^|\\.)falun-ny\\.net$\n(^|\\.)falunpilipinas\\.net$\n(^|\\.)falunworld\\.net$\n(^|\\.)familyfed\\.org$\n(^|\\.)famunion\\.com$\n(^|\\.)fangbinxing\\.com$\n(^|\\.)fangeming\\.com$\n(^|\\.)fangeqiang\\.com$\n(^|\\.)fanglizhi\\.info$\n(^|\\.)fangmincn\\.org$\n(^|\\.)fangong\\.forums-free\\.com$\n(^|\\.)fangongheike\\.com$\n(^|\\.)fangong\\.org$\n(^|\\.)fanhaodang\\.com$\n(^|\\.)fan-qiang\\.com$\n(^|\\.)fanqiangdang\\.com$\n(^|\\.)fanqianghou\\.com$\n(^|\\.)fanqiang\\.tk$\n(^|\\.)fanqiangyakexi\\.net$\n(^|\\.)fanqiangzhe\\.com$\n(^|\\.)fanswong\\.com$\n(^|\\.)fanyue\\.info$\n(^|\\.)fapdu\\.com$\n(^|\\.)faproxy\\.com$\n(^|\\.)faqserv\\.com$\n(^|\\.)fartit\\.com$\n(^|\\.)farwestchina\\.com$\n(^|\\.)fastpic\\.ru$\n(^|\\.)fastssh\\.com$\n(^|\\.)faststone\\.org$\n(^|\\.)fast\\.wistia\\.com$\n(^|\\.)fatbtc\\.com$\n(^|\\.)favstar\\.fm$\n(^|\\.)fawanghuihui\\.org$\n(^|\\.)faydao\\.com$\n(^|\\.)fbaddins\\.com$\n(^|\\.)fbcdn\\.net$\n(^|\\.)fb\\.com$\n(^|\\.)fb\\.me$\n(^|\\.)fbsbx\\.com$\n(^|\\.)fbworkmail\\.com$\n(^|\\.)fc2blog\\.net$\n(^|\\.)fc2china\\.com$\n(^|\\.)fc2cn\\.com$\n(^|\\.)fc2\\.com$\n(^|\\.)fda\\.gov\\.tw$\n(^|\\.)fdc64\\.de$\n(^|\\.)fdc64\\.org$\n(^|\\.)fdc89\\.jp$\n(^|\\.)feedburner\\.com$\n(^|\\.)feeds\\.fileforum\\.com$\n(^|\\.)feedx\\.net$\n(^|\\.)feelssh\\.com$\n(^|\\.)feer\\.com$\n(^|\\.)feifeiss\\.com$\n(^|\\.)feitianacademy\\.org$\n(^|\\.)feitian-california\\.org$\n(^|\\.)feministteacher\\.com$\n(^|\\.)fengzhenghu\\.com$\n(^|\\.)fengzhenghu\\.net$\n(^|\\.)fevernet\\.com$\n(^|\\.)fffff\\.at$\n(^|\\.)ff\\.im$\n(^|\\.)fflick\\.com$\n(^|\\.)ffvpn\\.com$\n(^|\\.)fgmtv\\.net$\n(^|\\.)fgmtv\\.org$\n(^|\\.)fhreports\\.net$\n(^|\\.)fiddle\\.jshell\\.net$\n(^|\\.)figprayer\\.com$\n(^|\\.)fileflyer\\.com$\n(^|\\.)files2me\\.com$\n(^|\\.)fileserve\\.com$\n(^|\\.)filesor\\.com$\n(^|\\.)fillthesquare\\.org$\n(^|\\.)filmingfortibet\\.org$\n(^|\\.)filmy\\.olabloga\\.pl$\n(^|\\.)filthdump\\.com$\n(^|\\.)financetwitter\\.com$\n(^|\\.)finchvpn\\.com$\n(^|\\.)findmespot\\.com$\n(^|\\.)findyoutube\\.com$\n(^|\\.)findyoutube\\.net$\n(^|\\.)fingerdaily\\.com$\n(^|\\.)finler\\.net$\n(^|\\.)firearmsworld\\.net$\n(^|\\.)firebaseio\\.com$\n(^|\\.)fireofliberty\\.org$\n(^|\\.)firetweet\\.io$\n(^|\\.)firstfivefollowers\\.com$\n(^|\\.)flagsonline\\.it$\n(^|\\.)flecheinthepeche\\.fr$\n(^|\\.)fleshbot\\.com$\n(^|\\.)fleursdeslettres\\.com$\n(^|\\.)flgg\\.us$\n(^|\\.)flgjustice\\.org$\n(^|\\.)flickr\\.com$\n(^|\\.)flickrhivemind\\.net$\n(^|\\.)flickriver\\.com$\n(^|\\.)fling\\.com$\n(^|\\.)flipboard\\.com$\n(^|\\.)flipkart\\.com$\n(^|\\.)flitto\\.com$\n(^|\\.)flnet\\.org$\n(^|\\.)flog\\.tw$\n(^|\\.)flyvpn\\.com$\n(^|\\.)flyzy2005\\.com$\n(^|\\.)fnac\\.be$\n(^|\\.)fnac\\.com$\n(^|\\.)fochk\\.org$\n(^|\\.)focustaiwan\\.tw$\n(^|\\.)focusvpn\\.com$\n(^|\\.)fofg-europe\\.net$\n(^|\\.)fofg\\.org$\n(^|\\.)fofldfradio\\.org$\n(^|\\.)fooooo\\.com$\n(^|\\.)footwiball\\.com$\n(^|\\.)foreignpolicy\\.com$\n(^|\\.)forum4hk\\.com$\n(^|\\.)forum\\.baby-kingdom\\.com$\n(^|\\.)forum\\.cyberctm\\.com$\n(^|\\.)forum\\.idsam\\.com$\n(^|\\.)forum\\.my903\\.com$\n(^|\\.)forum\\.mymaji\\.com$\n(^|\\.)forum\\.omy\\.sg$\n(^|\\.)forum\\.palmislife\\.com$\n(^|\\.)forum\\.setty\\.com\\.tw$\n(^|\\.)forum\\.sina\\.com\\.hk$\n(^|\\.)forum\\.slime\\.com\\.tw$\n(^|\\.)forum\\.tvb\\.com$\n(^|\\.)forum\\.xinbao\\.de$\n(^|\\.)fotile\\.me$\n(^|\\.)fourface\\.nodesnoop\\.com$\n(^|\\.)fourthinternational\\.org$\n(^|\\.)foxdie\\.us$\n(^|\\.)foxgay\\.com$\n(^|\\.)foxsub\\.com$\n(^|\\.)foxtang\\.com$\n(^|\\.)fpmtmexico\\.org$\n(^|\\.)fpmt\\.org$\n(^|\\.)fpmt-osel\\.org$\n(^|\\.)fpmt\\.tw$\n(^|\\.)fqok\\.org$\n(^|\\.)fqrouter\\.com$\n(^|\\.)fq\\.wikia\\.com$\n(^|\\.)franklc\\.com$\n(^|\\.)freakshare\\.com$\n(^|\\.)free4u\\.com\\.ar$\n(^|\\.)freealim\\.com$\n(^|\\.)freebrowser\\.org$\n(^|\\.)freechal\\.com$\n(^|\\.)freechinaforum\\.org$\n(^|\\.)freechina\\.net$\n(^|\\.)freechina\\.news$\n(^|\\.)freechinaweibo\\.com$\n(^|\\.)freeddns\\.com$\n(^|\\.)freeddns\\.org$\n(^|\\.)freedomchina\\.info$\n(^|\\.)freedomcollection\\.org$\n(^|\\.)freedomhouse\\.org$\n(^|\\.)freedominfonetweb\\.wordpress\\.com$\n(^|\\.)freedomsherald\\.org$\n(^|\\.)freeforums\\.org$\n(^|\\.)freefq\\.com$\n(^|\\.)free\\.fr$\n(^|\\.)freefuckvids\\.com$\n(^|\\.)freegao\\.com$\n(^|\\.)free-gate\\.org$\n(^|\\.)free-hada-now\\.org$\n(^|\\.)freehongkong\\.org$\n(^|\\.)freeilhamtohti\\.org$\n(^|\\.)freekwonpyong\\.org$\n(^|\\.)freelotto\\.com$\n(^|\\.)freeman2\\.com$\n(^|\\.)freemoren\\.com$\n(^|\\.)freemorenews\\.com$\n(^|\\.)freemuse\\.org$\n(^|\\.)freenet-china\\.org$\n(^|\\.)freenetproject\\.org$\n(^|\\.)freenewscn\\.com$\n(^|\\.)freeopenvpn\\.com$\n(^|\\.)freeoz\\.org$\n(^|\\.)free-proxy\\.cz$\n(^|\\.)free-ssh\\.com$\n(^|\\.)freessh\\.us$\n(^|\\.)free-ss\\.site$\n(^|\\.)freetcp\\.com$\n(^|\\.)freetibetanheroes\\.org$\n(^|\\.)freetibet\\.net$\n(^|\\.)freetibet\\.org$\n(^|\\.)freeviewmovies\\.com$\n(^|\\.)freevpn\\.me$\n(^|\\.)freevpn\\.nl$\n(^|\\.)freewallpaper4\\.me$\n(^|\\.)freewebs\\.com$\n(^|\\.)freewechat\\.com$\n(^|\\.)freeweibo\\.com$\n(^|\\.)freewww\\.biz$\n(^|\\.)freewww\\.info$\n(^|\\.)freexinwen\\.com$\n(^|\\.)freeyellow\\.com$\n(^|\\.)freeyoutubeproxy\\.net$\n(^|\\.)friendfeed\\.com$\n(^|\\.)friendfeed-media\\.com$\n(^|\\.)friends-of-tibet\\.org$\n(^|\\.)friendsoftibet\\.org$\n(^|\\.)fring\\.com$\n(^|\\.)fringenetwork\\.com$\n(^|\\.)fromchinatousa\\.net$\n(^|\\.)frommel\\.net$\n(^|\\.)from-pr\\.com$\n(^|\\.)from-sd\\.com$\n(^|\\.)frontlinedefenders\\.org$\n(^|\\.)frootvpn\\.com$\n(^|\\.)fscked\\.org$\n(^|\\.)fsurf\\.com$\n(^|\\.)ftchinese\\.com$\n(^|\\.)ftp1\\.biz$\n(^|\\.)ftpserver\\.biz$\n(^|\\.)ftv\\.com\\.tw$\n(^|\\.)fucd\\.com$\n(^|\\.)fuckcnnic\\.net$\n(^|\\.)fuckgfw\\.org$\n(^|\\.)fulione\\.com$\n(^|\\.)fullerconsideration\\.com$\n(^|\\.)fulue\\.com$\n(^|\\.)funf\\.tw$\n(^|\\.)funkyimg\\.com$\n(^|\\.)funp\\.com$\n(^|\\.)fuq\\.com$\n(^|\\.)furbo\\.org$\n(^|\\.)furhhdl\\.org$\n(^|\\.)furinkan\\.com$\n(^|\\.)furl\\.net$\n(^|\\.)futurechinaforum\\.org$\n(^|\\.)futuremessage\\.org$\n(^|\\.)fux\\.com$\n(^|\\.)fuyindiantai\\.org$\n(^|\\.)fuyin\\.net$\n(^|\\.)fuyu\\.org\\.tw$\n(^|\\.)fw\\.cm$\n(^|\\.)fxcm-chinese\\.com$\n(^|\\.)fxnetworks\\.com$\n(^|\\.)fzh999\\.com$\n(^|\\.)fzh999\\.net$\n(^|\\.)fzlm\\.com$\n(^|\\.)g0v\\.social$\n(^|\\.)g6hentai\\.com$\n(^|\\.)gabocorp\\.com$\n(^|\\.)gaeproxy\\.com$\n(^|\\.)gaforum\\.org$\n(^|\\.)galaxymacau\\.com$\n(^|\\.)galenwu\\.com$\n(^|\\.)galstars\\.net$\n(^|\\.)game735\\.com$\n(^|\\.)gamebase\\.com\\.tw$\n(^|\\.)gamejolt\\.com$\n(^|\\.)gamer2-cds\\.cdn\\.hinet\\.net$\n(^|\\.)gamer-cds\\.cdn\\.hinet\\.net$\n(^|\\.)gamer\\.com\\.tw$\n(^|\\.)gamez\\.com\\.tw$\n(^|\\.)gamousa\\.com$\n(^|\\.)ganges\\.com$\n(^|\\.)gaoming\\.net$\n(^|\\.)gaopi\\.net$\n(^|\\.)gaozhisheng\\.net$\n(^|\\.)gaozhisheng\\.org$\n(^|\\.)gardennetworks\\.com$\n(^|\\.)gardennetworks\\.org$\n(^|\\.)g-area\\.org$\n(^|\\.)gartlive\\.com$\n(^|\\.)gatecoin\\.com$\n(^|\\.)gate\\.io$\n(^|\\.)gate-project\\.com$\n(^|\\.)gather\\.com$\n(^|\\.)gatherproxy\\.com$\n(^|\\.)gati\\.org\\.tw$\n(^|\\.)gaybubble\\.com$\n(^|\\.)gaycn\\.net$\n(^|\\.)gayhub\\.com$\n(^|\\.)gaymap\\.cc$\n(^|\\.)gaymenring\\.com$\n(^|\\.)gaytube\\.com$\n(^|\\.)gaywatch\\.com$\n(^|\\.)gazotube\\.com$\n(^|\\.)gcc\\.org\\.hk$\n(^|\\.)gclooney\\.com$\n(^|\\.)gcmasia\\.com$\n(^|\\.)g\\.co$\n(^|\\.)gcpnews\\.com$\n(^|\\.)gcr\\.io$\n(^|\\.)gdbt\\.net$\n(^|\\.)gdzf\\.org$\n(^|\\.)geek-art\\.net$\n(^|\\.)geekerhome\\.com$\n(^|\\.)geekheart\\.info$\n(^|\\.)gekikame\\.com$\n(^|\\.)gelbooru\\.com$\n(^|\\.)geocities\\.co\\.jp$\n(^|\\.)geocities\\.com$\n(^|\\.)geocities\\.jp$\n(^|\\.)gerefoundation\\.org$\n(^|\\.)get\\.app$\n(^|\\.)getastrill\\.com$\n(^|\\.)getchu\\.com$\n(^|\\.)getcloak\\.com$\n(^|\\.)get\\.dev$\n(^|\\.)getfoxyproxy\\.org$\n(^|\\.)getfreedur\\.com$\n(^|\\.)getgom\\.com$\n(^|\\.)get\\.how$\n(^|\\.)geti2p\\.net$\n(^|\\.)getiton\\.com$\n(^|\\.)getjetso\\.com$\n(^|\\.)getlantern\\.org$\n(^|\\.)getmdl\\.io$\n(^|\\.)getoutline\\.org$\n(^|\\.)get\\.page$\n(^|\\.)getsocialscope\\.com$\n(^|\\.)getsync\\.com$\n(^|\\.)gettrials\\.com$\n(^|\\.)gettyimages\\.com$\n(^|\\.)getuploader\\.com$\n(^|\\.)gfbv\\.de$\n(^|\\.)gfgold\\.com\\.hk$\n(^|\\.)gfsale\\.com$\n(^|\\.)gfw\\.org\\.ua$\n(^|\\.)gfw\\.press$\n(^|\\.)ggpht\\.com$\n(^|\\.)ggssl\\.com$\n(^|\\.)ghostpath\\.com$\n(^|\\.)ghut\\.org$\n(^|\\.)giantessnight\\.com$\n(^|\\.)gifree\\.com$\n(^|\\.)giga-web\\.jp$\n(^|\\.)gigporno\\.ru$\n(^|\\.)girlbanker\\.com$\n(^|\\.)gist\\.github\\.com$\n(^|\\.)github\\.com$\n(^|\\.)git\\.io$\n(^|\\.)gizlen\\.net$\n(^|\\.)gjczz\\.com$\n(^|\\.)glass8\\.eu$\n(^|\\.)global\\.bing\\.com$\n(^|\\.)globaljihad\\.net$\n(^|\\.)globalmediaoutreach\\.com$\n(^|\\.)globalmuseumoncommunism\\.org$\n(^|\\.)globalrescue\\.net$\n(^|\\.)globaltm\\.org$\n(^|\\.)globalvoicesonline\\.org$\n(^|\\.)globalvoices\\.org$\n(^|\\.)globalvpn\\.net$\n(^|\\.)glock\\.com$\n(^|\\.)gloryhole\\.com$\n(^|\\.)glorystar\\.me$\n(^|\\.)gluckman\\.com$\n(^|\\.)glype\\.com$\n(^|\\.)gmail\\.com$\n(^|\\.)gmbd\\.cn$\n(^|\\.)gmhz\\.org$\n(^|\\.)gmll\\.org$\n(^|\\.)gmodules\\.com$\n(^|\\.)gmozomg\\.izihost\\.org$\n(^|\\.)gnci\\.org\\.hk$\n(^|\\.)go141\\.com$\n(^|\\.)goagent\\.biz$\n(^|\\.)goagent\\.codeplex\\.com$\n(^|\\.)goagentplus\\.com$\n(^|\\.)gobet\\.cc$\n(^|\\.)godfootsteps\\.org$\n(^|\\.)godns\\.work$\n(^|\\.)godoc\\.org$\n(^|\\.)godsdirectcontact\\.co\\.uk$\n(^|\\.)godsdirectcontact\\.org$\n(^|\\.)godsdirectcontact\\.org\\.tw$\n(^|\\.)godsimmediatecontact\\.com$\n(^|\\.)gogotunnel\\.com$\n(^|\\.)gohappy\\.com\\.tw$\n(^|\\.)gojet\\.krtco\\.com\\.tw$\n(^|\\.)gokbayrak\\.com$\n(^|\\.)golang\\.org$\n(^|\\.)goldbet\\.com$\n(^|\\.)goldbetsports\\.com$\n(^|\\.)goldeneyevault\\.com$\n(^|\\.)goldenfrog\\.com$\n(^|\\.)goldjizz\\.com$\n(^|\\.)goldstep\\.net$\n(^|\\.)goldwave\\.com$\n(^|\\.)go\\.nesnode\\.com$\n(^|\\.)gongmeng\\.info$\n(^|\\.)gongm\\.in$\n(^|\\.)gongminliliang\\.com$\n(^|\\.)gongwt\\.com$\n(^|\\.)gooday\\.xyz$\n(^|\\.)gooddns\\.info$\n(^|\\.)goodreaders\\.com$\n(^|\\.)goodreads\\.com$\n(^|\\.)goodtv\\.com\\.tw$\n(^|\\.)goodtv\\.tv$\n(^|\\.)goofind\\.com$\n(^|\\.)goo\\.gl$\n(^|\\.)google\\.ad$\n(^|\\.)google\\.ae$\n(^|\\.)google\\.al$\n(^|\\.)google\\.am$\n(^|\\.)googleapis\\.cn$\n(^|\\.)googleapis\\.com$\n(^|\\.)googleapps\\.com$\n(^|\\.)googlearth\\.com$\n(^|\\.)googleartproject\\.com$\n(^|\\.)google\\.as$\n(^|\\.)google\\.at$\n(^|\\.)google\\.az$\n(^|\\.)google\\.ba$\n(^|\\.)google\\.be$\n(^|\\.)google\\.bf$\n(^|\\.)google\\.bg$\n(^|\\.)google\\.bi$\n(^|\\.)google\\.bj$\n(^|\\.)googleblog\\.com$\n(^|\\.)googlebot\\.com$\n(^|\\.)google\\.bs$\n(^|\\.)google\\.bt$\n(^|\\.)google\\.by$\n(^|\\.)google\\.ca$\n(^|\\.)google\\.calstate\\.edu$\n(^|\\.)google\\.cat$\n(^|\\.)google\\.cd$\n(^|\\.)google\\.cf$\n(^|\\.)google\\.cg$\n(^|\\.)google\\.ch$\n(^|\\.)googlechinawebmaster\\.com$\n(^|\\.)google\\.ci$\n(^|\\.)google\\.cl$\n(^|\\.)google\\.cm$\n(^|\\.)google\\.cn$\n(^|\\.)google\\.co\\.ao$\n(^|\\.)google\\.co\\.bw$\n(^|\\.)google\\.co\\.ck$\n(^|\\.)google\\.co\\.cr$\n(^|\\.)googlecode\\.com$\n(^|\\.)google\\.co\\.id$\n(^|\\.)google\\.co\\.il$\n(^|\\.)google\\.co\\.in$\n(^|\\.)google\\.co\\.jp$\n(^|\\.)google\\.co\\.ke$\n(^|\\.)google\\.co\\.kr$\n(^|\\.)google\\.co\\.ls$\n(^|\\.)google\\.com$\n(^|\\.)google\\.co\\.ma$\n(^|\\.)google\\.com\\.af$\n(^|\\.)google\\.com\\.ag$\n(^|\\.)google\\.com\\.ai$\n(^|\\.)google\\.com\\.ar$\n(^|\\.)google\\.com\\.au$\n(^|\\.)google\\.com\\.bd$\n(^|\\.)google\\.com\\.bh$\n(^|\\.)google\\.com\\.bn$\n(^|\\.)google\\.com\\.bo$\n(^|\\.)google\\.com\\.br$\n(^|\\.)google\\.com\\.bz$\n(^|\\.)google\\.com\\.co$\n(^|\\.)google\\.com\\.cu$\n(^|\\.)google\\.com\\.cy$\n(^|\\.)google\\.com\\.do$\n(^|\\.)google\\.com\\.ec$\n(^|\\.)google\\.com\\.eg$\n(^|\\.)google\\.com\\.et$\n(^|\\.)google\\.com\\.fj$\n(^|\\.)google\\.com\\.gh$\n(^|\\.)google\\.com\\.gi$\n(^|\\.)google\\.com\\.gt$\n(^|\\.)google\\.com\\.hk$\n(^|\\.)google\\.com\\.jm$\n(^|\\.)google\\.com\\.kh$\n(^|\\.)google\\.com\\.kw$\n(^|\\.)google\\.com\\.lb$\n(^|\\.)google\\.com\\.ly$\n(^|\\.)googlecommerce\\.com$\n(^|\\.)google\\.com\\.mm$\n(^|\\.)google\\.com\\.mt$\n(^|\\.)google\\.com\\.mx$\n(^|\\.)google\\.com\\.my$\n(^|\\.)google\\.com\\.na$\n(^|\\.)google\\.com\\.nf$\n(^|\\.)google\\.com\\.ng$\n(^|\\.)google\\.com\\.ni$\n(^|\\.)google\\.com\\.np$\n(^|\\.)google\\.com\\.om$\n(^|\\.)google\\.com\\.pa$\n(^|\\.)google\\.com\\.pe$\n(^|\\.)google\\.com\\.pg$\n(^|\\.)google\\.com\\.ph$\n(^|\\.)google\\.com\\.pk$\n(^|\\.)google\\.com\\.pr$\n(^|\\.)google\\.com\\.py$\n(^|\\.)google\\.com\\.qa$\n(^|\\.)google\\.com\\.sa$\n(^|\\.)google\\.com\\.sb$\n(^|\\.)google\\.com\\.sg$\n(^|\\.)google\\.com\\.sl$\n(^|\\.)google\\.com\\.sv$\n(^|\\.)google\\.com\\.tj$\n(^|\\.)google\\.com\\.tr$\n(^|\\.)google\\.com\\.tw$\n(^|\\.)google\\.com\\.ua$\n(^|\\.)google\\.com\\.uy$\n(^|\\.)google\\.com\\.vc$\n(^|\\.)google\\.com\\.vn$\n(^|\\.)google\\.co\\.mz$\n(^|\\.)google\\.co\\.nz$\n(^|\\.)google\\.co\\.th$\n(^|\\.)google\\.co\\.tz$\n(^|\\.)google\\.co\\.ug$\n(^|\\.)google\\.co\\.uk$\n(^|\\.)google\\.co\\.uz$\n(^|\\.)google\\.co\\.ve$\n(^|\\.)google\\.co\\.vi$\n(^|\\.)google\\.co\\.za$\n(^|\\.)google\\.co\\.zm$\n(^|\\.)google\\.co\\.zw$\n(^|\\.)google\\.cv$\n(^|\\.)google\\.cz$\n(^|\\.)google\\.de$\n(^|\\.)google\\.dev$\n(^|\\.)google\\.dj$\n(^|\\.)google\\.dk$\n(^|\\.)google\\.dm$\n(^|\\.)googledomains\\.com$\n(^|\\.)googledrive\\.com$\n(^|\\.)google\\.dz$\n(^|\\.)googleearth\\.com$\n(^|\\.)google\\.ee$\n(^|\\.)google\\.es$\n(^|\\.)google\\.fi$\n(^|\\.)google\\.fm$\n(^|\\.)google\\.fr$\n(^|\\.)google\\.ga$\n(^|\\.)google\\.ge$\n(^|\\.)google\\.gg$\n(^|\\.)google\\.gl$\n(^|\\.)google\\.gm$\n(^|\\.)google\\.gp$\n(^|\\.)google\\.gr$\n(^|\\.)googlegroups\\.com$\n(^|\\.)google\\.gy$\n(^|\\.)google\\.hn$\n(^|\\.)googlehosted\\.com$\n(^|\\.)google\\.hr$\n(^|\\.)google\\.ht$\n(^|\\.)google\\.hu$\n(^|\\.)googleideas\\.com$\n(^|\\.)google\\.ie$\n(^|\\.)google\\.im$\n(^|\\.)googleinsidesearch\\.com$\n(^|\\.)google\\.iq$\n(^|\\.)google\\.is$\n(^|\\.)google\\.it$\n(^|\\.)google\\.je$\n(^|\\.)google\\.jo$\n(^|\\.)google\\.kg$\n(^|\\.)google\\.ki$\n(^|\\.)google\\.kz$\n(^|\\.)google\\.la$\n(^|\\.)googlelabs\\.com$\n(^|\\.)google\\.li$\n(^|\\.)google\\.lk$\n(^|\\.)google\\.lt$\n(^|\\.)google\\.lu$\n(^|\\.)google\\.lv$\n(^|\\.)googlemail\\.com$\n(^|\\.)googlemashups\\.com$\n(^|\\.)google\\.md$\n(^|\\.)google\\.me$\n(^|\\.)google\\.mg$\n(^|\\.)google\\.mk$\n(^|\\.)google\\.ml$\n(^|\\.)google\\.mn$\n(^|\\.)google\\.ms$\n(^|\\.)google\\.mu$\n(^|\\.)google\\.mv$\n(^|\\.)google\\.mw$\n(^|\\.)google\\.ne$\n(^|\\.)google\\.nl$\n(^|\\.)google\\.no$\n(^|\\.)google\\.nr$\n(^|\\.)google\\.nu$\n(^|\\.)googlepagecreator\\.com$\n(^|\\.)google\\.pl$\n(^|\\.)googleplay\\.com$\n(^|\\.)googleplus\\.com$\n(^|\\.)google\\.pn$\n(^|\\.)google\\.ps$\n(^|\\.)google\\.pt$\n(^|\\.)google\\.ro$\n(^|\\.)google\\.rs$\n(^|\\.)google\\.ru$\n(^|\\.)google\\.rw$\n(^|\\.)google\\.sc$\n(^|\\.)googlescholar\\.com$\n(^|\\.)google\\.se$\n(^|\\.)google\\.sh$\n(^|\\.)google\\.si$\n(^|\\.)googlesile\\.com$\n(^|\\.)google\\.sk$\n(^|\\.)google\\.sm$\n(^|\\.)google\\.sn$\n(^|\\.)google\\.so$\n(^|\\.)googlesource\\.com$\n(^|\\.)google\\.sr$\n(^|\\.)google\\.st$\n(^|\\.)google\\.td$\n(^|\\.)google\\.tg$\n(^|\\.)google\\.tk$\n(^|\\.)google\\.tl$\n(^|\\.)google\\.tm$\n(^|\\.)google\\.tn$\n(^|\\.)google\\.to$\n(^|\\.)google\\.tt$\n(^|\\.)googleusercontent\\.com$\n(^|\\.)google\\.vg$\n(^|\\.)googlevideo\\.com$\n(^|\\.)google\\.vu$\n(^|\\.)googleweblight\\.com$\n(^|\\.)google\\.ws$\n(^|\\.)googlezip\\.net$\n(^|\\.)gopetition\\.com$\n(^|\\.)go-pki\\.com$\n(^|\\.)goproxing\\.net$\n(^|\\.)goregrish\\.com$\n(^|\\.)gospelherald\\.com$\n(^|\\.)gotdns\\.ch$\n(^|\\.)got-game\\.org$\n(^|\\.)gotgeeks\\.com$\n(^|\\.)gotrusted\\.com$\n(^|\\.)gotw\\.ca$\n(^|\\.)gov\\.taipei$\n(^|\\.)gov\\.tw$\n(^|\\.)g-queen\\.com$\n(^|\\.)gr8domain\\.biz$\n(^|\\.)gr8name\\.biz$\n(^|\\.)grammaly\\.com$\n(^|\\.)grandtrial\\.org$\n(^|\\.)grangorz\\.org$\n(^|\\.)graphis\\.ne\\.jp$\n(^|\\.)graphql\\.org$\n(^|\\.)greasespot\\.net$\n(^|\\.)greatfire\\.org$\n(^|\\.)greatfire\\.us7\\.list-manage\\.com$\n(^|\\.)greatfirewall\\.biz$\n(^|\\.)great-firewall\\.com$\n(^|\\.)greatfirewallofchina\\.net$\n(^|\\.)greatfirewallofchina\\.org$\n(^|\\.)great-roc\\.org$\n(^|\\.)greatroc\\.org$\n(^|\\.)greatroc\\.tw$\n(^|\\.)greatzhonghua\\.org$\n(^|\\.)greenfieldbookstore\\.com\\.hk$\n(^|\\.)greenparty\\.org\\.tw$\n(^|\\.)greenpeace\\.com\\.tw$\n(^|\\.)greenpeace\\.org$\n(^|\\.)greenreadings\\.com$\n(^|\\.)greenvpn\\.net$\n(^|\\.)greenvpn\\.org$\n(^|\\.)grotty-monday\\.com$\n(^|\\.)groups\\.google\\.cn$\n(^|\\.)grow\\.google$\n(^|\\.)gs-discuss\\.com$\n(^|\\.)gsp\\.target\\.com$\n(^|\\.)gstatic\\.com$\n(^|\\.)gtricks\\.com$\n(^|\\.)gts-vpn\\.com$\n(^|\\.)guaguass\\.com$\n(^|\\.)guaguass\\.org$\n(^|\\.)guancha\\.org$\n(^|\\.)guaneryu\\.com$\n(^|\\.)guangming\\.com\\.my$\n(^|\\.)guangnianvpn\\.com$\n(^|\\.)guardster\\.com$\n(^|\\.)gu-chu-sum\\.org$\n(^|\\.)guishan\\.org$\n(^|\\.)gumroad\\.com$\n(^|\\.)gunsamerica\\.com$\n(^|\\.)gunsandammo\\.com$\n(^|\\.)gun-world\\.net$\n(^|\\.)guo\\.media$\n(^|\\.)guruonline\\.hk$\n(^|\\.)gutteruncensored\\.com$\n(^|\\.)gvlib\\.com$\n(^|\\.)gvm\\.com\\.tw$\n(^|\\.)gvt0\\.com$\n(^|\\.)gvt1\\.com$\n(^|\\.)gvt3\\.com$\n(^|\\.)gwtproject\\.org$\n(^|\\.)gyalwarinpoche\\.com$\n(^|\\.)gyatsostudio\\.com$\n(^|\\.)gzm\\.tv$\n(^|\\.)gzone-anime\\.info$\n(^|\\.)h1n1china\\.org$\n(^|\\.)h528\\.com$\n(^|\\.)h5dm\\.com$\n(^|\\.)h5galgame\\.me$\n(^|\\.)hacg\\.club$\n(^|\\.)hacg\\.in$\n(^|\\.)hacg\\.li$\n(^|\\.)hacg\\.me$\n(^|\\.)hacg\\.red$\n(^|\\.)hacken\\.cc$\n(^|\\.)hacker\\.org$\n(^|\\.)hackthatphone\\.net$\n(^|\\.)hahaxixi\\.github\\.io$\n(^|\\.)hahlo\\.com$\n(^|\\.)hakkatv\\.org\\.tw$\n(^|\\.)handcraftedsoftware\\.org$\n(^|\\.)hanime\\.tv$\n(^|\\.)hanunyi\\.com$\n(^|\\.)haoel\\.github\\.io$\n(^|\\.)hao\\.news$\n(^|\\.)happy-vpn\\.com$\n(^|\\.)haproxy\\.org$\n(^|\\.)hardsextube\\.com$\n(^|\\.)harunyahya\\.com$\n(^|\\.)hautelookcdn\\.com$\n(^|\\.)hautelook\\.com$\n(^|\\.)have8\\.com$\n(^|\\.)hbg\\.com$\n(^|\\.)hbo\\.com$\n(^|\\.)h-china\\.org$\n(^|\\.)hclips\\.com$\n(^|\\.)hdlt\\.me$\n(^|\\.)hd\\.stheadline\\.com$\n(^|\\.)hdtvb\\.net$\n(^|\\.)hdzog\\.com$\n(^|\\.)heartyit\\.com$\n(^|\\.)heavy-r\\.com$\n(^|\\.)hecaitou\\.net$\n(^|\\.)hechaji\\.com$\n(^|\\.)hec\\.su$\n(^|\\.)heeact\\.edu\\.tw$\n(^|\\.)hegre-art\\.com$\n(^|\\.)heix\\.pp\\.ru$\n(^|\\.)helloandroid\\.com$\n(^|\\.)helloqueer\\.com$\n(^|\\.)helloss\\.pw$\n(^|\\.)hellotxt\\.com$\n(^|\\.)hellouk\\.org$\n(^|\\.)helpeachpeople\\.com$\n(^|\\.)helplinfen\\.com$\n(^|\\.)help\\.linksalpha\\.com$\n(^|\\.)helpster\\.de$\n(^|\\.)helpzhuling\\.org$\n(^|\\.)hentai\\.to$\n(^|\\.)hentaitube\\.tv$\n(^|\\.)hentaivideoworld\\.com$\n(^|\\.)heqinglian\\.net$\n(^|\\.)heungkongdiscuss\\.com$\n(^|\\.)hexieshe\\.com$\n(^|\\.)hexieshe\\.xyz$\n(^|\\.)hexxeh\\.net$\n(^|\\.)heyzo\\.com$\n(^|\\.)hgseav\\.com$\n(^|\\.)hhdcb3office\\.org$\n(^|\\.)hhthesakyatrizin\\.org$\n(^|\\.)hidden-advent\\.org$\n(^|\\.)hidecloud\\.com$\n(^|\\.)hidein\\.net$\n(^|\\.)hideipvpn\\.com$\n(^|\\.)hideman\\.net$\n(^|\\.)hide\\.me$\n(^|\\.)hideme\\.nl$\n(^|\\.)hidemyass\\.com$\n(^|\\.)hidemycomp\\.com$\n(^|\\.)hidemy\\.name$\n(^|\\.)higfw\\.com$\n(^|\\.)highpeakspureearth\\.com$\n(^|\\.)highrockmedia\\.com$\n(^|\\.)hihiforum\\.com$\n(^|\\.)hihistory\\.net$\n(^|\\.)hiitch\\.com$\n(^|\\.)hikinggfw\\.org$\n(^|\\.)hilive\\.tv$\n(^|\\.)himalayan-foundation\\.org$\n(^|\\.)himalayanglacier\\.com$\n(^|\\.)himemix\\.com$\n(^|\\.)himemix\\.net$\n(^|\\.)hi-on\\.org\\.tw$\n(^|\\.)hitbtc\\.com$\n(^|\\.)hitomi\\.la$\n(^|\\.)hiwifi\\.com$\n(^|\\.)hizb-ut-tahrir\\.info$\n(^|\\.)hizb-ut-tahrir\\.org$\n(^|\\.)hizbuttahrir\\.org$\n(^|\\.)hjclub\\.info$\n(^|\\.)hk01\\.com$\n(^|\\.)hk32168\\.com$\n(^|\\.)hka8964\\.wordpress\\.com$\n(^|\\.)hkacg\\.com$\n(^|\\.)hkacg\\.net$\n(^|\\.)hkanews\\.wordpress\\.com$\n(^|\\.)hkatvnews\\.com$\n(^|\\.)hkbc\\.net$\n(^|\\.)hkbf\\.org$\n(^|\\.)hkbookcity\\.com$\n(^|\\.)hkchurch\\.org$\n(^|\\.)hkci\\.org\\.hk$\n(^|\\.)hkcmi\\.edu$\n(^|\\.)hkcnews\\.com$\n(^|\\.)hkcoc\\.com$\n(^|\\.)hkcoc\\.weather\\.com\\.hk$\n(^|\\.)hkdailynews\\.com\\.hk$\n(^|\\.)hkday\\.net$\n(^|\\.)hkdf\\.org$\n(^|\\.)hkej\\.com$\n(^|\\.)hkepc\\.com$\n(^|\\.)hkfaa\\.com$\n(^|\\.)hkfreezone\\.com$\n(^|\\.)hk\\.frienddy\\.com$\n(^|\\.)hkfront\\.org$\n(^|\\.)hkgalden\\.com$\n(^|\\.)hk\\.geocities\\.com$\n(^|\\.)hkgolden\\.com$\n(^|\\.)hk\\.gradconnection\\.com$\n(^|\\.)hkgreenradio\\.org$\n(^|\\.)hk\\.hao123img\\.com$\n(^|\\.)hkheadline\\.com$\n(^|\\.)hkhkhk\\.com$\n(^|\\.)hkhrc\\.org\\.hk$\n(^|\\.)hkhrm\\.org\\.hk$\n(^|\\.)hkip\\.org\\.uk$\n(^|\\.)hkjc\\.com$\n(^|\\.)hk\\.jiepang\\.com$\n(^|\\.)hkjp\\.org$\n(^|\\.)hk\\.knowledge\\.yahoo\\.com$\n(^|\\.)hklft\\.com$\n(^|\\.)hklts\\.org\\.hk$\n(^|\\.)hk\\.myblog\\.yahoo\\.com$\n(^|\\.)hk\\.news\\.yahoo\\.com$\n(^|\\.)hkptu\\.org$\n(^|\\.)hk-pub\\.com$\n(^|\\.)hk\\.rd\\.yahoo\\.com$\n(^|\\.)hkreporter\\.com$\n(^|\\.)hkreporter\\.loved\\.hk$\n(^|\\.)hk\\.search\\.yahoo\\.com$\n(^|\\.)hkupop\\.hku\\.hk$\n(^|\\.)hkusu\\.net$\n(^|\\.)hk\\.video\\.news\\.yahoo\\.com$\n(^|\\.)hkvwet\\.com$\n(^|\\.)hkwcc\\.org\\.hk$\n(^|\\.)hk\\.yahoo\\.com$\n(^|\\.)hkzone\\.org$\n(^|\\.)h-moe\\.com$\n(^|\\.)hmonghot\\.com$\n(^|\\.)hmv\\.co\\.jp$\n(^|\\.)hmvdigital\\.ca$\n(^|\\.)hmvdigital\\.com$\n(^|\\.)hnjhj\\.com$\n(^|\\.)hnntube\\.com$\n(^|\\.)hola\\.com$\n(^|\\.)hola\\.org$\n(^|\\.)holymountaincn\\.com$\n(^|\\.)holyspiritspeaks\\.org$\n(^|\\.)homedepot\\.com$\n(^|\\.)homeperversion\\.com$\n(^|\\.)homeservershow\\.com$\n(^|\\.)home\\.sina\\.com$\n(^|\\.)home\\.so-net\\.net\\.tw$\n(^|\\.)hongkongfp\\.com$\n(^|\\.)hongmeimei\\.com$\n(^|\\.)hongzhi\\.li$\n(^|\\.)hootsuite\\.com$\n(^|\\.)hoovers\\.com$\n(^|\\.)hopedialogue\\.org$\n(^|\\.)hopto\\.org$\n(^|\\.)hornygamer\\.com$\n(^|\\.)hornytrip\\.com$\n(^|\\.)hotav\\.tv$\n(^|\\.)hotels\\.cn$\n(^|\\.)hotfrog\\.com\\.tw$\n(^|\\.)hotgoo\\.com$\n(^|\\.)hotpornshow\\.com$\n(^|\\.)hotpot\\.hk$\n(^|\\.)hotshame\\.com$\n(^|\\.)hotspotshield\\.com$\n(^|\\.)hotvpn\\.com$\n(^|\\.)hougaige\\.com$\n(^|\\.)howtoforge\\.com$\n(^|\\.)hoxx\\.com$\n(^|\\.)hpa\\.gov\\.tw$\n(^|\\.)hqcdp\\.org$\n(^|\\.)hqjapanesesex\\.com$\n(^|\\.)hqmovies\\.com$\n(^|\\.)hqsbnet\\.wordpress\\.com$\n(^|\\.)hqsbonline\\.wordpress\\.com$\n(^|\\.)hrcchina\\.org$\n(^|\\.)hrcir\\.com$\n(^|\\.)hrea\\.org$\n(^|\\.)hrichina\\.org$\n(^|\\.)hrtsea\\.com$\n(^|\\.)hrweb\\.org$\n(^|\\.)hrw\\.org$\n(^|\\.)hsjp\\.net$\n(^|\\.)hsselite\\.com$\n(^|\\.)hstern\\.net$\n(^|\\.)hst\\.net\\.tw$\n(^|\\.)hstt\\.net$\n(^|\\.)htkou\\.net$\n(^|\\.)htl\\.li$\n(^|\\.)ht\\.ly$\n(^|\\.)html5rocks\\.com$\n(^|\\.)https443\\.net$\n(^|\\.)https443\\.org$\n(^|\\.)huaglad\\.com$\n(^|\\.)huanghuagang\\.org$\n(^|\\.)huangyiyu\\.com$\n(^|\\.)huaren4us\\.com$\n(^|\\.)huaren\\.us$\n(^|\\.)huashangnews\\.com$\n(^|\\.)huaxiabao\\.org$\n(^|\\.)huaxia-news\\.com$\n(^|\\.)huaxin\\.ph$\n(^|\\.)hua-yue\\.net$\n(^|\\.)huayuworld\\.org$\n(^|\\.)hudatoriq\\.web\\.id$\n(^|\\.)hudson\\.org$\n(^|\\.)huffingtonpost\\.com$\n(^|\\.)hugoroy\\.eu$\n(^|\\.)huhaitai\\.com$\n(^|\\.)huhamhire\\.com$\n(^|\\.)huiyi\\.in$\n(^|\\.)hulkshare\\.com$\n(^|\\.)hulu\\.com$\n(^|\\.)huluim\\.com$\n(^|\\.)humanrightsbriefing\\.org$\n(^|\\.)hungerstrikeforaids\\.org$\n(^|\\.)hung-ya\\.com$\n(^|\\.)huobi\\.com$\n(^|\\.)huobi\\.pro$\n(^|\\.)huobipro\\.com$\n(^|\\.)huping\\.net$\n(^|\\.)hurgokbayrak\\.com$\n(^|\\.)hurriyet\\.com\\.tr$\n(^|\\.)hustlercash\\.com$\n(^|\\.)hut2\\.ru$\n(^|\\.)hutianyi\\.net$\n(^|\\.)hutong9\\.net$\n(^|\\.)huyandex\\.com$\n(^|\\.)hwadzan\\.tw$\n(^|\\.)hwayue\\.org\\.tw$\n(^|\\.)hwinfo\\.com$\n(^|\\.)hxwk\\.org$\n(^|\\.)hxwq\\.org$\n(^|\\.)hybrid-analysis\\.com$\n(^|\\.)hyperrate\\.com$\n(^|\\.)i1\\.hk$\n(^|\\.)i2p2\\.de$\n(^|\\.)i2runner\\.com$\n(^|\\.)i818hk\\.com$\n(^|\\.)iam\\.soy$\n(^|\\.)iamtopone\\.com$\n(^|\\.)iask\\.bz$\n(^|\\.)iask\\.ca$\n(^|\\.)iav19\\.com$\n(^|\\.)ibiblio\\.org$\n(^|\\.)iblist\\.com$\n(^|\\.)iblogserv-f\\.net$\n(^|\\.)ibros\\.org$\n(^|\\.)ibvpn\\.com$\n(^|\\.)i-cable\\.com$\n(^|\\.)icams\\.com$\n(^|\\.)ice\\.audionow\\.com$\n(^|\\.)icij\\.org$\n(^|\\.)icl-fi\\.org$\n(^|\\.)icoco\\.com$\n(^|\\.)iconpaper\\.org$\n(^|\\.)icu-project\\.org$\n(^|\\.)iddddg\\.com$\n(^|\\.)idemocracy\\.asia$\n(^|\\.)identi\\.ca$\n(^|\\.)id\\.hao123\\.com$\n(^|\\.)id\\.heroku\\.com$\n(^|\\.)idiomconnection\\.com$\n(^|\\.)idouga\\.com$\n(^|\\.)idreamx\\.com$\n(^|\\.)idv\\.tw$\n(^|\\.)ieasy5\\.com$\n(^|\\.)ied2k\\.net$\n(^|\\.)ienergy1\\.com$\n(^|\\.)ifan\\.cz\\.cc$\n(^|\\.)ifanqiang\\.com$\n(^|\\.)ifcss\\.org$\n(^|\\.)ifjc\\.org$\n(^|\\.)ifreewares\\.com$\n(^|\\.)if\\.ttt$\n(^|\\.)ift\\.tt$\n(^|\\.)igcd\\.net$\n(^|\\.)igfw\\.net$\n(^|\\.)igfw\\.tech$\n(^|\\.)igmg\\.de$\n(^|\\.)ignitedetroit\\.net$\n(^|\\.)igoogle\\.com$\n(^|\\.)igotmail\\.com\\.tw$\n(^|\\.)igvita\\.com$\n(^|\\.)ihakka\\.net$\n(^|\\.)ihao\\.org$\n(^|\\.)iicns\\.com$\n(^|\\.)iipdigital\\.usembassy\\.gov$\n(^|\\.)ikstar\\.com$\n(^|\\.)ikwb\\.com$\n(^|\\.)i\\.lithium\\.com$\n(^|\\.)illusionfactory\\.com$\n(^|\\.)ilove80\\.be$\n(^|\\.)ilovelongtoes\\.com$\n(^|\\.)im88\\.tw$\n(^|\\.)imageab\\.com$\n(^|\\.)imagefap\\.com$\n(^|\\.)imageflea\\.com$\n(^|\\.)images\\.comico\\.tw$\n(^|\\.)images-gaytube\\.com$\n(^|\\.)imageshack\\.us$\n(^|\\.)imagevenue\\.com$\n(^|\\.)imagezilla\\.net$\n(^|\\.)imb\\.org$\n(^|\\.)imdb\\.com$\n(^|\\.)imgchili\\.net$\n(^|\\.)img\\.dlsite\\.jp$\n(^|\\.)img\\.ly$\n(^|\\.)imgmega\\.com$\n(^|\\.)imgur\\.com$\n(^|\\.)imkev\\.com$\n(^|\\.)imlive\\.com$\n(^|\\.)immigration\\.gov\\.tw$\n(^|\\.)immoral\\.jp$\n(^|\\.)impact\\.org\\.au$\n(^|\\.)impp\\.mn$\n(^|\\.)im\\.tv$\n(^|\\.)in99\\.org$\n(^|\\.)incapdns\\.net$\n(^|\\.)incloak\\.com$\n(^|\\.)incredibox\\.fr$\n(^|\\.)indiandefensenews\\.in$\n(^|\\.)indiemerch\\.com$\n(^|\\.)in-disguise\\.com$\n(^|\\.)info-graf\\.fr$\n(^|\\.)initiativesforchina\\.org$\n(^|\\.)inkui\\.com$\n(^|\\.)inmediahk\\.net$\n(^|\\.)innermongolia\\.org$\n(^|\\.)inote\\.tw$\n(^|\\.)insecam\\.org$\n(^|\\.)insidevoa\\.com$\n(^|\\.)instagram\\.com$\n(^|\\.)instanthq\\.com$\n(^|\\.)institut-tibetain\\.org$\n(^|\\.)international-news\\.newsmagazine\\.asia$\n(^|\\.)internetdefenseleague\\.org$\n(^|\\.)internetfreedom\\.org$\n(^|\\.)internet\\.org$\n(^|\\.)internetpopculture\\.com$\n(^|\\.)inthenameofconfuciusmovie\\.com$\n(^|\\.)investigating\\.wordpress\\.com$\n(^|\\.)inxian\\.com$\n(^|\\.)iownyour\\.biz$\n(^|\\.)iownyour\\.org$\n(^|\\.)ipalter\\.com$\n(^|\\.)i-part\\.com\\.tw$\n(^|\\.)ipfire\\.org$\n(^|\\.)ipfs\\.io$\n(^|\\.)iphone4hongkong\\.com$\n(^|\\.)iphonehacks\\.com$\n(^|\\.)iphonetaiwan\\.org$\n(^|\\.)iphonix\\.fr$\n(^|\\.)ipicture\\.ru$\n(^|\\.)ipjetable\\.net$\n(^|\\.)ipobar\\.com$\n(^|\\.)ipoock\\.com$\n(^|\\.)iportal\\.me$\n(^|\\.)ippotv\\.com$\n(^|\\.)ipredator\\.se$\n(^|\\.)iptvbin\\.com$\n(^|\\.)iptv\\.com\\.tw$\n(^|\\.)ipvanish\\.com$\n(^|\\.)iredmail\\.org$\n(^|\\.)ironbigfools\\.compython\\.net$\n(^|\\.)ironpython\\.net$\n(^|\\.)ironsocket\\.com$\n(^|\\.)isaacmao\\.com$\n(^|\\.)is-a-hunter\\.com$\n(^|\\.)isasecret\\.com$\n(^|\\.)i-scmp\\.com$\n(^|\\.)isc\\.sans\\.edu$\n(^|\\.)is\\.gd$\n(^|\\.)isgreat\\.org$\n(^|\\.)islahhaber\\.net$\n(^|\\.)islamawareness\\.net$\n(^|\\.)islamhouse\\.com$\n(^|\\.)islamicity\\.com$\n(^|\\.)islamicpluralism\\.org$\n(^|\\.)islam\\.org\\.hk$\n(^|\\.)islamtoday\\.net$\n(^|\\.)ismaelan\\.com$\n(^|\\.)ismalltits\\.com$\n(^|\\.)ismprofessional\\.net$\n(^|\\.)isohunt\\.com$\n(^|\\.)israbox\\.com$\n(^|\\.)issuu\\.com$\n(^|\\.)istars\\.co\\.nz$\n(^|\\.)istiqlalhewer\\.com$\n(^|\\.)istockphoto\\.com$\n(^|\\.)isunaffairs\\.com$\n(^|\\.)isuntv\\.com$\n(^|\\.)itaboo\\.info$\n(^|\\.)itaiwan\\.gov\\.tw$\n(^|\\.)italiatibet\\.org$\n(^|\\.)itasoftware\\.com$\n(^|\\.)itemdb\\.com$\n(^|\\.)ithelp\\.ithome\\.com\\.tw$\n(^|\\.)itsaol\\.com$\n(^|\\.)its\\.caltech\\.edu$\n(^|\\.)itshidden\\.com$\n(^|\\.)itsky\\.it$\n(^|\\.)itweet\\.net$\n(^|\\.)iu45\\.com$\n(^|\\.)iuhrdf\\.org$\n(^|\\.)iuksky\\.com$\n(^|\\.)ivacy\\.com$\n(^|\\.)iverycd\\.com$\n(^|\\.)ivpn\\.net$\n(^|\\.)ixquick\\.com$\n(^|\\.)ixxx\\.com$\n(^|\\.)iyouport\\.com$\n(^|\\.)izaobao\\.us$\n(^|\\.)izlesem\\.org$\n(^|\\.)izles\\.net$\n(^|\\.)jamaat\\.org$\n(^|\\.)jamyangnorbu\\.com$\n(^|\\.)jandyx\\.com$\n(^|\\.)janwongphoto\\.com$\n(^|\\.)japanfirst\\.asianfreeforum\\.com$\n(^|\\.)japantimes\\.co\\.jp$\n(^|\\.)japan-whores\\.com$\n(^|\\.)jav101\\.com$\n(^|\\.)jav2be\\.com$\n(^|\\.)jav68\\.tv$\n(^|\\.)javakiba\\.org$\n(^|\\.)javbus\\.com$\n(^|\\.)jav\\.com$\n(^|\\.)javfor\\.me$\n(^|\\.)javhd\\.com$\n(^|\\.)javhip\\.com$\n(^|\\.)javhub\\.net$\n(^|\\.)javhuge\\.com$\n(^|\\.)javlibrary\\.com$\n(^|\\.)javmobile\\.net$\n(^|\\.)javmoo\\.com$\n(^|\\.)javmoo\\.xyz$\n(^|\\.)javseen\\.com$\n(^|\\.)javtag\\.com$\n(^|\\.)javzoo\\.com$\n(^|\\.)ja\\.wikipedia\\.org$\n(^|\\.)jbtalks\\.cc$\n(^|\\.)jbtalks\\.com$\n(^|\\.)jbtalks\\.my$\n(^|\\.)jcpenney\\.com$\n(^|\\.)jdwsy\\.com$\n(^|\\.)jeanyim\\.com$\n(^|\\.)jetos\\.com$\n(^|\\.)jex\\.com$\n(^|\\.)jfqu36\\.club$\n(^|\\.)jfqu37\\.xyz$\n(^|\\.)jgoodies\\.com$\n(^|\\.)jiangweiping\\.com$\n(^|\\.)jiaoyou8\\.com$\n(^|\\.)jiehua\\.cz$\n(^|\\.)jieshibaobao\\.com$\n(^|\\.)jigglegifs\\.com$\n(^|\\.)jigong1024\\.com$\n(^|\\.)jihadintel\\.meforum\\.org$\n(^|\\.)jihadology\\.net$\n(^|\\.)jiji\\.com$\n(^|\\.)jims\\.net$\n(^|\\.)jinbushe\\.org$\n(^|\\.)jingpin\\.org$\n(^|\\.)jingsim\\.org$\n(^|\\.)jinpianwang\\.com$\n(^|\\.)jinroukong\\.com$\n(^|\\.)jintian\\.net$\n(^|\\.)jinx\\.com$\n(^|\\.)jitouch\\.com$\n(^|\\.)jizzthis\\.com$\n(^|\\.)jjgirls\\.com$\n(^|\\.)jkb\\.cc$\n(^|\\.)jkforum\\.net$\n(^|\\.)jkub\\.com$\n(^|\\.)jma\\.go\\.jp$\n(^|\\.)j\\.mp$\n(^|\\.)jmscult\\.com$\n(^|\\.)joachims\\.org$\n(^|\\.)jobnewera\\.wordpress\\.com$\n(^|\\.)jobso\\.tv$\n(^|\\.)joinmastodon\\.org$\n(^|\\.)journalchretien\\.net$\n(^|\\.)journalofdemocracy\\.org$\n(^|\\.)joymiihub\\.com$\n(^|\\.)joyourself\\.com$\n(^|\\.)jp\\.hao123\\.com$\n(^|\\.)jpl\\.nasa\\.gov$\n(^|\\.)jpopforum\\.net$\n(^|\\.)jtvnw\\.net$\n(^|\\.)jubushoushen\\.com$\n(^|\\.)juhuaren\\.com$\n(^|\\.)jukujo-club\\.com$\n(^|\\.)juliepost\\.com$\n(^|\\.)juliereyc\\.com$\n(^|\\.)junauza\\.com$\n(^|\\.)june4commemoration\\.org$\n(^|\\.)junefourth-20\\.net$\n(^|\\.)jungleheart\\.com$\n(^|\\.)juoaa\\.com$\n(^|\\.)justdied\\.com$\n(^|\\.)justfreevpn\\.com$\n(^|\\.)justicefortenzin\\.org$\n(^|\\.)justpaste\\.it$\n(^|\\.)justtristan\\.com$\n(^|\\.)juyuange\\.org$\n(^|\\.)juziyue\\.com$\n(^|\\.)jwmusic\\.org$\n(^|\\.)jyxf\\.net$\n(^|\\.)kagyumonlam\\.org$\n(^|\\.)kagyunews\\.com\\.hk$\n(^|\\.)kagyuoffice\\.org$\n(^|\\.)kagyuoffice\\.org\\.tw$\n(^|\\.)kagyu\\.org$\n(^|\\.)kagyu\\.org\\.za$\n(^|\\.)kaiyuan\\.de$\n(^|\\.)kakao\\.com$\n(^|\\.)kalachakralugano\\.org$\n(^|\\.)kankan\\.today$\n(^|\\.)kannewyork\\.com$\n(^|\\.)kanshifang\\.com$\n(^|\\.)kantie\\.org$\n(^|\\.)kanzhongguo\\.com$\n(^|\\.)kanzhongguo\\.eu$\n(^|\\.)kaotic\\.com$\n(^|\\.)karayou\\.com$\n(^|\\.)karkhung\\.com$\n(^|\\.)karmapa\\.org$\n(^|\\.)karmapa-teachings\\.org$\n(^|\\.)ka-wai\\.com$\n(^|\\.)kawaiikawaii\\.jp$\n(^|\\.)kawase\\.com$\n(^|\\.)kba-tx\\.org$\n(^|\\.)kb\\.monitorware\\.com$\n(^|\\.)kcoolonline\\.com$\n(^|\\.)k-doujin\\.net$\n(^|\\.)kebrum\\.com$\n(^|\\.)kechara\\.com$\n(^|\\.)keepandshare\\.com$\n(^|\\.)keezmovies\\.com$\n(^|\\.)kendatire\\.com$\n(^|\\.)kendincos\\.net$\n(^|\\.)kenengba\\.com$\n(^|\\.)keontech\\.net$\n(^|\\.)kepard\\.com$\n(^|\\.)kex\\.com$\n(^|\\.)keycdn\\.com$\n(^|\\.)khabdha\\.org$\n(^|\\.)khatrimaza\\.org$\n(^|\\.)khmusic\\.com\\.tw$\n(^|\\.)kichiku-doujinko\\.com$\n(^|\\.)kik\\.com$\n(^|\\.)killwall\\.com$\n(^|\\.)kindleren\\.com$\n(^|\\.)kineox\\.free\\.fr$\n(^|\\.)kingdomsalvation\\.org$\n(^|\\.)kinghost\\.com$\n(^|\\.)kingstone\\.com\\.tw$\n(^|\\.)kink\\.com$\n(^|\\.)kinmen\\.org\\.tw$\n(^|\\.)kinmen\\.travel$\n(^|\\.)kinokuniya\\.com$\n(^|\\.)kir\\.jp$\n(^|\\.)kissbbao\\.cn$\n(^|\\.)kiwi\\.kz$\n(^|\\.)kkbox\\.com$\n(^|\\.)kknews\\.cc$\n(^|\\.)kk-whys\\.co\\.jp$\n(^|\\.)kmuh\\.org\\.tw$\n(^|\\.)knowledgerush\\.com$\n(^|\\.)kobobooks\\.com$\n(^|\\.)kobo\\.com$\n(^|\\.)kodingen\\.com$\n(^|\\.)kompozer\\.net$\n(^|\\.)konachan\\.com$\n(^|\\.)kone\\.com$\n(^|\\.)koolsolutions\\.com$\n(^|\\.)koornk\\.com$\n(^|\\.)koranmandarin\\.com$\n(^|\\.)korenan2\\.com$\n(^|\\.)ksdl\\.org$\n(^|\\.)ksnews\\.com\\.tw$\n(^|\\.)kspcoin\\.com$\n(^|\\.)ktzhk\\.com$\n(^|\\.)kucoin\\.com$\n(^|\\.)kui\\.name$\n(^|\\.)kun\\.im$\n(^|\\.)kurashsultan\\.com$\n(^|\\.)kurtmunger\\.com$\n(^|\\.)kusocity\\.com$\n(^|\\.)kwcg\\.ca$\n(^|\\.)kwongwah\\.com\\.my$\n(^|\\.)kxsw\\.life$\n(^|\\.)kyofun\\.com$\n(^|\\.)kyohk\\.net$\n(^|\\.)kyoyue\\.com$\n(^|\\.)kyzyhello\\.com$\n(^|\\.)kzeng\\.info$\n(^|\\.)labiennale\\.org$\n(^|\\.)ladbrokes\\.com$\n(^|\\.)la-forum\\.org$\n(^|\\.)lagranepoca\\.com$\n(^|\\.)lalulalu\\.com$\n(^|\\.)lama\\.com\\.tw$\n(^|\\.)lamayeshe\\.com$\n(^|\\.)lamnia\\.co\\.uk$\n(^|\\.)lamrim\\.com$\n(^|\\.)lanterncn\\.cn$\n(^|\\.)lantosfoundation\\.org$\n(^|\\.)laod\\.cn$\n(^|\\.)laogai\\.org$\n(^|\\.)laomiu\\.com$\n(^|\\.)laoyang\\.info$\n(^|\\.)laptoplockdown\\.com$\n(^|\\.)laqingdan\\.net$\n(^|\\.)larsgeorge\\.com$\n(^|\\.)lastcombat\\.com$\n(^|\\.)lastfm\\.es$\n(^|\\.)latelinenews\\.com$\n(^|\\.)latibet\\.org$\n(^|\\.)lbank\\.info$\n(^|\\.)ld\\.hao123img\\.com$\n(^|\\.)leafyvpn\\.net$\n(^|\\.)lecloud\\.net$\n(^|\\.)leeao\\.com\\.cn$\n(^|\\.)lefora\\.com$\n(^|\\.)left21\\.hk$\n(^|\\.)legalporno\\.com$\n(^|\\.)legaltech\\.law\\.com$\n(^|\\.)legsjapan\\.com$\n(^|\\.)leirentv\\.ca$\n(^|\\.)leisurecafe\\.ca$\n(^|\\.)leisurepro\\.com$\n(^|\\.)lematin\\.ch$\n(^|\\.)lemonde\\.fr$\n(^|\\.)lenwhite\\.com$\n(^|\\.)lerosua\\.org$\n(^|\\.)lers\\.google$\n(^|\\.)lesoir\\.be$\n(^|\\.)letou\\.com$\n(^|\\.)letscorp\\.net$\n(^|\\.)le-vpn\\.com$\n(^|\\.)lflink\\.com$\n(^|\\.)lflinkup\\.com$\n(^|\\.)lflinkup\\.net$\n(^|\\.)lflinkup\\.org$\n(^|\\.)lhakar\\.org$\n(^|\\.)lhasocialwork\\.org$\n(^|\\.)liangyou\\.net$\n(^|\\.)liangzhichuanmei\\.com$\n(^|\\.)lianyue\\.net$\n(^|\\.)liaowangxizang\\.net$\n(^|\\.)liberal\\.org\\.hk$\n(^|\\.)libertytimes\\.com\\.tw$\n(^|\\.)library\\.usc\\.cuhk\\.edu\\.hk$\n(^|\\.)lidecheng\\.com$\n(^|\\.)lifemiles\\.com$\n(^|\\.)lighten\\.org\\.tw$\n(^|\\.)lighti\\.me$\n(^|\\.)lightnovel\\.cn$\n(^|\\.)lightyearvpn\\.com$\n(^|\\.)lihkg\\.com$\n(^|\\.)like\\.com$\n(^|\\.)limiao\\.net$\n(^|\\.)line-apps\\.com$\n(^|\\.)linear-abematv\\.akamaized\\.net$\n(^|\\.)line\\.me$\n(^|\\.)line\\.naver\\.jp$\n(^|\\.)line-scdn\\.net$\n(^|\\.)linglingfa\\.com$\n(^|\\.)lingvodics\\.com$\n(^|\\.)linkideo\\.com$\n(^|\\.)link-o-rama\\.com$\n(^|\\.)linkuswell\\.com$\n(^|\\.)linux\\.org\\.hk$\n(^|\\.)linuxtoy\\.org$\n(^|\\.)lionsroar\\.com$\n(^|\\.)lipuman\\.com$\n(^|\\.)liquidvpn\\.com$\n(^|\\.)listentoyoutube\\.com$\n(^|\\.)listorious\\.com$\n(^|\\.)lists\\.w3\\.org$\n(^|\\.)liudejun\\.com$\n(^|\\.)liuhanyu\\.com$\n(^|\\.)liujianshu\\.com$\n(^|\\.)liuxiaobo\\.net$\n(^|\\.)liu-xiaobo\\.org$\n(^|\\.)liuxiaotong\\.com$\n(^|\\.)livecoin\\.net$\n(^|\\.)livedoor\\.jp$\n(^|\\.)liveleak\\.com$\n(^|\\.)livestation\\.com$\n(^|\\.)livestream\\.com$\n(^|\\.)livevideo\\.com$\n(^|\\.)livingonline\\.us$\n(^|\\.)livingstream\\.com$\n(^|\\.)liwangyang\\.com$\n(^|\\.)lizhizhuangbi\\.com$\n(^|\\.)lkcn\\.net$\n(^|\\.)llss\\.me$\n(^|\\.)load\\.to$\n(^|\\.)lobsangwangyal\\.com$\n(^|\\.)localbitcoins\\.com$\n(^|\\.)localdomain\\.ws$\n(^|\\.)localpresshk\\.com$\n(^|\\.)lockestek\\.com$\n(^|\\.)logbot\\.net$\n(^|\\.)login\\.target\\.com$\n(^|\\.)logiqx\\.com$\n(^|\\.)londonchinese\\.ca$\n(^|\\.)longhair\\.hk$\n(^|\\.)longmusic\\.com$\n(^|\\.)longtermly\\.net$\n(^|\\.)longtoes\\.com$\n(^|\\.)lookpic\\.com$\n(^|\\.)looktoronto\\.com$\n(^|\\.)lotsawahouse\\.org$\n(^|\\.)lotuslight\\.org\\.hk$\n(^|\\.)lotuslight\\.org\\.tw$\n(^|\\.)lovetvshow\\.com$\n(^|\\.)lpsg\\.com$\n(^|\\.)lrfz\\.com$\n(^|\\.)lrip\\.org$\n(^|\\.)lsd\\.org\\.hk$\n(^|\\.)lsforum\\.net$\n(^|\\.)lsmchinese\\.org$\n(^|\\.)lsmkorean\\.org$\n(^|\\.)lsm\\.org$\n(^|\\.)lsmradio\\.com$\n(^|\\.)lsmwebcast\\.com$\n(^|\\.)lsxszzg\\.com$\n(^|\\.)ltn\\.com\\.tw$\n(^|\\.)luke54\\.com$\n(^|\\.)luke54\\.org$\n(^|\\.)lupm\\.org$\n(^|\\.)lushstories\\.com$\n(^|\\.)luxebc\\.com$\n(^|\\.)lvhai\\.org$\n(^|\\.)lvv2\\.com$\n(^|\\.)lyfhk\\.net$\n(^|\\.)lzmtnews\\.org$\n(^|\\.)macgamestore\\.com$\n(^|\\.)macrovpn\\.com$\n(^|\\.)macts\\.com\\.tw$\n(^|\\.)mad-ar\\.ch$\n(^|\\.)madewithcode\\.com$\n(^|\\.)madonna-av\\.com$\n(^|\\.)madrau\\.com$\n(^|\\.)madthumbs\\.com$\n(^|\\.)magazines\\.sina\\.com\\.tw$\n(^|\\.)magic-net\\.info$\n(^|\\.)mahabodhi\\.org$\n(^|\\.)ma\\.hao123\\.com$\n(^|\\.)maiio\\.net$\n(^|\\.)mail-archive\\.com$\n(^|\\.)maildns\\.xyz$\n(^|\\.)maiplus\\.com$\n(^|\\.)maizhong\\.org$\n(^|\\.)makemymood\\.com$\n(^|\\.)makkahnewspaper\\.com$\n(^|\\.)makzhou\\.warehouse333\\.com$\n(^|\\.)malaysiakini\\.com$\n(^|\\.)mamingzhe\\.com$\n(^|\\.)manchukuo\\.net$\n(^|\\.)mangafox\\.com$\n(^|\\.)mangafox\\.me$\n(^|\\.)maniash\\.com$\n(^|\\.)manicur4ik\\.ru$\n(^|\\.)mansion\\.com$\n(^|\\.)mansionpoker\\.com$\n(^|\\.)manta\\.com$\n(^|\\.)maplew\\.com$\n(^|\\.)marc\\.info$\n(^|\\.)marguerite\\.su$\n(^|\\.)martau\\.com$\n(^|\\.)martincartoons\\.com$\n(^|\\.)martsangkagyuofficial\\.org$\n(^|\\.)maruta\\.be$\n(^|\\.)marxist\\.com$\n(^|\\.)marxist\\.net$\n(^|\\.)marxists\\.org$\n(^|\\.)mash\\.to$\n(^|\\.)maskedip\\.com$\n(^|\\.)mastodon\\.cloud$\n(^|\\.)mastodon\\.host$\n(^|\\.)mastodon\\.social$\n(^|\\.)matainja\\.com$\n(^|\\.)material\\.io$\n(^|\\.)mathable\\.io$\n(^|\\.)mathiew-badimon\\.com$\n(^|\\.)matome-plus\\.com$\n(^|\\.)matome-plus\\.net$\n(^|\\.)matsushimakaede\\.com$\n(^|\\.)matters\\.news$\n(^|\\.)mattwilcox\\.net$\n(^|\\.)maturejp\\.com$\n(^|\\.)maxing\\.jp$\n(^|\\.)mayimayi\\.com$\n(^|\\.)mcadforums\\.com$\n(^|\\.)mcaf\\.ee$\n(^|\\.)mcfog\\.com$\n(^|\\.)mcreasite\\.com$\n(^|\\.)md-t\\.org$\n(^|\\.)meansys\\.com$\n(^|\\.)mediachinese\\.com$\n(^|\\.)mediafire\\.com$\n(^|\\.)mediafreakcity\\.com$\n(^|\\.)media\\.nu\\.nl$\n(^|\\.)media\\.org\\.hk$\n(^|\\.)medium\\.com$\n(^|\\.)meetav\\.com$\n(^|\\.)meetup\\.com$\n(^|\\.)mefeedia\\.com$\n(^|\\.)mefound\\.com$\n(^|\\.)mega\\.nz$\n(^|\\.)megaproxy\\.com$\n(^|\\.)megarotic\\.com$\n(^|\\.)megavideo\\.com$\n(^|\\.)megurineluka\\.com$\n(^|\\.)meirixiaochao\\.com$\n(^|\\.)meltoday\\.com$\n(^|\\.)me\\.me$\n(^|\\.)memehk\\.com$\n(^|\\.)meme\\.yahoo\\.com$\n(^|\\.)memorybbs\\.com$\n(^|\\.)memrijttm\\.org$\n(^|\\.)memri\\.org$\n(^|\\.)mercatox\\.com$\n(^|\\.)mercyprophet\\.org$\n(^|\\.)mergersandinquisitions\\.org$\n(^|\\.)meridian-trust\\.org$\n(^|\\.)meripet\\.biz$\n(^|\\.)meripet\\.com$\n(^|\\.)merit-times\\.com\\.tw$\n(^|\\.)meshrep\\.com$\n(^|\\.)mesotw\\.com$\n(^|\\.)messenger\\.com$\n(^|\\.)metacafe\\.com$\n(^|\\.)metart\\.com$\n(^|\\.)metarthunter\\.com$\n(^|\\.)meteorshowersonline\\.com$\n(^|\\.)metrohk\\.com\\.hk$\n(^|\\.)metrolife\\.ca$\n(^|\\.)metroradio\\.com\\.hk$\n(^|\\.)meyou\\.jp$\n(^|\\.)me\\.youthwant\\.com\\.tw$\n(^|\\.)meyul\\.com$\n(^|\\.)mfxmedia\\.com$\n(^|\\.)mgoon\\.com$\n(^|\\.)mgstage\\.com$\n(^|\\.)mh4u\\.org$\n(^|\\.)m\\.hkgalden\\.com$\n(^|\\.)mhradio\\.org$\n(^|\\.)michaelanti\\.com$\n(^|\\.)michaelmarketl\\.com$\n(^|\\.)microvpn\\.com$\n(^|\\.)middle-way\\.net$\n(^|\\.)mihk\\.hk$\n(^|\\.)mihr\\.com$\n(^|\\.)mihua\\.org$\n(^|\\.)mike\\.cz\\.cc$\n(^|\\.)mikesoltys\\.com$\n(^|\\.)milph\\.net$\n(^|\\.)milsurps\\.com$\n(^|\\.)mimiai\\.net$\n(^|\\.)mimivip\\.com$\n(^|\\.)mimivv\\.com$\n(^|\\.)mindrolling\\.org$\n(^|\\.)minghui-a\\.org$\n(^|\\.)minghui-b\\.org$\n(^|\\.)minghui\\.org$\n(^|\\.)minghui\\.or\\.kr$\n(^|\\.)minghui-school\\.org$\n(^|\\.)minghuiyw\\.wordpress\\.com$\n(^|\\.)mingjinglishi\\.com$\n(^|\\.)mingjingnews\\.com$\n(^|\\.)mingjingtimes\\.com$\n(^|\\.)mingpaocanada\\.com$\n(^|\\.)mingpao\\.com$\n(^|\\.)mingpaomonthly\\.com$\n(^|\\.)mingpaonews\\.com$\n(^|\\.)mingpaony\\.com$\n(^|\\.)mingpaosf\\.com$\n(^|\\.)mingpaotor\\.com$\n(^|\\.)mingpaovan\\.com$\n(^|\\.)mingshengbao\\.com$\n(^|\\.)minhhue\\.net$\n(^|\\.)miniforum\\.org$\n(^|\\.)ministrybooks\\.org$\n(^|\\.)minzhuhua\\.net$\n(^|\\.)minzhuzhanxian\\.com$\n(^|\\.)minzhuzhongguo\\.org$\n(^|\\.)miroguide\\.com$\n(^|\\.)mirrorbooks\\.com$\n(^|\\.)mist\\.vip$\n(^|\\.)mitao\\.com\\.tw$\n(^|\\.)mitbbsau\\.com$\n(^|\\.)mitbbs\\.com$\n(^|\\.)mixero\\.com$\n(^|\\.)mixpod\\.com$\n(^|\\.)mixx\\.com$\n(^|\\.)mizzmona\\.com$\n(^|\\.)mjib\\.gov\\.tw$\n(^|\\.)mjlsh\\.usc\\.cuhk\\.edu\\.hk$\n(^|\\.)mk5000\\.com$\n(^|\\.)mlcool\\.com$\n(^|\\.)mlzs\\.work$\n(^|\\.)mmaaxx\\.com$\n(^|\\.)mm-cg\\.com$\n(^|\\.)m\\.me$\n(^|\\.)mmmca\\.com$\n(^|\\.)mnewstv\\.com$\n(^|\\.)mobatek\\.net$\n(^|\\.)mobile01\\.com$\n(^|\\.)mobileways\\.de$\n(^|\\.)mobypicture\\.com$\n(^|\\.)moby\\.to$\n(^|\\.)moeaic\\.gov\\.tw$\n(^|\\.)moeerolibrary\\.com$\n(^|\\.)mofa\\.gov\\.tw$\n(^|\\.)mofaxiehui\\.com$\n(^|\\.)mofos\\.com$\n(^|\\.)mog\\.com$\n(^|\\.)mohu\\.club$\n(^|\\.)mohu\\.ml$\n(^|\\.)mojim\\.com$\n(^|\\.)mol\\.gov\\.tw$\n(^|\\.)molihua\\.org$\n(^|\\.)mondex\\.org$\n(^|\\.)moneyhome\\.biz$\n(^|\\.)money-link\\.com\\.tw$\n(^|\\.)mo\\.nightlife141\\.com$\n(^|\\.)monitorchina\\.org$\n(^|\\.)monster\\.com$\n(^|\\.)moodyz\\.com$\n(^|\\.)moonbbs\\.com$\n(^|\\.)moonbingo\\.com$\n(^|\\.)morningsun\\.org$\n(^|\\.)moroneta\\.com$\n(^|\\.)mos\\.ru$\n(^|\\.)motherless\\.com$\n(^|\\.)motiyun\\.com$\n(^|\\.)motor4ik\\.ru$\n(^|\\.)mousebreaker\\.com$\n(^|\\.)movements\\.org$\n(^|\\.)moviefap\\.com$\n(^|\\.)mp3buscador\\.com$\n(^|\\.)mp3ye\\.eu$\n(^|\\.)mpettis\\.com$\n(^|\\.)mpfinance\\.com$\n(^|\\.)mpinews\\.com$\n(^|\\.)m\\.plixi\\.com$\n(^|\\.)mponline\\.hk$\n(^|\\.)mqxd\\.org$\n(^|\\.)mrbasic\\.com$\n(^|\\.)mrbonus\\.com$\n(^|\\.)mrface\\.com$\n(^|\\.)mrslove\\.com$\n(^|\\.)mrtweet\\.com$\n(^|\\.)msa-it\\.org$\n(^|\\.)msguancha\\.com$\n(^|\\.)msha\\.gov$\n(^|\\.)m\\.slandr\\.net$\n(^|\\.)mswe1\\.org$\n(^|\\.)m-team\\.cc$\n(^|\\.)mthruf\\.com$\n(^|\\.)mtw\\.tl$\n(^|\\.)muchosucko\\.com$\n(^|\\.)mullvad\\.net$\n(^|\\.)multiply\\.com$\n(^|\\.)multiproxy\\.org$\n(^|\\.)multiupload\\.com$\n(^|\\.)mummysgold\\.com$\n(^|\\.)murmur\\.tw$\n(^|\\.)musicade\\.net$\n(^|\\.)muslimvideo\\.com$\n(^|\\.)muzi\\.com$\n(^|\\.)muzi\\.net$\n(^|\\.)muzu\\.tv$\n(^|\\.)mvdis\\.gov\\.tw$\n(^|\\.)mvg\\.jp$\n(^|\\.)mx981\\.com$\n(^|\\.)mx\\.hao123\\.com$\n(^|\\.)my03\\.com$\n(^|\\.)myactimes\\.com$\n(^|\\.)myanniu\\.com$\n(^|\\.)myaudiocast\\.com$\n(^|\\.)myav\\.com\\.tw$\n(^|\\.)mybbs\\.us$\n(^|\\.)mybet\\.com$\n(^|\\.)myca168\\.com$\n(^|\\.)mycanadanow\\.com$\n(^|\\.)mychinamyhome\\.com$\n(^|\\.)mychinanet\\.com$\n(^|\\.)mychinanews\\.com$\n(^|\\.)mychinese\\.news$\n(^|\\.)mycnnews\\.com$\n(^|\\.)mycould\\.com$\n(^|\\.)mydad\\.info$\n(^|\\.)myddns\\.com$\n(^|\\.)myeasytv\\.com$\n(^|\\.)myeclipseide\\.com$\n(^|\\.)my-formosa\\.com$\n(^|\\.)myforum\\.com\\.hk$\n(^|\\.)myforum\\.com\\.uk$\n(^|\\.)myfreecams\\.com$\n(^|\\.)myfreepaysite\\.com$\n(^|\\.)myfreshnet\\.com$\n(^|\\.)myftp\\.info$\n(^|\\.)myftp\\.name$\n(^|\\.)myiphide\\.com$\n(^|\\.)mykomica\\.org$\n(^|\\.)mylftv\\.com$\n(^|\\.)my\\.mail\\.ru$\n(^|\\.)mymediarom\\.com$\n(^|\\.)mymoe\\.moe$\n(^|\\.)mymom\\.info$\n(^|\\.)mymusic\\.net\\.tw$\n(^|\\.)mynetav\\.net$\n(^|\\.)mynetav\\.org$\n(^|\\.)mynumber\\.org$\n(^|\\.)my\\.opera\\.com$\n(^|\\.)myparagliding\\.com$\n(^|\\.)my\\.pcloud\\.com$\n(^|\\.)mypicture\\.info$\n(^|\\.)mypop3\\.net$\n(^|\\.)mypop3\\.org$\n(^|\\.)mypopescu\\.com$\n(^|\\.)my-private-network\\.co\\.uk$\n(^|\\.)my-proxy\\.com$\n(^|\\.)myradio\\.hk$\n(^|\\.)myreadingmanga\\.info$\n(^|\\.)mysecondarydns\\.com$\n(^|\\.)myshare\\.url\\.com\\.tw$\n(^|\\.)mysinablog\\.com$\n(^|\\.)mysite\\.verizon\\.net$\n(^|\\.)myspacecdn\\.com$\n(^|\\.)myspace\\.com$\n(^|\\.)mytalkbox\\.com$\n(^|\\.)mytizi\\.com$\n(^|\\.)mywww\\.biz$\n(^|\\.)myz\\.info$\n(^|\\.)naacoalition\\.org$\n(^|\\.)naitik\\.net$\n(^|\\.)nakido\\.com$\n(^|\\.)nakuz\\.com$\n(^|\\.)nalandabodhi\\.org$\n(^|\\.)nalandawest\\.org$\n(^|\\.)namgyalmonastery\\.org$\n(^|\\.)namgyal\\.org$\n(^|\\.)namsisi\\.com$\n(^|\\.)nanyang\\.com$\n(^|\\.)nanyangpost\\.com$\n(^|\\.)nanzao\\.com$\n(^|\\.)naol\\.ca$\n(^|\\.)naol\\.cc$\n(^|\\.)nat\\.gov\\.tw$\n(^|\\.)national-lottery\\.co\\.uk$\n(^|\\.)nationsonline\\.org$\n(^|\\.)nationwide\\.com$\n(^|\\.)nat\\.moe$\n(^|\\.)naughtyamerica\\.com$\n(^|\\.)navyfamily\\.navy\\.mil$\n(^|\\.)navyreserve\\.navy\\.mil$\n(^|\\.)naweeklytimes\\.com$\n(^|\\.)nbtvpn\\.com$\n(^|\\.)nccwatch\\.org\\.tw$\n(^|\\.)nch\\.com\\.tw$\n(^|\\.)ncn\\.org$\n(^|\\.)nde\\.de$\n(^|\\.)ndr\\.de$\n(^|\\.)ned\\.org$\n(^|\\.)nekoslovakia\\.net$\n(^|\\.)nemesis2\\.qx\\.net$\n(^|\\.)neo-miracle\\.com$\n(^|\\.)nepusoku\\.com$\n(^|\\.)netbirds\\.com$\n(^|\\.)netcolony\\.com$\n(^|\\.)net-fits\\.pro$\n(^|\\.)netflix\\.com$\n(^|\\.)netme\\.cc$\n(^|\\.)netsneak\\.com$\n(^|\\.)network54\\.com$\n(^|\\.)networkedblogs\\.com$\n(^|\\.)networktunnel\\.net$\n(^|\\.)neverforget8964\\.org$\n(^|\\.)new-3lunch\\.net$\n(^|\\.)new96\\.ca$\n(^|\\.)new-akiba\\.com$\n(^|\\.)newcenturymc\\.com$\n(^|\\.)newcenturynews\\.com$\n(^|\\.)newchen\\.com$\n(^|\\.)newgrounds\\.com$\n(^|\\.)newipnow\\.com$\n(^|\\.)newlandmagazine\\.com\\.au$\n(^|\\.)newnews\\.ca$\n(^|\\.)news100\\.com\\.tw$\n(^|\\.)newsancai\\.com$\n(^|\\.)newschinacomment\\.org$\n(^|\\.)newscn\\.org$\n(^|\\.)news\\.cnyes\\.com$\n(^|\\.)newsdetox\\.ca$\n(^|\\.)newsdh\\.com$\n(^|\\.)news\\.hk\\.msn\\.com$\n(^|\\.)news\\.hkpeanut\\.com$\n(^|\\.)news\\.msn\\.com\\.tw$\n(^|\\.)news\\.nationalgeographic\\.com$\n(^|\\.)news\\.now\\.com$\n(^|\\.)news\\.omy\\.sg$\n(^|\\.)newspeak\\.cc$\n(^|\\.)news\\.seehua\\.com$\n(^|\\.)news\\.sina\\.com\\.hk$\n(^|\\.)news\\.sina\\.com\\.tw$\n(^|\\.)news\\.sinchew\\.com\\.my$\n(^|\\.)news\\.singtao\\.ca$\n(^|\\.)newstamago\\.com$\n(^|\\.)newstapa\\.org$\n(^|\\.)newstarnet\\.com$\n(^|\\.)news\\.tvb\\.com$\n(^|\\.)news\\.tvbs\\.com\\.tw$\n(^|\\.)news\\.yahoo\\.com$\n(^|\\.)newtaiwan\\.com\\.tw$\n(^|\\.)newtalk\\.tw$\n(^|\\.)newyorktimes\\.com$\n(^|\\.)nexon\\.com$\n(^|\\.)next11\\.co\\.jp$\n(^|\\.)nextmag\\.com\\.tw$\n(^|\\.)nextmedia\\.com$\n(^|\\.)nexton-net\\.jp$\n(^|\\.)nexttv\\.com\\.tw$\n(^|\\.)nf\\.id\\.au$\n(^|\\.)nfjtyd\\.com$\n(^|\\.)nflxext\\.com$\n(^|\\.)nflximg\\.com$\n(^|\\.)nflximg\\.net$\n(^|\\.)nflxso\\.net$\n(^|\\.)nflxvideo\\.net$\n(^|\\.)nga\\.mil$\n(^|\\.)ngensis\\.com$\n(^|\\.)nhentai\\.net$\n(^|\\.)nhi\\.gov\\.tw$\n(^|\\.)nhk-ondemand\\.jp$\n(^|\\.)nic\\.cz\\.cc$\n(^|\\.)nic\\.google$\n(^|\\.)nic\\.gov$\n(^|\\.)nicovideo\\.jp$\n(^|\\.)nighost\\.org$\n(^|\\.)nikkei\\.com$\n(^|\\.)ninecommentaries\\.com$\n(^|\\.)ninjacloak\\.com$\n(^|\\.)ninjaproxy\\.ninja$\n(^|\\.)nintendium\\.com$\n(^|\\.)ninth\\.biz$\n(^|\\.)niu\\.moe$\n(^|\\.)niusnews\\.com$\n(^|\\.)njactb\\.org$\n(^|\\.)njuice\\.com$\n(^|\\.)nko\\.navy\\.mil$\n(^|\\.)nlfreevpn\\.com$\n(^|\\.)nobelprize\\.org$\n(^|\\.)nobel\\.se$\n(^|\\.)nobodycanstop\\.us$\n(^|\\.)nofile\\.io$\n(^|\\.)no-ip\\.org$\n(^|\\.)nokogiri\\.org$\n(^|\\.)nokola\\.com$\n(^|\\.)noodlevpn\\.com$\n(^|\\.)norbulingka\\.org$\n(^|\\.)nordstrom\\.com$\n(^|\\.)nordstromimage\\.com$\n(^|\\.)nordstromrack\\.com$\n(^|\\.)nordvpn\\.com$\n(^|\\.)notify\\.dropboxapi\\.com$\n(^|\\.)nottinghampost\\.com$\n(^|\\.)novelasia\\.com$\n(^|\\.)now\\.com$\n(^|\\.)now\\.im$\n(^|\\.)nownews\\.com$\n(^|\\.)nowtorrents\\.com$\n(^|\\.)noypf\\.com$\n(^|\\.)npa\\.go\\.jp$\n(^|\\.)npa\\.gov\\.tw$\n(^|\\.)npnt\\.me$\n(^|\\.)npsboost\\.com$\n(^|\\.)nps\\.gov$\n(^|\\.)nradio\\.me$\n(^|\\.)nrk\\.no$\n(^|\\.)ns01\\.biz$\n(^|\\.)ns01\\.info$\n(^|\\.)ns01\\.us$\n(^|\\.)ns02\\.biz$\n(^|\\.)ns02\\.info$\n(^|\\.)ns02\\.us$\n(^|\\.)ns1\\.name$\n(^|\\.)ns2\\.name$\n(^|\\.)ns3\\.name$\n(^|\\.)nsc\\.gov\\.tw$\n(^|\\.)ntbk\\.gov\\.tw$\n(^|\\.)ntbna\\.gov\\.tw$\n(^|\\.)ntbt\\.gov\\.tw$\n(^|\\.)ntd\\.tv$\n(^|\\.)ntdtv\\.ca$\n(^|\\.)ntdtv\\.co\\.kr$\n(^|\\.)ntdtv\\.com$\n(^|\\.)ntdtv\\.cz$\n(^|\\.)ntdtvla\\.com$\n(^|\\.)ntdtv\\.org$\n(^|\\.)ntdtv\\.ru$\n(^|\\.)ntrfun\\.com$\n(^|\\.)ntsna\\.gov\\.tw$\n(^|\\.)nubiles\\.net$\n(^|\\.)nuexpo\\.com$\n(^|\\.)nukistream\\.com$\n(^|\\.)nurgo-software\\.com$\n(^|\\.)nusatrip\\.com$\n(^|\\.)nutaku\\.net$\n(^|\\.)nuuvem\\.com$\n(^|\\.)nuvid\\.com$\n(^|\\.)nuzcom\\.com$\n(^|\\.)nvdst\\.com$\n(^|\\.)nvquan\\.org$\n(^|\\.)nvtongzhisheng\\.org$\n(^|\\.)nwtca\\.org$\n(^|\\.)nyaa\\.eu$\n(^|\\.)nyaa\\.si$\n(^|\\.)nydus\\.ca$\n(^|\\.)nylon-angel\\.com$\n(^|\\.)nylonstockingsonline\\.com$\n(^|\\.)ny\\.stgloballink\\.com$\n(^|\\.)nytchina\\.com$\n(^|\\.)nytcn\\.me$\n(^|\\.)nytco\\.com$\n(^|\\.)nyt\\.com$\n(^|\\.)nytimes\\.com$\n(^|\\.)nytimes\\.map\\.fastly\\.net$\n(^|\\.)nytimg\\.com$\n(^|\\.)nyti\\.ms$\n(^|\\.)nytstyle\\.com$\n(^|\\.)ny\\.visiontimes\\.com$\n(^|\\.)nzchinese\\.com$\n(^|\\.)nzchinese\\.net\\.nz$\n(^|\\.)observechina\\.net$\n(^|\\.)obutu\\.com$\n(^|\\.)ocaspro\\.com$\n(^|\\.)occupytiananmen\\.com$\n(^|\\.)oclp\\.hk$\n(^|\\.)ocreampies\\.com$\n(^|\\.)ocry\\.com$\n(^|\\.)october-review\\.org$\n(^|\\.)oculuscdn\\.com$\n(^|\\.)oculus\\.com$\n(^|\\.)oex\\.com$\n(^|\\.)offbeatchina\\.com$\n(^|\\.)officeoftibet\\.com$\n(^|\\.)ofile\\.org$\n(^|\\.)ogaoga\\.org$\n(^|\\.)ogate\\.org$\n(^|\\.)oikos\\.com\\.tw$\n(^|\\.)oiktv\\.com$\n(^|\\.)oizoblog\\.com$\n(^|\\.)okayfreedom\\.com$\n(^|\\.)okex\\.com$\n(^|\\.)okk\\.tw$\n(^|\\.)ok\\.ru$\n(^|\\.)old-cat\\.net$\n(^|\\.)old\\.honeynet\\.org$\n(^|\\.)old\\.nabble\\.com$\n(^|\\.)olumpo\\.com$\n(^|\\.)olympicwatch\\.org$\n(^|\\.)omgili\\.com$\n(^|\\.)omni7\\.jp$\n(^|\\.)omnitalk\\.com$\n(^|\\.)omnitalk\\.org$\n(^|\\.)on2\\.com$\n(^|\\.)onapp\\.com$\n(^|\\.)on\\.cc$\n(^|\\.)onedrive\\.live\\.com$\n(^|\\.)onedumb\\.com$\n(^|\\.)onejav\\.com$\n(^|\\.)onion\\.city$\n(^|\\.)onlinecha\\.com$\n(^|\\.)online\\.recoveryversion\\.org$\n(^|\\.)onlineyoutube\\.com$\n(^|\\.)onlytweets\\.com$\n(^|\\.)onmoon\\.com$\n(^|\\.)onmoon\\.net$\n(^|\\.)onmypc\\.biz$\n(^|\\.)onmypc\\.info$\n(^|\\.)onmypc\\.net$\n(^|\\.)onmypc\\.org$\n(^|\\.)onmypc\\.us$\n(^|\\.)onthehunt\\.com$\n(^|\\.)ontrac\\.com$\n(^|\\.)oopsforum\\.com$\n(^|\\.)openallweb\\.com$\n(^|\\.)open\\.com\\.hk$\n(^|\\.)opendemocracy\\.net$\n(^|\\.)opendn\\.xyz$\n(^|\\.)openervpn\\.in$\n(^|\\.)openid\\.net$\n(^|\\.)openleaks\\.org$\n(^|\\.)openvpn\\.net$\n(^|\\.)openvpn\\.org$\n(^|\\.)openwebster\\.com$\n(^|\\.)openwrt\\.org\\.cn$\n(^|\\.)opml\\.radiotime\\.com$\n(^|\\.)opus-gaming\\.com$\n(^|\\.)organcare\\.org\\.tw$\n(^|\\.)organharvestinvestigation\\.net$\n(^|\\.)organiccrap\\.com$\n(^|\\.)orgasm\\.com$\n(^|\\.)orgfree\\.com$\n(^|\\.)orientaldaily\\.com\\.my$\n(^|\\.)orient-doll\\.com$\n(^|\\.)orn\\.jp$\n(^|\\.)orzistic\\.org$\n(^|\\.)osfoora\\.com$\n(^|\\.)otcbtc\\.com$\n(^|\\.)otnd\\.org$\n(^|\\.)otto\\.de$\n(^|\\.)otzo\\.com$\n(^|\\.)ourdearamy\\.com$\n(^|\\.)ourhobby\\.com$\n(^|\\.)oursogo\\.com$\n(^|\\.)oursteps\\.com\\.au$\n(^|\\.)oursweb\\.net$\n(^|\\.)ourtv\\.hk$\n(^|\\.)overplay\\.net$\n(^|\\.)oversea\\.istarshine\\.com$\n(^|\\.)owl\\.li$\n(^|\\.)ow\\.ly$\n(^|\\.)oyax\\.com$\n(^|\\.)oyghan\\.com$\n(^|\\.)ozchinese\\.com$\n(^|\\.)ozvoice\\.org$\n(^|\\.)ozxw\\.com$\n(^|\\.)ozyoyo\\.com$\n(^|\\.)pachosting\\.com$\n(^|\\.)pacificpoker\\.com$\n(^|\\.)packages\\.debian\\.org$\n(^|\\.)packetix\\.net$\n(^|\\.)pacopacomama\\.com$\n(^|\\.)padmanet\\.com$\n(^|\\.)page2rss\\.com$\n(^|\\.)page\\.bid\\.yahoo\\.com$\n(^|\\.)pagodabox\\.com$\n(^|\\.)palacemoon\\.com$\n(^|\\.)paldengyal\\.com$\n(^|\\.)paljorpublications\\.com$\n(^|\\.)paltalk\\.com$\n(^|\\.)panamapapers\\.sueddeutsche\\.de$\n(^|\\.)pandapow\\.co$\n(^|\\.)pandapow\\.net$\n(^|\\.)pandavpn-jp\\.com$\n(^|\\.)pandora\\.com$\n(^|\\.)pandora\\.tv$\n(^|\\.)panluan\\.net$\n(^|\\.)panoramio\\.com$\n(^|\\.)pao-pao\\.net$\n(^|\\.)paperb\\.us$\n(^|\\.)paper\\.li$\n(^|\\.)paradisehill\\.cc$\n(^|\\.)paradisepoker\\.com$\n(^|\\.)parkansky\\.com$\n(^|\\.)partycasino\\.com$\n(^|\\.)partypoker\\.com$\n(^|\\.)passion\\.com$\n(^|\\.)passiontimes\\.hk$\n(^|\\.)pastebin\\.com$\n(^|\\.)paste\\.ee$\n(^|\\.)pastie\\.org$\n(^|\\.)pbs\\.org$\n(^|\\.)pbwiki\\.com$\n(^|\\.)pbworks\\.com$\n(^|\\.)pbxes\\.com$\n(^|\\.)pbxes\\.org$\n(^|\\.)pcanywhere\\.net$\n(^|\\.)pcc\\.gov\\.tw$\n(^|\\.)pcdvd\\.com\\.tw$\n(^|\\.)pchome\\.com\\.tw$\n(^|\\.)pcij\\.org$\n(^|\\.)pcstore\\.com\\.tw$\n(^|\\.)pct\\.org\\.tw$\n(^|\\.)pdetails\\.com$\n(^|\\.)pdproxy\\.com$\n(^|\\.)pds\\.nasa\\.gov$\n(^|\\.)peace\\.ca$\n(^|\\.)peacefire\\.org$\n(^|\\.)peacehall\\.com$\n(^|\\.)pearlher\\.org$\n(^|\\.)peeasian\\.com$\n(^|\\.)pekingduck\\.org$\n(^|\\.)pemulihan\\.or\\.id$\n(^|\\.)penchinese\\.com$\n(^|\\.)penchinese\\.net$\n(^|\\.)pengyulong\\.com$\n(^|\\.)pen\\.io$\n(^|\\.)penisbot\\.com$\n(^|\\.)penthouse\\.com$\n(^|\\.)pentoy\\.hk$\n(^|\\.)peoplebookcafe\\.com$\n(^|\\.)peoplenews\\.tw$\n(^|\\.)peopo\\.org$\n(^|\\.)percy\\.in$\n(^|\\.)perfectgirls\\.net$\n(^|\\.)perfectvpn\\.net$\n(^|\\.)periscope\\.tv$\n(^|\\.)persecutionblog\\.com$\n(^|\\.)persiankitty\\.com$\n(^|\\.)pfd\\.org\\.hk$\n(^|\\.)phapluan\\.org$\n(^|\\.)phayul\\.com$\n(^|\\.)philborges\\.com$\n(^|\\.)philly\\.com$\n(^|\\.)phmsociety\\.org$\n(^|\\.)phncdn\\.com$\n(^|\\.)phobos\\.apple\\.com$\n(^|\\.)phosphation13\\.rssing\\.com$\n(^|\\.)photodharma\\.net$\n(^|\\.)photofocus\\.com$\n(^|\\.)phuquocservices\\.com$\n(^|\\.)picacomiccn\\.com$\n(^|\\.)picacomic\\.com$\n(^|\\.)picasaweb\\.com$\n(^|\\.)picidae\\.net$\n(^|\\.)picturedip\\.com$\n(^|\\.)picturesocial\\.com$\n(^|\\.)pictures\\.playboy\\.com$\n(^|\\.)pimg\\.tw$\n(^|\\.)pin6\\.com$\n(^|\\.)pin-cong\\.com$\n(^|\\.)pincong\\.rocks$\n(^|\\.)ping\\.fm$\n(^|\\.)pinimg\\.com$\n(^|\\.)pinkrod\\.com$\n(^|\\.)pinoy-n\\.com$\n(^|\\.)pinterest\\.at$\n(^|\\.)pinterest\\.ca$\n(^|\\.)pinterest\\.co\\.kr$\n(^|\\.)pinterest\\.com$\n(^|\\.)pinterest\\.co\\.uk$\n(^|\\.)pinterest\\.de$\n(^|\\.)pinterest\\.dk$\n(^|\\.)pinterest\\.fr$\n(^|\\.)pinterest\\.jp$\n(^|\\.)pinterest\\.nl$\n(^|\\.)pinterest\\.se$\n(^|\\.)pioneer-worker\\.forums-free\\.com$\n(^|\\.)pipii\\.tv$\n(^|\\.)piposay\\.com$\n(^|\\.)piraattilahti\\.org$\n(^|\\.)piring\\.com$\n(^|\\.)pixelqi\\.com$\n(^|\\.)pixiv\\.net$\n(^|\\.)pixnet\\.net$\n(^|\\.)pk\\.com$\n(^|\\.)pki\\.goog$\n(^|\\.)placemix\\.com$\n(^|\\.)playboy\\.com$\n(^|\\.)playboyplus\\.com$\n(^|\\.)player\\.fm$\n(^|\\.)playno1\\.com$\n(^|\\.)playpcesor\\.com$\n(^|\\.)plays\\.com\\.tw$\n(^|\\.)plm\\.org\\.hk$\n(^|\\.)plunder\\.com$\n(^|\\.)plurk\\.com$\n(^|\\.)plus28\\.com$\n(^|\\.)plusbb\\.com$\n(^|\\.)plus\\.codes$\n(^|\\.)pmatehunter\\.com$\n(^|\\.)pmates\\.com$\n(^|\\.)po2b\\.com$\n(^|\\.)pobieramy\\.top$\n(^|\\.)podictionary\\.com$\n(^|\\.)pokerstars\\.com$\n(^|\\.)pokerstars\\.net$\n(^|\\.)politicalchina\\.org$\n(^|\\.)politicalconsultation\\.org$\n(^|\\.)politiscales\\.net$\n(^|\\.)poloniex\\.com$\n(^|\\.)polymerhk\\.com$\n(^|\\.)polymer-project\\.org$\n(^|\\.)popo\\.tw$\n(^|\\.)popvote\\.hk$\n(^|\\.)popyard\\.com$\n(^|\\.)popyard\\.org$\n(^|\\.)porn2\\.com$\n(^|\\.)porn5\\.com$\n(^|\\.)pornbase\\.org$\n(^|\\.)porn\\.com$\n(^|\\.)pornerbros\\.com$\n(^|\\.)pornhd\\.com$\n(^|\\.)pornhost\\.com$\n(^|\\.)pornhub\\.com$\n(^|\\.)pornhubdeutsch\\.net$\n(^|\\.)pornmm\\.net$\n(^|\\.)pornoxo\\.com$\n(^|\\.)pornrapidshare\\.com$\n(^|\\.)pornsharing\\.com$\n(^|\\.)pornsocket\\.com$\n(^|\\.)pornstarclub\\.com$\n(^|\\.)porntube\\.com$\n(^|\\.)porntubenews\\.com$\n(^|\\.)porntvblog\\.com$\n(^|\\.)pornvisit\\.com$\n(^|\\.)port25\\.biz$\n(^|\\.)portablevpn\\.nl$\n(^|\\.)poskotanews\\.com$\n(^|\\.)post01\\.com$\n(^|\\.)post76\\.com$\n(^|\\.)post852\\.com$\n(^|\\.)postadult\\.com$\n(^|\\.)postimg\\.org$\n(^|\\.)potato\\.im$\n(^|\\.)potvpn\\.com$\n(^|\\.)powerapple\\.com$\n(^|\\.)power\\.com$\n(^|\\.)powercx\\.com$\n(^|\\.)powerphoto\\.org$\n(^|\\.)prayforchina\\.net$\n(^|\\.)premeforwindows7\\.com$\n(^|\\.)premproxy\\.com$\n(^|\\.)presentationzen\\.com$\n(^|\\.)presidentlee\\.tw$\n(^|\\.)prestige-av\\.com$\n(^|\\.)pride\\.google$\n(^|\\.)prism-break\\.org$\n(^|\\.)prisoneralert\\.com$\n(^|\\.)pritunl\\.com$\n(^|\\.)privacybox\\.de$\n(^|\\.)private\\.com$\n(^|\\.)privateinternetaccess\\.com$\n(^|\\.)privatepaste\\.com$\n(^|\\.)privatetunnel\\.com$\n(^|\\.)privatevpn\\.com$\n(^|\\.)procopytips\\.com$\n(^|\\.)prosiben\\.de$\n(^|\\.)protonvpn\\.com$\n(^|\\.)provideocoalition\\.com$\n(^|\\.)provpnaccounts\\.com$\n(^|\\.)proxfree\\.com$\n(^|\\.)proxifier\\.com$\n(^|\\.)proxomitron\\.info$\n(^|\\.)proxpn\\.com$\n(^|\\.)proxyanonimo\\.es$\n(^|\\.)proxydns\\.com$\n(^|\\.)proxylist\\.org\\.uk$\n(^|\\.)proxynetwork\\.org\\.uk$\n(^|\\.)proxypy\\.net$\n(^|\\.)proxyroad\\.com$\n(^|\\.)proxytunnel\\.net$\n(^|\\.)proyectoclubes\\.com$\n(^|\\.)prozz\\.net$\n(^|\\.)psblog\\.name$\n(^|\\.)pscp\\.tv$\n(^|\\.)psiphon3\\.com$\n(^|\\.)psiphon\\.ca$\n(^|\\.)psiphon\\.civisec\\.org$\n(^|\\.)psiphontoday\\.com$\n(^|\\.)pts\\.org\\.tw$\n(^|\\.)ptt\\.cc$\n(^|\\.)pttvan\\.org$\n(^|\\.)pubu\\.com\\.tw$\n(^|\\.)puffinbrowser\\.com$\n(^|\\.)puffstore\\.com$\n(^|\\.)pullfolio\\.com$\n(^|\\.)pulse\\.yahoo\\.com$\n(^|\\.)punyu\\.com$\n(^|\\.)pure18\\.com$\n(^|\\.)pureconcepts\\.net$\n(^|\\.)pureinsight\\.org$\n(^|\\.)purepdf\\.com$\n(^|\\.)purevpn\\.com$\n(^|\\.)purplelotus\\.org$\n(^|\\.)pursuestar\\.com$\n(^|\\.)pushchinawall\\.com$\n(^|\\.)pussyspace\\.com$\n(^|\\.)putihome\\.org$\n(^|\\.)putlocker\\.com$\n(^|\\.)putty\\.org$\n(^|\\.)puuko\\.com$\n(^|\\.)pwned\\.com$\n(^|\\.)python\\.com$\n(^|\\.)python\\.com\\.tw$\n(^|\\.)pythonhackers\\.com$\n(^|\\.)pytorch\\.org$\n(^|\\.)qanote\\.com$\n(^|\\.)qgirl\\.com\\.tw$\n(^|\\.)qhigh\\.com$\n(^|\\.)qiandao\\.today$\n(^|\\.)qiangyou\\.org$\n(^|\\.)qidian\\.ca$\n(^|\\.)qienkuen\\.org$\n(^|\\.)qi-gong\\.me$\n(^|\\.)qiwen\\.lu$\n(^|\\.)qixianglu\\.cn$\n(^|\\.)qkshare\\.com$\n(^|\\.)qoos\\.com$\n(^|\\.)qpoe\\.com$\n(^|\\.)qq\\.co\\.za$\n(^|\\.)qstatus\\.com$\n(^|\\.)qtrac\\.eu$\n(^|\\.)qtweeter\\.com$\n(^|\\.)quannengshen\\.org$\n(^|\\.)quantumbooter\\.net$\n(^|\\.)questvisual\\.com$\n(^|\\.)quitccp\\.net$\n(^|\\.)quitccp\\.org$\n(^|\\.)quoracdn\\.net$\n(^|\\.)quora\\.com$\n(^|\\.)quran\\.com$\n(^|\\.)quranexplorer\\.com$\n(^|\\.)qusi8\\.net$\n(^|\\.)qvodzy\\.org$\n(^|\\.)qxbbs\\.org$\n(^|\\.)qz\\.com$\n(^|\\.)r18\\.com$\n(^|\\.)radicalparty\\.org$\n(^|\\.)radiko\\.jp$\n(^|\\.)radioaustralia\\.net\\.au$\n(^|\\.)radiohilight\\.net$\n(^|\\.)radiovaticana\\.org$\n(^|\\.)radiovncr\\.com$\n(^|\\.)rael\\.org$\n(^|\\.)ra\\.gg$\n(^|\\.)raggedbanner\\.com$\n(^|\\.)raidcall\\.com\\.tw$\n(^|\\.)raidtalk\\.com\\.tw$\n(^|\\.)rainbowplan\\.org$\n(^|\\.)raindrop\\.io$\n(^|\\.)raizoji\\.or\\.jp$\n(^|\\.)ramcity\\.com\\.au$\n(^|\\.)rangwang\\.biz$\n(^|\\.)rangzen\\.com$\n(^|\\.)rangzen\\.net$\n(^|\\.)rangzen\\.org$\n(^|\\.)ranyunfei\\.com$\n(^|\\.)rapbull\\.net$\n(^|\\.)rapidgator\\.net$\n(^|\\.)rapidmoviez\\.com$\n(^|\\.)rapidvpn\\.com$\n(^|\\.)rarbgprx\\.org$\n(^|\\.)raremovie\\.cc$\n(^|\\.)raremovie\\.net$\n(^|\\.)rawgit\\.com$\n(^|\\.)rawgithub\\.com$\n(^|\\.)raw\\.githubusercontent\\.com$\n(^|\\.)razyboard\\.com$\n(^|\\.)rcam\\.target\\.com$\n(^|\\.)rcinet\\.ca$\n(^|\\.)rconversation\\.blogs\\.com$\n(^|\\.)rd\\.com$\n(^|\\.)rdio\\.com$\n(^|\\.)read01\\.com$\n(^|\\.)read100\\.com$\n(^|\\.)readingtimes\\.com\\.tw$\n(^|\\.)readmoo\\.com$\n(^|\\.)readydown\\.com$\n(^|\\.)realcourage\\.org$\n(^|\\.)realforum\\.zkiz\\.com$\n(^|\\.)realitykings\\.com$\n(^|\\.)realraptalk\\.com$\n(^|\\.)realsexpass\\.com$\n(^|\\.)rebatesrule\\.net$\n(^|\\.)recordhistory\\.org$\n(^|\\.)recovery\\.org\\.tw$\n(^|\\.)recoveryversion\\.com\\.tw$\n(^|\\.)redballoonsolidarity\\.org$\n(^|\\.)redchinacn\\.net$\n(^|\\.)redchinacn\\.org$\n(^|\\.)redd\\.it$\n(^|\\.)reddit\\.com$\n(^|\\.)redditlist\\.com$\n(^|\\.)redditmedia\\.com$\n(^|\\.)redditstatic\\.com$\n(^|\\.)redhotlabs\\.com$\n(^|\\.)red-lang\\.org$\n(^|\\.)redtube\\.com$\n(^|\\.)referer\\.us$\n(^|\\.)reflectivecode\\.com$\n(^|\\.)registry\\.google$\n(^|\\.)relaxbbs\\.com$\n(^|\\.)relay\\.com\\.tw$\n(^|\\.)releaseinternational\\.org$\n(^|\\.)religioustolerance\\.org$\n(^|\\.)renminbao\\.com$\n(^|\\.)renyurenquan\\.org$\n(^|\\.)research\\.jmsc\\.hku\\.hk$\n(^|\\.)resilio\\.com$\n(^|\\.)retweeteffect\\.com$\n(^|\\.)retweetist\\.com$\n(^|\\.)retweetrank\\.com$\n(^|\\.)reuters\\.com$\n(^|\\.)reutersmedia\\.net$\n(^|\\.)revleft\\.com$\n(^|\\.)revver\\.com$\n(^|\\.)rfachina\\.com$\n(^|\\.)rfalive1\\.akacast\\.akamaistream\\.net$\n(^|\\.)rfamobile\\.org$\n(^|\\.)rfa\\.org$\n(^|\\.)rfaweb\\.org$\n(^|\\.)rferl\\.org$\n(^|\\.)rfi\\.fr$\n(^|\\.)rfi\\.my$\n(^|\\.)rg3\\.github\\.io$\n(^|\\.)rightbtc\\.com$\n(^|\\.)rigpa\\.org$\n(^|\\.)riku\\.me$\n(^|\\.)rileyguide\\.com$\n(^|\\.)riseup\\.net$\n(^|\\.)ritouki\\.jp$\n(^|\\.)ritter\\.vg$\n(^|\\.)rixcloud\\.com$\n(^|\\.)rixcloud\\.us$\n(^|\\.)rlwlw\\.com$\n(^|\\.)rmjdw132\\.info$\n(^|\\.)rmjdw\\.com$\n(^|\\.)roadshow\\.hk$\n(^|\\.)roboforex\\.com$\n(^|\\.)robustnessiskey\\.com$\n(^|\\.)rocket-inc\\.net$\n(^|\\.)rocksdb\\.org$\n(^|\\.)rojo\\.com$\n(^|\\.)rolia\\.net$\n(^|\\.)ronjoneswriter\\.com$\n(^|\\.)roodo\\.com$\n(^|\\.)rosechina\\.net$\n(^|\\.)rotten\\.com$\n(^|\\.)rsdlmonitor\\.com$\n(^|\\.)rsf-chinese\\.org$\n(^|\\.)rsf\\.org$\n(^|\\.)rsgamen\\.org$\n(^|\\.)rssmeme\\.com$\n(^|\\.)rtalabel\\.org$\n(^|\\.)rthk\\.hk$\n(^|\\.)rthklive2-lh\\.akamaihd\\.net$\n(^|\\.)rthk\\.org\\.hk$\n(^|\\.)rti\\.org\\.tw$\n(^|\\.)rtycminnesota\\.org$\n(^|\\.)ruanyifeng\\.com$\n(^|\\.)rukor\\.org$\n(^|\\.)runbtx\\.com$\n(^|\\.)rushbee\\.com$\n(^|\\.)ruten\\.com\\.tw$\n(^|\\.)rutube\\.ru$\n(^|\\.)ruyiseek\\.com$\n(^|\\.)rxhj\\.net$\n(^|\\.)s1heng\\.com$\n(^|\\.)s1\\.nudezz\\.com$\n(^|\\.)s1s1s1\\.com$\n(^|\\.)s3\\.amazonaws\\.com$\n(^|\\.)s3-ap-northeast-1\\.amazonaws\\.com$\n(^|\\.)s3-ap-southeast-2\\.amazonaws\\.com$\n(^|\\.)s8forum\\.com$\n(^|\\.)sacks\\.com$\n(^|\\.)sacom\\.hk$\n(^|\\.)sadistic-v\\.com$\n(^|\\.)sadpanda\\.us$\n(^|\\.)safervpn\\.com$\n(^|\\.)safety\\.google$\n(^|\\.)sa\\.hao123\\.com$\n(^|\\.)saintyculture\\.com$\n(^|\\.)saiq\\.me$\n(^|\\.)sakuralive\\.com$\n(^|\\.)sakya\\.org$\n(^|\\.)salvation\\.org\\.hk$\n(^|\\.)samair\\.ru$\n(^|\\.)sambhota\\.org$\n(^|\\.)sanmin\\.com\\.tw$\n(^|\\.)sapikachu\\.net$\n(^|\\.)saveliuxiaobo\\.com$\n(^|\\.)savemedia\\.com$\n(^|\\.)savethedate\\.foo$\n(^|\\.)savethesounds\\.info$\n(^|\\.)savetibet\\.de$\n(^|\\.)savetibet\\.fr$\n(^|\\.)savetibet\\.nl$\n(^|\\.)savetibet\\.org$\n(^|\\.)savetibet\\.ru$\n(^|\\.)savetibetstore\\.org$\n(^|\\.)savevid\\.com$\n(^|\\.)say2\\.info$\n(^|\\.)sbme\\.me$\n(^|\\.)sbs\\.com\\.au$\n(^|\\.)scache1\\.vzw\\.com$\n(^|\\.)scache2\\.vzw\\.com$\n(^|\\.)scache\\.vzw\\.com$\n(^|\\.)scasino\\.com$\n(^|\\.)schema\\.org$\n(^|\\.)sciencenets\\.com$\n(^|\\.)scieron\\.com$\n(^|\\.)scmpchinese\\.com$\n(^|\\.)scmp\\.com$\n(^|\\.)scramble\\.io$\n(^|\\.)scribd\\.com$\n(^|\\.)scriptspot\\.com$\n(^|\\.)s-cute\\.com$\n(^|\\.)s-dragon\\.org$\n(^|\\.)seapuff\\.com$\n(^|\\.)search\\.aol\\.com$\n(^|\\.)searchtruth\\.com$\n(^|\\.)search\\.xxx$\n(^|\\.)search\\.yahoo\\.co\\.jp$\n(^|\\.)search\\.yahoo\\.com$\n(^|\\.)secretchina\\.com$\n(^|\\.)secretgarden\\.no$\n(^|\\.)secretsline\\.biz$\n(^|\\.)secure\\.hustler\\.com$\n(^|\\.)secure\\.logmein\\.com$\n(^|\\.)secure\\.raxcdn\\.com$\n(^|\\.)securetunnel\\.com$\n(^|\\.)securityinabox\\.org$\n(^|\\.)securitykiss\\.com$\n(^|\\.)seed4\\.me$\n(^|\\.)seesmic\\.com$\n(^|\\.)seevpn\\.com$\n(^|\\.)seezone\\.net$\n(^|\\.)sejie\\.com$\n(^|\\.)sellclassics\\.com$\n(^|\\.)sendsmtp\\.com$\n(^|\\.)sendspace\\.com$\n(^|\\.)servehttp\\.com$\n(^|\\.)serveuser\\.com$\n(^|\\.)serveusers\\.com$\n(^|\\.)sesawe\\.net$\n(^|\\.)sesawe\\.org$\n(^|\\.)sethwklein\\.net$\n(^|\\.)setn\\.com$\n(^|\\.)settv\\.com\\.tw$\n(^|\\.)sevenload\\.com$\n(^|\\.)sex-11\\.com$\n(^|\\.)sex3\\.com$\n(^|\\.)sex8\\.cc$\n(^|\\.)sexandsubmission\\.com$\n(^|\\.)sexbot\\.com$\n(^|\\.)sex\\.com$\n(^|\\.)sexhuang\\.com$\n(^|\\.)sexhu\\.com$\n(^|\\.)sexidude\\.com$\n(^|\\.)sexinsex\\.net$\n(^|\\.)sextvx\\.com$\n(^|\\.)sexxxy\\.biz$\n(^|\\.)sfileydy\\.com$\n(^|\\.)sf\\.net$\n(^|\\.)sfshibao\\.com$\n(^|\\.)sftindia\\.org$\n(^|\\.)sftuk\\.org$\n(^|\\.)shadeyouvpn\\.com$\n(^|\\.)shadow\\.ma$\n(^|\\.)shadowsky\\.xyz$\n(^|\\.)shadowsocks9\\.com$\n(^|\\.)shadowsocks\\.asia$\n(^|\\.)shadowsocks\\.be$\n(^|\\.)shadowsocks\\.com$\n(^|\\.)shadowsocks\\.com\\.hk$\n(^|\\.)shadowsocks\\.org$\n(^|\\.)shadowsocks-r\\.com$\n(^|\\.)shambalapost\\.com$\n(^|\\.)shambhalasun\\.com$\n(^|\\.)shangfang\\.org$\n(^|\\.)shapeservices\\.com$\n(^|\\.)share\\.america\\.gov$\n(^|\\.)sharebee\\.com$\n(^|\\.)sharecool\\.org$\n(^|\\.)share\\.dmhy\\.org$\n(^|\\.)share\\.ovi\\.com$\n(^|\\.)share\\.youthwant\\.com\\.tw$\n(^|\\.)sharpdaily\\.com\\.hk$\n(^|\\.)sharpdaily\\.hk$\n(^|\\.)sharpdaily\\.tw$\n(^|\\.)shattered\\.io$\n(^|\\.)shat-tibet\\.com$\n(^|\\.)sheikyermami\\.com$\n(^|\\.)shellfire\\.de$\n(^|\\.)shenshou\\.org$\n(^|\\.)shenyun\\.com$\n(^|\\.)shenyunperformingarts\\.org$\n(^|\\.)shenzhoufilm\\.com$\n(^|\\.)sherabgyaltsen\\.com$\n(^|\\.)shiatv\\.net$\n(^|\\.)shicheng\\.org$\n(^|\\.)shiksha\\.com$\n(^|\\.)shinychan\\.com$\n(^|\\.)shipcamouflage\\.com$\n(^|\\.)shireyishunjian\\.com$\n(^|\\.)shitaotv\\.org$\n(^|\\.)shixiao\\.org$\n(^|\\.)shizhao\\.org$\n(^|\\.)shkspr\\.mobi$\n(^|\\.)shodanhq\\.com$\n(^|\\.)shooshtime\\.com$\n(^|\\.)shop2000\\.com\\.tw$\n(^|\\.)shopping\\.com$\n(^|\\.)showbiz\\.omy\\.sg$\n(^|\\.)showhaotu\\.com$\n(^|\\.)showtime\\.jp$\n(^|\\.)shutterstock\\.com$\n(^|\\.)shwchurch3\\.com$\n(^|\\.)shwchurch\\.org$\n(^|\\.)siddharthasintent\\.org$\n(^|\\.)sidelinesnews\\.com$\n(^|\\.)sidelinessportseatery\\.com$\n(^|\\.)sierrafriendsoftibet\\.org$\n(^|\\.)sijihuisuo\\.club$\n(^|\\.)sijihuisuo\\.com$\n(^|\\.)sikaozhe1997\\.github\\.io$\n(^|\\.)silkbook\\.com$\n(^|\\.)simbolostwitter\\.com$\n(^|\\.)simplecd\\.org$\n(^|\\.)simpleproductivityblog\\.com$\n(^|\\.)sinchew\\.com\\.my$\n(^|\\.)singaporepools\\.com\\.sg$\n(^|\\.)singfortibet\\.com$\n(^|\\.)singpao\\.com\\.hk$\n(^|\\.)singtao\\.com$\n(^|\\.)singtaousa\\.com$\n(^|\\.)sinoants\\.com$\n(^|\\.)sinocast\\.com$\n(^|\\.)sinocism\\.com$\n(^|\\.)sino-monthly\\.com$\n(^|\\.)sinomontreal\\.ca$\n(^|\\.)sinonet\\.ca$\n(^|\\.)sinopitt\\.info$\n(^|\\.)sinoquebec\\.com$\n(^|\\.)sipml5\\.org$\n(^|\\.)sis001\\.com$\n(^|\\.)sis001\\.us$\n(^|\\.)sis\\.xxx$\n(^|\\.)site2unblock\\.com$\n(^|\\.)site90\\.net$\n(^|\\.)sitebro\\.tw$\n(^|\\.)sitekreator\\.com$\n(^|\\.)siteks\\.uk\\.to$\n(^|\\.)sitemaps\\.org$\n(^|\\.)six-degrees\\.io$\n(^|\\.)sixth\\.biz$\n(^|\\.)sjrt\\.org$\n(^|\\.)sjum\\.cn$\n(^|\\.)sketchappsources\\.com$\n(^|\\.)skimtube\\.com$\n(^|\\.)skybet\\.com$\n(^|\\.)skyking\\.com\\.tw$\n(^|\\.)skyvegas\\.com$\n(^|\\.)skyxvpn\\.com$\n(^|\\.)slacker\\.com$\n(^|\\.)slaytizle\\.com$\n(^|\\.)sleazydream\\.com$\n(^|\\.)slheng\\.com$\n(^|\\.)slickvpn\\.com$\n(^|\\.)slideshare\\.net$\n(^|\\.)slinkset\\.com$\n(^|\\.)slutload\\.com$\n(^|\\.)slutmoonbeam\\.com$\n(^|\\.)slyip\\.com$\n(^|\\.)slyip\\.net$\n(^|\\.)smartdnsproxy\\.com$\n(^|\\.)smarthide\\.com$\n(^|\\.)smchbooks\\.com$\n(^|\\.)smh\\.com\\.au$\n(^|\\.)smhric\\.org$\n(^|\\.)smith\\.edu$\n(^|\\.)sm-miracle\\.com$\n(^|\\.)smyxy\\.org$\n(^|\\.)snapchat\\.com$\n(^|\\.)snaptu\\.com$\n(^|\\.)sndcdn\\.com$\n(^|\\.)sneakme\\.net$\n(^|\\.)snowlionpub\\.com$\n(^|\\.)sobees\\.com$\n(^|\\.)socialwhale\\.com$\n(^|\\.)sockscap64\\.com$\n(^|\\.)sockslist\\.net$\n(^|\\.)socks-proxy\\.net$\n(^|\\.)soc\\.mil$\n(^|\\.)socrec\\.org$\n(^|\\.)sodatea\\.github\\.io$\n(^|\\.)sod\\.co\\.jp$\n(^|\\.)softether\\.co\\.jp$\n(^|\\.)softether-download\\.com$\n(^|\\.)softether\\.org$\n(^|\\.)softfamous\\.com$\n(^|\\.)softsmirror\\.cf$\n(^|\\.)softwarebychuck\\.com$\n(^|\\.)softwaredownload\\.gitbooks\\.io$\n(^|\\.)sogclub\\.com$\n(^|\\.)sogrady\\.me$\n(^|\\.)sohcradio\\.com$\n(^|\\.)sohfrance\\.org$\n(^|\\.)soh\\.tw$\n(^|\\.)sokamonline\\.com$\n(^|\\.)sokmil\\.com$\n(^|\\.)solarsystem\\.nasa\\.gov$\n(^|\\.)solidaritetibet\\.org$\n(^|\\.)solidfiles\\.com$\n(^|\\.)somee\\.com$\n(^|\\.)songjianjun\\.com$\n(^|\\.)sonicbbs\\.cc$\n(^|\\.)sonidodelaesperanza\\.org$\n(^|\\.)sopcast\\.com$\n(^|\\.)sopcast\\.org$\n(^|\\.)sorazone\\.net$\n(^|\\.)sorting-algorithms\\.com$\n(^|\\.)sos\\.org$\n(^|\\.)sosreader\\.com$\n(^|\\.)sostibet\\.org$\n(^|\\.)soubory\\.com$\n(^|\\.)soulcaliburhentai\\.net$\n(^|\\.)soul-plus\\.net$\n(^|\\.)soumo\\.info$\n(^|\\.)soundcloud\\.com$\n(^|\\.)soundofhope\\.kr$\n(^|\\.)soundofhope\\.org$\n(^|\\.)soup\\.io$\n(^|\\.)soupofmedia\\.com$\n(^|\\.)sourceforge\\.net$\n(^|\\.)sourcewadio\\.com$\n(^|\\.)southnews\\.com\\.tw$\n(^|\\.)sowers\\.org\\.hk$\n(^|\\.)soylentnews\\.org$\n(^|\\.)spaces\\.hightail\\.com$\n(^|\\.)spankbang\\.com$\n(^|\\.)spankingtube\\.com$\n(^|\\.)spankwire\\.com$\n(^|\\.)spb\\.com$\n(^|\\.)speakerdeck\\.com$\n(^|\\.)specxinzl\\.jigsy\\.com$\n(^|\\.)speedify\\.com$\n(^|\\.)spem\\.at$\n(^|\\.)spencertipping\\.com$\n(^|\\.)spendee\\.com$\n(^|\\.)spicevpn\\.com$\n(^|\\.)spideroak\\.com$\n(^|\\.)spike\\.com$\n(^|\\.)sports\\.williamhill\\.com$\n(^|\\.)spotflux\\.com$\n(^|\\.)spotify\\.com$\n(^|\\.)spreadshirt\\.es$\n(^|\\.)spring4u\\.info$\n(^|\\.)springboardplatform\\.com$\n(^|\\.)sprite\\.org$\n(^|\\.)sproutcore\\.com$\n(^|\\.)sproxy\\.info$\n(^|\\.)squirly\\.info$\n(^|\\.)srcf\\.ucam\\.org$\n(^|\\.)srocket\\.us$\n(^|\\.)ss7\\.vzw\\.com$\n(^|\\.)ss\\.carryzhou\\.com$\n(^|\\.)ssglobal\\.co$\n(^|\\.)ssglobal\\.me$\n(^|\\.)ssh91\\.com$\n(^|\\.)ssl443\\.org$\n(^|\\.)ss\\.levyhsu\\.com$\n(^|\\.)ss-link\\.com$\n(^|\\.)ssl\\.webpack\\.de$\n(^|\\.)sspanel\\.net$\n(^|\\.)sspro\\.ml$\n(^|\\.)ss\\.pythonic\\.life$\n(^|\\.)ssrshare\\.com$\n(^|\\.)ssr\\.tools$\n(^|\\.)sss\\.camp$\n(^|\\.)sstmlt\\.moe$\n(^|\\.)sstmlt\\.net$\n(^|\\.)stackoverflow\\.com$\n(^|\\.)stage64\\.hk$\n(^|\\.)standupfortibet\\.org$\n(^|\\.)stanford\\.edu$\n(^|\\.)starfishfx\\.com$\n(^|\\.)starp2p\\.com$\n(^|\\.)startpage\\.com$\n(^|\\.)startuplivingchina\\.com$\n(^|\\.)stat\\.gov\\.tw$\n(^|\\.)static01\\.nyt\\.com$\n(^|\\.)static\\.comico\\.tw$\n(^|\\.)static-economist\\.com$\n(^|\\.)staticflickr\\.com$\n(^|\\.)static\\.shemalez\\.com$\n(^|\\.)statueofdemocracy\\.org$\n(^|\\.)stc\\.com\\.sa$\n(^|\\.)steamcommunity\\.com$\n(^|\\.)steel-storm\\.com$\n(^|\\.)steemit\\.com$\n(^|\\.)steganos\\.com$\n(^|\\.)steganos\\.net$\n(^|\\.)stepchina\\.com$\n(^|\\.)stephaniered\\.com$\n(^|\\.)sthoo\\.com$\n(^|\\.)stickam\\.com$\n(^|\\.)stickeraction\\.com$\n(^|\\.)stileproject\\.com$\n(^|\\.)sto\\.cc$\n(^|\\.)stoporganharvesting\\.org$\n(^|\\.)stoptibetcrisis\\.net$\n(^|\\.)storagenewsletter\\.com$\n(^|\\.)store\\.steampowered\\.com$\n(^|\\.)stories\\.google$\n(^|\\.)storify\\.com$\n(^|\\.)stormmediagroup\\.com$\n(^|\\.)storm\\.mg$\n(^|\\.)stoweboyd\\.com$\n(^|\\.)stranabg\\.com$\n(^|\\.)straplessdildo\\.com$\n(^|\\.)streamingthe\\.net$\n(^|\\.)streema\\.com$\n(^|\\.)strikingly\\.com$\n(^|\\.)strongvpn\\.com$\n(^|\\.)strongwindpress\\.com$\n(^|\\.)studentsforafreetibet\\.org$\n(^|\\.)student\\.tw$\n(^|\\.)stumbleupon\\.com$\n(^|\\.)stupidvideos\\.com$\n(^|\\.)subacme\\.rerouted\\.org$\n(^|\\.)successfn\\.com$\n(^|\\.)sugarsync\\.com$\n(^|\\.)sugobbs\\.com$\n(^|\\.)sugumiru18\\.com$\n(^|\\.)suissl\\.com$\n(^|\\.)sujiatun\\.wordpress\\.com$\n(^|\\.)sukebei\\.nyaa\\.si$\n(^|\\.)sulian\\.me$\n(^|\\.)summify\\.com$\n(^|\\.)sumrando\\.com$\n(^|\\.)sun1911\\.com$\n(^|\\.)sunmedia\\.ca$\n(^|\\.)sunporno\\.com$\n(^|\\.)sunskyforum\\.com$\n(^|\\.)sunta\\.com\\.tw$\n(^|\\.)sunvpn\\.net$\n(^|\\.)sunwinism\\.joinbbs\\.net$\n(^|\\.)suoluo\\.org$\n(^|\\.)supchina\\.com$\n(^|\\.)superfreevpn\\.com$\n(^|\\.)superokayama\\.com$\n(^|\\.)superpages\\.com$\n(^|\\.)supervpn\\.net$\n(^|\\.)superzooi\\.com$\n(^|\\.)suppig\\.net$\n(^|\\.)suprememastertv\\.com$\n(^|\\.)surfeasy\\.com$\n(^|\\.)surfeasy\\.com\\.au$\n(^|\\.)suroot\\.com$\n(^|\\.)surrenderat20\\.net$\n(^|\\.)sustainability\\.google$\n(^|\\.)suyangg\\.com$\n(^|\\.)svsfx\\.com$\n(^|\\.)swagbucks\\.com$\n(^|\\.)swissinfo\\.ch$\n(^|\\.)swissvpn\\.net$\n(^|\\.)switch1\\.jp$\n(^|\\.)switchvpn\\.net$\n(^|\\.)sydneytoday\\.com$\n(^|\\.)sylfoundation\\.org$\n(^|\\.)syncback\\.com$\n(^|\\.)synergyse\\.com$\n(^|\\.)sysresccd\\.org$\n(^|\\.)sytes\\.net$\n(^|\\.)szbbs\\.net$\n(^|\\.)szetowah\\.org\\.hk$\n(^|\\.)t35\\.com$\n(^|\\.)t66y\\.com$\n(^|\\.)taa-usa\\.org$\n(^|\\.)taaze\\.tw$\n(^|\\.)tabtter\\.jp$\n(^|\\.)tacc\\.cwb\\.gov\\.tw$\n(^|\\.)tacem\\.org$\n(^|\\.)taconet\\.com\\.tw$\n(^|\\.)taedp\\.org\\.tw$\n(^|\\.)tafm\\.org$\n(^|\\.)tagwalk\\.com$\n(^|\\.)tagwa\\.org\\.au$\n(^|\\.)tahr\\.org\\.tw$\n(^|\\.)taipei\\.gov\\.tw$\n(^|\\.)taipeisociety\\.org$\n(^|\\.)taiwanbible\\.com$\n(^|\\.)taiwancon\\.com$\n(^|\\.)taiwandaily\\.net$\n(^|\\.)taiwandc\\.org$\n(^|\\.)taiwanjobs\\.gov\\.tw$\n(^|\\.)taiwanjustice\\.com$\n(^|\\.)taiwanjustice\\.net$\n(^|\\.)taiwankiss\\.com$\n(^|\\.)taiwannation\\.50webs\\.com$\n(^|\\.)taiwannation\\.com$\n(^|\\.)taiwannation\\.com\\.tw$\n(^|\\.)taiwanncf\\.org\\.tw$\n(^|\\.)taiwannews\\.com\\.tw$\n(^|\\.)taiwan-sex\\.com$\n(^|\\.)taiwantp\\.net$\n(^|\\.)taiwantt\\.org\\.tw$\n(^|\\.)taiwanus\\.net$\n(^|\\.)taiwanyes\\.com$\n(^|\\.)taiwanyes\\.ning\\.com$\n(^|\\.)talk853\\.com$\n(^|\\.)talkboxapp\\.com$\n(^|\\.)talkcc\\.com$\n(^|\\.)talkonly\\.net$\n(^|\\.)tamiaode\\.tk$\n(^|\\.)tanc\\.org$\n(^|\\.)tangben\\.com$\n(^|\\.)tangren\\.us$\n(^|\\.)taoism\\.net$\n(^|\\.)taolun\\.info$\n(^|\\.)tapanwap\\.com$\n(^|\\.)tapatalk\\.com$\n(^|\\.)tarr\\.uspto\\.gov$\n(^|\\.)tascn\\.com\\.au$\n(^|\\.)taup\\.net$\n(^|\\.)taweet\\.com$\n(^|\\.)tbcollege\\.org$\n(^|\\.)tbicn\\.org$\n(^|\\.)tbi\\.org\\.hk$\n(^|\\.)tbjyt\\.org$\n(^|\\.)tbpic\\.info$\n(^|\\.)tbrc\\.org$\n(^|\\.)tbsec\\.org$\n(^|\\.)tbskkinabalu\\.page\\.tl$\n(^|\\.)tbsmalaysia\\.org$\n(^|\\.)tbsn\\.org$\n(^|\\.)tbs-rainbow\\.org$\n(^|\\.)tbsseattle\\.org$\n(^|\\.)tbssqh\\.org$\n(^|\\.)tbswd\\.org$\n(^|\\.)tbtemple\\.org\\.uk$\n(^|\\.)tbthouston\\.org$\n(^|\\.)tccwonline\\.org$\n(^|\\.)tcewf\\.org$\n(^|\\.)tchrd\\.org$\n(^|\\.)tcnynj\\.org$\n(^|\\.)t\\.co$\n(^|\\.)tcpspeed\\.co$\n(^|\\.)tcpspeed\\.com$\n(^|\\.)tcsofbc\\.org$\n(^|\\.)tcsovi\\.org$\n(^|\\.)tdm\\.com\\.mo$\n(^|\\.)teachparentstech\\.org$\n(^|\\.)teamamericany\\.com$\n(^|\\.)tech2\\.in\\.com$\n(^|\\.)techviz\\.net$\n(^|\\.)teck\\.in$\n(^|\\.)teco-hk\\.org$\n(^|\\.)teco-mo\\.org$\n(^|\\.)teddysun\\.com$\n(^|\\.)teeniefuck\\.net$\n(^|\\.)teensinasia\\.com$\n(^|\\.)telecomspace\\.com$\n(^|\\.)telegram\\.dog$\n(^|\\.)telegramdownload\\.com$\n(^|\\.)telegram\\.me$\n(^|\\.)telegram\\.org$\n(^|\\.)telegraph\\.co\\.uk$\n(^|\\.)telesco\\.pe$\n(^|\\.)tellme\\.pw$\n(^|\\.)tenacy\\.com$\n(^|\\.)tensorflow\\.org$\n(^|\\.)tenzinpalmo\\.com$\n(^|\\.)terminus2049\\.github\\.io$\n(^|\\.)tew\\.org$\n(^|\\.)textnow\\.me$\n(^|\\.)tfhub\\.dev$\n(^|\\.)t-g\\.com$\n(^|\\.)thaicn\\.com$\n(^|\\.)thb\\.gov\\.tw$\n(^|\\.)theatrum-belli\\.com$\n(^|\\.)thebcomplex\\.com$\n(^|\\.)theblemish\\.com$\n(^|\\.)thebobs\\.com$\n(^|\\.)thebodyshop-usa\\.com$\n(^|\\.)thecenter\\.mit\\.edu$\n(^|\\.)thechinabeat\\.org$\n(^|\\.)thedalailamamovie\\.com$\n(^|\\.)thedw\\.us$\n(^|\\.)thefacebook\\.com$\n(^|\\.)thefrontier\\.hk$\n(^|\\.)thegioitinhoc\\.vn$\n(^|\\.)thegly\\.com$\n(^|\\.)thehots\\.info$\n(^|\\.)thehousenews\\.com$\n(^|\\.)thehun\\.net$\n(^|\\.)theinitium\\.com$\n(^|\\.)thenewslens\\.com$\n(^|\\.)thepiratebay\\.org$\n(^|\\.)theporndude\\.com$\n(^|\\.)theportalwiki\\.com$\n(^|\\.)thereallove\\.kr$\n(^|\\.)therock\\.net\\.nz$\n(^|\\.)thespeeder\\.com$\n(^|\\.)thestandnews\\.com$\n(^|\\.)thetibetcenter\\.org$\n(^|\\.)thetibetconnection\\.org$\n(^|\\.)thetibetmuseum\\.org$\n(^|\\.)thetibetpost\\.com$\n(^|\\.)thetinhat\\.com$\n(^|\\.)thetrotskymovie\\.com$\n(^|\\.)thevivekspot\\.com$\n(^|\\.)thewgo\\.org$\n(^|\\.)theync\\.com$\n(^|\\.)th\\.hao123\\.com$\n(^|\\.)thinkgeek\\.com$\n(^|\\.)thinkingtaiwan\\.com$\n(^|\\.)thinkwithgoogle\\.com$\n(^|\\.)thisav\\.com$\n(^|\\.)thlib\\.org$\n(^|\\.)thomasbernhard\\.org$\n(^|\\.)thongdreams\\.com$\n(^|\\.)threatchaos\\.com$\n(^|\\.)throughnightsfire\\.com$\n(^|\\.)thumbzilla\\.com$\n(^|\\.)thywords\\.com$\n(^|\\.)thywords\\.com\\.tw$\n(^|\\.)tiananmenduizhi\\.com$\n(^|\\.)tiananmenmother\\.org$\n(^|\\.)tiananmenuniv\\.com$\n(^|\\.)tiananmenuniv\\.net$\n(^|\\.)tiandixing\\.org$\n(^|\\.)tianhuayuan\\.com$\n(^|\\.)tianlawoffice\\.com$\n(^|\\.)tiantibooks\\.org$\n(^|\\.)tianti\\.io$\n(^|\\.)tianyantong\\.org\\.cn$\n(^|\\.)tianzhu\\.org$\n(^|\\.)tibet3rdpole\\.org$\n(^|\\.)tibetaction\\.net$\n(^|\\.)tibetaid\\.org$\n(^|\\.)tibetalk\\.com$\n(^|\\.)tibetanaidproject\\.org$\n(^|\\.)tibetan-alliance\\.org$\n(^|\\.)tibetanarts\\.org$\n(^|\\.)tibetanbuddhistinstitute\\.org$\n(^|\\.)tibetancommunity\\.org$\n(^|\\.)tibetancommunityuk\\.net$\n(^|\\.)tibetanculture\\.org$\n(^|\\.)tibetanfeministcollective\\.org$\n(^|\\.)tibetan\\.fr$\n(^|\\.)tibetanjournal\\.com$\n(^|\\.)tibetanlanguage\\.org$\n(^|\\.)tibetanliberation\\.org$\n(^|\\.)tibetanpaintings\\.com$\n(^|\\.)tibetanphotoproject\\.com$\n(^|\\.)tibetanpoliticalreview\\.org$\n(^|\\.)tibetanreview\\.net$\n(^|\\.)tibetansports\\.org$\n(^|\\.)tibetanwomen\\.org$\n(^|\\.)tibetanyouthcongress\\.org$\n(^|\\.)tibetanyouth\\.org$\n(^|\\.)tibet\\.a\\.se$\n(^|\\.)tibet\\.at$\n(^|\\.)tibet\\.ca$\n(^|\\.)tibetcharity\\.dk$\n(^|\\.)tibetcharity\\.in$\n(^|\\.)tibetchild\\.org$\n(^|\\.)tibetcity\\.com$\n(^|\\.)tibetcollection\\.com$\n(^|\\.)tibet\\.com$\n(^|\\.)tibetcorps\\.org$\n(^|\\.)tibet-envoy\\.eu$\n(^|\\.)tibetexpress\\.net$\n(^|\\.)tibetfocus\\.com$\n(^|\\.)tibet-foundation\\.org$\n(^|\\.)tibet\\.fr$\n(^|\\.)tibetfund\\.org$\n(^|\\.)tibetgermany\\.com$\n(^|\\.)tibetgermany\\.de$\n(^|\\.)tibethaus\\.com$\n(^|\\.)tibetheritagefund\\.org$\n(^|\\.)tibethouse\\.jp$\n(^|\\.)tibethouse\\.org$\n(^|\\.)tibet-house-trust\\.co\\.uk$\n(^|\\.)tibethouse\\.us$\n(^|\\.)tibet-info\\.net$\n(^|\\.)tibetinfonet\\.net$\n(^|\\.)tibet-initiative\\.de$\n(^|\\.)tibetjustice\\.org$\n(^|\\.)tibetkomite\\.dk$\n(^|\\.)tibetlibre\\.free\\.fr$\n(^|\\.)tibet-munich\\.de$\n(^|\\.)tibetmuseum\\.org$\n(^|\\.)tibet\\.net$\n(^|\\.)tibetnetwork\\.org$\n(^|\\.)tibet\\.nu$\n(^|\\.)tibetoffice\\.ch$\n(^|\\.)tibetoffice\\.com\\.au$\n(^|\\.)tibetoffice\\.eu$\n(^|\\.)tibetoffice\\.org$\n(^|\\.)tibetonline\\.com$\n(^|\\.)tibetonline\\.tv$\n(^|\\.)tibetoralhistory\\.org$\n(^|\\.)tibet\\.org$\n(^|\\.)tibet\\.org\\.tw$\n(^|\\.)tibetpolicy\\.eu$\n(^|\\.)tibetrelieffund\\.co\\.uk$\n(^|\\.)tibetsites\\.com$\n(^|\\.)tibet\\.sk$\n(^|\\.)tibetsociety\\.com$\n(^|\\.)tibetsun\\.com$\n(^|\\.)tibetsupportgroup\\.org$\n(^|\\.)tibetswiss\\.ch$\n(^|\\.)tibettelegraph\\.com$\n(^|\\.)tibettimes\\.net$\n(^|\\.)tibet\\.to$\n(^|\\.)tibetwrites\\.org$\n(^|\\.)ticket\\.com\\.tw$\n(^|\\.)tigervpn\\.com$\n(^|\\.)tiltbrush\\.com$\n(^|\\.)timdir\\.com$\n(^|\\.)time\\.com$\n(^|\\.)times\\.hinet\\.net$\n(^|\\.)timesofindia\\.indiatimes\\.com$\n(^|\\.)timsah\\.com$\n(^|\\.)tinc-vpn\\.org$\n(^|\\.)tineye\\.com$\n(^|\\.)tintuc101\\.com$\n(^|\\.)tiny\\.cc$\n(^|\\.)tinychat\\.com$\n(^|\\.)tinypaste\\.com$\n(^|\\.)tipo\\.gov\\.tw$\n(^|\\.)tistory\\.com$\n(^|\\.)tkcs-collins\\.com$\n(^|\\.)tl\\.gd$\n(^|\\.)tma\\.co\\.jp$\n(^|\\.)tmagazine\\.com$\n(^|\\.)tmdfish\\.com$\n(^|\\.)t\\.me$\n(^|\\.)tmi\\.me$\n(^|\\.)tmpp\\.org$\n(^|\\.)tn1\\.shemalez\\.com$\n(^|\\.)tn2\\.shemalez\\.com$\n(^|\\.)tn3\\.shemalez\\.com$\n(^|\\.)tnaflix\\.com$\n(^|\\.)tngrnow\\.com$\n(^|\\.)tngrnow\\.net$\n(^|\\.)tnp\\.org$\n(^|\\.)togetter\\.com$\n(^|\\.)toh\\.info$\n(^|\\.)tokyo-247\\.com$\n(^|\\.)tokyocn\\.com$\n(^|\\.)tokyo-hot\\.com$\n(^|\\.)tokyo-porn-tube\\.com$\n(^|\\.)tongil\\.or\\.kr$\n(^|\\.)tono-oka\\.jp$\n(^|\\.)tonyyan\\.net$\n(^|\\.)toodoc\\.com$\n(^|\\.)toonel\\.net$\n(^|\\.)top10vpn\\.com$\n(^|\\.)top81\\.ws$\n(^|\\.)topbtc\\.com$\n(^|\\.)topic\\.youthwant\\.com\\.tw$\n(^|\\.)topnews\\.in$\n(^|\\.)to-porno\\.com$\n(^|\\.)toppornsites\\.com$\n(^|\\.)topshareware\\.com$\n(^|\\.)topsy\\.com$\n(^|\\.)toptip\\.ca$\n(^|\\.)top\\.tv$\n(^|\\.)tora\\.to$\n(^|\\.)tor\\.blingblingsquad\\.net$\n(^|\\.)torcn\\.com$\n(^|\\.)tor\\.cn\\.uptodown\\.com$\n(^|\\.)torguard\\.net$\n(^|\\.)torproject\\.org$\n(^|\\.)torrentprivacy\\.com$\n(^|\\.)torrentproject\\.se$\n(^|\\.)torrenty\\.org$\n(^|\\.)torrentz\\.eu$\n(^|\\.)tor\\.updatestar\\.com$\n(^|\\.)torvpn\\.com$\n(^|\\.)t\\.orzdream\\.com$\n(^|\\.)tosh\\.comedycentral\\.com$\n(^|\\.)totalvpn\\.com$\n(^|\\.)toutiaoabc\\.com$\n(^|\\.)toutyrater\\.github\\.io$\n(^|\\.)towngain\\.com$\n(^|\\.)toypark\\.in$\n(^|\\.)toythieves\\.com$\n(^|\\.)toytractorshow\\.com$\n(^|\\.)tparents\\.org$\n(^|\\.)tpi\\.org\\.tw$\n(^|\\.)tracfone\\.com$\n(^|\\.)traffichaus\\.com$\n(^|\\.)transparency\\.org$\n(^|\\.)trans\\.wenweipo\\.com$\n(^|\\.)treemall\\.com\\.tw$\n(^|\\.)trendsmap\\.com$\n(^|\\.)trialofccp\\.org$\n(^|\\.)trickip\\.net$\n(^|\\.)trickip\\.org$\n(^|\\.)trimondi\\.de$\n(^|\\.)trouw\\.nl$\n(^|\\.)trtc\\.com\\.tw$\n(^|\\.)trt\\.net\\.tr$\n(^|\\.)truebuddha-md\\.org$\n(^|\\.)trulyergonomic\\.com$\n(^|\\.)truth101\\.co\\.tv$\n(^|\\.)truthontour\\.org$\n(^|\\.)truveo\\.com$\n(^|\\.)tryheart\\.jp$\n(^|\\.)tsctv\\.net$\n(^|\\.)tsdr\\.uspto\\.gov$\n(^|\\.)tsemtulku\\.com$\n(^|\\.)tsquare\\.tv$\n(^|\\.)tsunagarumon\\.com$\n(^|\\.)tsu\\.org\\.tw$\n(^|\\.)tt1069\\.com$\n(^|\\.)tttan\\.com$\n(^|\\.)ttvnw\\.net$\n(^|\\.)tu8964\\.com$\n(^|\\.)tubaholic\\.com$\n(^|\\.)tube8\\.com$\n(^|\\.)tube911\\.com$\n(^|\\.)tube\\.com$\n(^|\\.)tubecup\\.com$\n(^|\\.)tubegals\\.com$\n(^|\\.)tubeislam\\.com$\n(^|\\.)tubepornclassic\\.com$\n(^|\\.)tubestack\\.com$\n(^|\\.)tubewolf\\.com$\n(^|\\.)tuibeitu\\.net$\n(^|\\.)tuidang\\.net$\n(^|\\.)tuidang\\.org$\n(^|\\.)tuidang\\.se$\n(^|\\.)tui\\.orzdream\\.com$\n(^|\\.)tuitwit\\.com$\n(^|\\.)tumblr\\.com$\n(^|\\.)tumutanzi\\.com$\n(^|\\.)tumview\\.com$\n(^|\\.)tunein\\.com$\n(^|\\.)tunnelbear\\.com$\n(^|\\.)tunnelr\\.com$\n(^|\\.)tuo8\\.blue$\n(^|\\.)tuo8\\.cc$\n(^|\\.)tuo8\\.club$\n(^|\\.)tuo8\\.fit$\n(^|\\.)tuo8\\.hk$\n(^|\\.)tuo8\\.in$\n(^|\\.)tuo8\\.ninja$\n(^|\\.)tuo8\\.org$\n(^|\\.)tuo8\\.pw$\n(^|\\.)tuo8\\.red$\n(^|\\.)tuo8\\.space$\n(^|\\.)turansam\\.org$\n(^|\\.)turbobit\\.net$\n(^|\\.)turbohide\\.com$\n(^|\\.)turbotwitter\\.com$\n(^|\\.)turntable\\.fm$\n(^|\\.)tushycash\\.com$\n(^|\\.)tuvpn\\.com$\n(^|\\.)tuzaijidi\\.com$\n(^|\\.)tvants\\.com$\n(^|\\.)tvboxnow\\.com$\n(^|\\.)tv\\.com$\n(^|\\.)tvider\\.com$\n(^|\\.)tvmost\\.com\\.hk$\n(^|\\.)tvplayvideos\\.com$\n(^|\\.)tvunetworks\\.com$\n(^|\\.)tw01\\.org$\n(^|\\.)twaitter\\.com$\n(^|\\.)tw\\.answers\\.yahoo\\.com$\n(^|\\.)twapperkeeper\\.com$\n(^|\\.)twaud\\.io$\n(^|\\.)twavi\\.com$\n(^|\\.)twbbs\\.net\\.tw$\n(^|\\.)twbbs\\.org$\n(^|\\.)twbbs\\.tw$\n(^|\\.)tw\\.bid\\.yahoo\\.com$\n(^|\\.)tw-blog\\.com$\n(^|\\.)twblogger\\.com$\n(^|\\.)tweepguide\\.com$\n(^|\\.)tweeplike\\.me$\n(^|\\.)tweepmag\\.com$\n(^|\\.)tweepml\\.org$\n(^|\\.)tweetbackup\\.com$\n(^|\\.)tweetboard\\.com$\n(^|\\.)tweetboner\\.biz$\n(^|\\.)tweetcs\\.com$\n(^|\\.)tweetdeck\\.com$\n(^|\\.)tweetedtimes\\.com$\n(^|\\.)tweetmylast\\.fm$\n(^|\\.)tweetphoto\\.com$\n(^|\\.)tweetrans\\.com$\n(^|\\.)tweetree\\.com$\n(^|\\.)tweets\\.seraph\\.me$\n(^|\\.)tweettunnel\\.com$\n(^|\\.)tweetwally\\.com$\n(^|\\.)tweetymail\\.com$\n(^|\\.)tweez\\.net$\n(^|\\.)twelve\\.today$\n(^|\\.)twerkingbutt\\.com$\n(^|\\.)twftp\\.org$\n(^|\\.)tw\\.gigacircle\\.com$\n(^|\\.)twgreatdaily\\.com$\n(^|\\.)tw\\.hao123\\.com$\n(^|\\.)twibase\\.com$\n(^|\\.)twibble\\.de$\n(^|\\.)twibbon\\.com$\n(^|\\.)twibs\\.com$\n(^|\\.)twicountry\\.org$\n(^|\\.)twicsy\\.com$\n(^|\\.)twiends\\.com$\n(^|\\.)twifan\\.com$\n(^|\\.)twiffo\\.com$\n(^|\\.)twiggit\\.org$\n(^|\\.)twilightsex\\.com$\n(^|\\.)twilog\\.org$\n(^|\\.)twimbow\\.com$\n(^|\\.)twimg\\.com$\n(^|\\.)twimg\\.edgesuite\\.net$\n(^|\\.)twindexx\\.com$\n(^|\\.)twip\\.me$\n(^|\\.)twipple\\.jp$\n(^|\\.)tw\\.iqiyi\\.com$\n(^|\\.)twishort\\.com$\n(^|\\.)twistar\\.cc$\n(^|\\.)twisterio\\.com$\n(^|\\.)twister\\.net\\.co$\n(^|\\.)twisternow\\.com$\n(^|\\.)twistory\\.net$\n(^|\\.)twit2d\\.com$\n(^|\\.)twitbrowser\\.net$\n(^|\\.)twitcause\\.com$\n(^|\\.)twitchcdn\\.net$\n(^|\\.)twitch\\.tv$\n(^|\\.)twitgether\\.com$\n(^|\\.)twitgoo\\.com$\n(^|\\.)twitiq\\.com$\n(^|\\.)twitlonger\\.com$\n(^|\\.)twitmania\\.com$\n(^|\\.)twitoaster\\.com$\n(^|\\.)twitonmsn\\.com$\n(^|\\.)twitpic\\.com$\n(^|\\.)twitstat\\.com$\n(^|\\.)twittbot\\.net$\n(^|\\.)twitter4j\\.org$\n(^|\\.)twitter\\.com$\n(^|\\.)twittercounter\\.com$\n(^|\\.)twitterfeed\\.com$\n(^|\\.)twittergadget\\.com$\n(^|\\.)twitter\\.jp$\n(^|\\.)twitterkr\\.com$\n(^|\\.)twittermail\\.com$\n(^|\\.)twitterrific\\.com$\n(^|\\.)twittertim\\.es$\n(^|\\.)twitthat\\.com$\n(^|\\.)twitturk\\.com$\n(^|\\.)twitturly\\.com$\n(^|\\.)twitvid\\.com$\n(^|\\.)twitzap\\.com$\n(^|\\.)twiyia\\.com$\n(^|\\.)tw\\.jiepang\\.com$\n(^|\\.)tw\\.knowledge\\.yahoo\\.com$\n(^|\\.)tw\\.mall\\.yahoo\\.com$\n(^|\\.)tw\\.mobi\\.yahoo\\.com$\n(^|\\.)tw\\.money\\.yahoo\\.com$\n(^|\\.)tw\\.myblog\\.yahoo\\.com$\n(^|\\.)tw\\.news\\.yahoo\\.com$\n(^|\\.)twnorth\\.org\\.tw$\n(^|\\.)tw-npo\\.org$\n(^|\\.)twskype\\.com$\n(^|\\.)twstar\\.net$\n(^|\\.)tw\\.streetvoice\\.com$\n(^|\\.)twtkr\\.com$\n(^|\\.)tw\\.tomonews\\.net$\n(^|\\.)twtr2src\\.ogaoga\\.org$\n(^|\\.)twtrland\\.com$\n(^|\\.)twt\\.tl$\n(^|\\.)twttr\\.com$\n(^|\\.)twurl\\.nl$\n(^|\\.)tw\\.voa\\.mobi$\n(^|\\.)twyac\\.org$\n(^|\\.)tw\\.yahoo\\.com$\n(^|\\.)txxx\\.com$\n(^|\\.)tycool\\.com$\n(^|\\.)typepad\\.com$\n(^|\\.)u15\\.info$\n(^|\\.)u9un\\.com$\n(^|\\.)ub0\\.cc$\n(^|\\.)ubddns\\.org$\n(^|\\.)uberproxy\\.net$\n(^|\\.)ucdc1998\\.org$\n(^|\\.)uchicago\\.edu$\n(^|\\.)uc-japan\\.org$\n(^|\\.)uderzo\\.it$\n(^|\\.)udnbkk\\.com$\n(^|\\.)udn\\.com$\n(^|\\.)udn\\.com\\.tw$\n(^|\\.)uforadio\\.com\\.tw$\n(^|\\.)ufreevpn\\.com$\n(^|\\.)ugo\\.com$\n(^|\\.)uhdwallpapers\\.org$\n(^|\\.)uhrp\\.org$\n(^|\\.)uighurbiz\\.net$\n(^|\\.)uighur\\.narod\\.ru$\n(^|\\.)uighur\\.nl$\n(^|\\.)ukcdp\\.co\\.uk$\n(^|\\.)ukliferadio\\.co\\.uk$\n(^|\\.)uku\\.im$\n(^|\\.)ulike\\.net$\n(^|\\.)ulop\\.net$\n(^|\\.)ultravpn\\.fr$\n(^|\\.)ultraxs\\.com$\n(^|\\.)umich\\.edu$\n(^|\\.)unblock\\.cn\\.com$\n(^|\\.)unblockdmm\\.com$\n(^|\\.)unblocker\\.yt$\n(^|\\.)unblocksit\\.es$\n(^|\\.)unblock-us\\.com$\n(^|\\.)uncyclomedia\\.org$\n(^|\\.)uncyclopedia\\.hk$\n(^|\\.)uncyclopedia\\.tw$\n(^|\\.)underwoodammo\\.com$\n(^|\\.)unholyknight\\.com$\n(^|\\.)uni\\.cc$\n(^|\\.)unification\\.net$\n(^|\\.)unification\\.org\\.tw$\n(^|\\.)unirule\\.cloud$\n(^|\\.)unitedsocialpress\\.com$\n(^|\\.)unix100\\.com$\n(^|\\.)unknownspace\\.org$\n(^|\\.)unodedos\\.com$\n(^|\\.)unpo\\.org$\n(^|\\.)unseen\\.is$\n(^|\\.)untraceable\\.us$\n(^|\\.)uocn\\.org$\n(^|\\.)upcoming\\.yahoo\\.com$\n(^|\\.)updates\\.tdesktop\\.com$\n(^|\\.)upholdjustice\\.org$\n(^|\\.)upload4u\\.info$\n(^|\\.)uploaded\\.net$\n(^|\\.)uploaded\\.to$\n(^|\\.)uploadstation\\.com$\n(^|\\.)upmedia\\.mg$\n(^|\\.)upornia\\.com$\n(^|\\.)uproxy\\.org$\n(^|\\.)upwill\\.org$\n(^|\\.)ur7s\\.com$\n(^|\\.)uraban\\.me$\n(^|\\.)urbansurvival\\.com$\n(^|\\.)urchin\\.com$\n(^|\\.)urlborg\\.com$\n(^|\\.)urlparser\\.com$\n(^|\\.)usacn\\.com$\n(^|\\.)usaip\\.eu$\n(^|\\.)userapi\\.nytlog\\.com$\n(^|\\.)users\\.skynet\\.be$\n(^|\\.)usfk\\.mil$\n(^|\\.)ushuarencity\\.echainhost\\.com$\n(^|\\.)usinfo\\.state\\.gov$\n(^|\\.)usma\\.edu$\n(^|\\.)usmc\\.mil$\n(^|\\.)usmgtcg\\.ning\\.com$\n(^|\\.)usno\\.navy\\.mil$\n(^|\\.)usocctn\\.com$\n(^|\\.)us\\.to$\n(^|\\.)ustream\\.tv$\n(^|\\.)usunitednews\\.com$\n(^|\\.)usus\\.cc$\n(^|\\.)utopianpal\\.com$\n(^|\\.)uu-gg\\.com$\n(^|\\.)uukanshu\\.com$\n(^|\\.)uvwxyz\\.xyz$\n(^|\\.)uwants\\.com$\n(^|\\.)uwants\\.net$\n(^|\\.)uyghuramerican\\.org$\n(^|\\.)uyghurcanadiansociety\\.org$\n(^|\\.)uyghurcongress\\.org$\n(^|\\.)uyghur\\.co\\.uk$\n(^|\\.)uyghurensemble\\.co\\.uk$\n(^|\\.)uyghur-j\\.org$\n(^|\\.)uyghurpen\\.org$\n(^|\\.)uyghurpress\\.com$\n(^|\\.)uyghurstudies\\.org$\n(^|\\.)uygur\\.fc2web\\.com$\n(^|\\.)uygur\\.org$\n(^|\\.)uymaarip\\.com$\n(^|\\.)v2ex\\.com$\n(^|\\.)v2ray\\.com$\n(^|\\.)van001\\.com$\n(^|\\.)van698\\.com$\n(^|\\.)vanemu\\.cn$\n(^|\\.)vanilla-jp\\.com$\n(^|\\.)vanpeople\\.com$\n(^|\\.)vansky\\.com$\n(^|\\.)vaticannews\\.va$\n(^|\\.)vatn\\.org$\n(^|\\.)vcfbuilder\\.org$\n(^|\\.)vcf-online\\.org$\n(^|\\.)vds\\.rightster\\.com$\n(^|\\.)vegasred\\.com$\n(^|\\.)vegas\\.williamhill\\.com$\n(^|\\.)velkaepocha\\.sk$\n(^|\\.)venbbs\\.com$\n(^|\\.)venchina\\.com$\n(^|\\.)venetianmacao\\.com$\n(^|\\.)ventureswell\\.com$\n(^|\\.)veoh\\.com$\n(^|\\.)vermonttibet\\.org$\n(^|\\.)versavpn\\.com$\n(^|\\.)verybs\\.com$\n(^|\\.)vevo\\.com$\n(^|\\.)vft\\.com\\.tw$\n(^|\\.)viber\\.com$\n(^|\\.)vica\\.info$\n(^|\\.)victimsofcommunism\\.org$\n(^|\\.)vidble\\.com$\n(^|\\.)video\\.aol\\.ca$\n(^|\\.)video\\.aol\\.com$\n(^|\\.)video\\.aol\\.co\\.uk$\n(^|\\.)video\\.ap\\.org$\n(^|\\.)videobam\\.com$\n(^|\\.)videodetective\\.com$\n(^|\\.)video\\.fdbox\\.com$\n(^|\\.)video\\.foxbusiness\\.com$\n(^|\\.)videomega\\.tv$\n(^|\\.)videomo\\.com$\n(^|\\.)video\\.pbs\\.org$\n(^|\\.)videopediaworld\\.com$\n(^|\\.)videopress\\.com$\n(^|\\.)video\\.yahoo\\.com$\n(^|\\.)vidinfo\\.org$\n(^|\\.)vid\\.me$\n(^|\\.)vietdaikynguyen\\.com$\n(^|\\.)vijayatemple\\.org$\n(^|\\.)vimeo\\.com$\n(^|\\.)vimperator\\.org$\n(^|\\.)vincnd\\.com$\n(^|\\.)vine\\.co$\n(^|\\.)vinniev\\.com$\n(^|\\.)vip-enterprise\\.com$\n(^|\\.)virtualrealporn\\.com$\n(^|\\.)visibletweets\\.com$\n(^|\\.)vital247\\.org$\n(^|\\.)viu\\.com$\n(^|\\.)viu\\.tv$\n(^|\\.)vivahentai4u\\.net$\n(^|\\.)vivatube\\.com$\n(^|\\.)vivthomas\\.com$\n(^|\\.)vizvaz\\.com$\n(^|\\.)vjav\\.com$\n(^|\\.)vjmedia\\.com\\.hk$\n(^|\\.)vllcs\\.org$\n(^|\\.)vlog\\.xuite\\.net$\n(^|\\.)vmixcore\\.com$\n(^|\\.)vmpsoft\\.com$\n(^|\\.)vnet\\.link$\n(^|\\.)vn\\.hao123\\.com$\n(^|\\.)voa-11\\.akacast\\.akamaistream\\.net$\n(^|\\.)voacantonese\\.com$\n(^|\\.)voachineseblog\\.com$\n(^|\\.)voachinese\\.com$\n(^|\\.)voagd\\.com$\n(^|\\.)voanews\\.com$\n(^|\\.)voatibetan\\.com$\n(^|\\.)voatibetanenglish\\.com$\n(^|\\.)vocativ\\.com$\n(^|\\.)vocn\\.tv$\n(^|\\.)vod-abematv\\.akamaized\\.net$\n(^|\\.)vod\\.wwe\\.com$\n(^|\\.)vot\\.org$\n(^|\\.)vovo2000\\.com$\n(^|\\.)voxer\\.com$\n(^|\\.)voy\\.com$\n(^|\\.)vpn4all\\.com$\n(^|\\.)vpn\\.ac$\n(^|\\.)vpnaccount\\.org$\n(^|\\.)vpnaccounts\\.com$\n(^|\\.)vpnbook\\.com$\n(^|\\.)vpn\\.cjb\\.net$\n(^|\\.)vpn\\.cmu\\.edu$\n(^|\\.)vpncomparison\\.org$\n(^|\\.)vpncoupons\\.com$\n(^|\\.)vpncup\\.com$\n(^|\\.)vpndada\\.com$\n(^|\\.)vpnfan\\.com$\n(^|\\.)vpnfire\\.com$\n(^|\\.)vpnfires\\.biz$\n(^|\\.)vpnforgame\\.net$\n(^|\\.)vpngate\\.jp$\n(^|\\.)vpngate\\.net$\n(^|\\.)vpngratis\\.net$\n(^|\\.)vpnhq\\.com$\n(^|\\.)vpninja\\.net$\n(^|\\.)vpnintouch\\.com$\n(^|\\.)vpnintouch\\.net$\n(^|\\.)vpnjack\\.com$\n(^|\\.)vpnmaster\\.com$\n(^|\\.)vpnmentor\\.com$\n(^|\\.)vpnpick\\.com$\n(^|\\.)vpnpop\\.com$\n(^|\\.)vpnpronet\\.com$\n(^|\\.)vpnreactor\\.com$\n(^|\\.)vpnreviewz\\.com$\n(^|\\.)vpnsecure\\.me$\n(^|\\.)vpnshazam\\.com$\n(^|\\.)vpnshieldapp\\.com$\n(^|\\.)vpnsp\\.com$\n(^|\\.)vpn\\.sv\\.cmu\\.edu$\n(^|\\.)vpntraffic\\.com$\n(^|\\.)vpntunnel\\.com$\n(^|\\.)vpnuk\\.info$\n(^|\\.)vpnunlimitedapp\\.com$\n(^|\\.)vpnvip\\.com$\n(^|\\.)vpnworldwide\\.com$\n(^|\\.)vporn\\.com$\n(^|\\.)vpser\\.net$\n(^|\\.)vraiesagesse\\.net$\n(^|\\.)vrmtr\\.com$\n(^|\\.)vrsmash\\.com$\n(^|\\.)vtunnel\\.com$\n(^|\\.)vuku\\.cc$\n(^|\\.)vultryhw\\.com$\n(^|\\.)w3schools\\.com$\n(^|\\.)waffle1999\\.com$\n(^|\\.)wahas\\.com$\n(^|\\.)waigaobu\\.com$\n(^|\\.)waikeung\\.org$\n(^|\\.)wailaike\\.net$\n(^|\\.)waiwaier\\.com$\n(^|\\.)wallmama\\.com$\n(^|\\.)wallornot\\.org$\n(^|\\.)wallpapercasa\\.com$\n(^|\\.)wallproxy\\.com$\n(^|\\.)waltermartin\\.com$\n(^|\\.)waltermartin\\.org$\n(^|\\.)wanderinghorse\\.net$\n(^|\\.)wangafu\\.net$\n(^|\\.)wangjinbo\\.org$\n(^|\\.)wanglixiong\\.com$\n(^|\\.)wango\\.org$\n(^|\\.)wangruoshui\\.net$\n(^|\\.)want-daily\\.com$\n(^|\\.)wanz-factory\\.com$\n(^|\\.)wapedia\\.mobi$\n(^|\\.)warbler\\.iconfactory\\.net$\n(^|\\.)waselpro\\.com$\n(^|\\.)washeng\\.net$\n(^|\\.)washingtonpost\\.com$\n(^|\\.)watch8x\\.com$\n(^|\\.)watchinese\\.com$\n(^|\\.)watchmygf\\.net$\n(^|\\.)wattpad\\.com$\n(^|\\.)waveprotocol\\.org$\n(^|\\.)wav\\.tv$\n(^|\\.)waymo\\.com$\n(^|\\.)wda\\.gov\\.tw$\n(^|\\.)wdf5\\.com$\n(^|\\.)wearehairy\\.com$\n(^|\\.)wearn\\.com$\n(^|\\.)web2project\\.net$\n(^|\\.)webbang\\.net$\n(^|\\.)web\\.dev$\n(^|\\.)webevader\\.org$\n(^|\\.)webfreer\\.com$\n(^|\\.)webjb\\.org$\n(^|\\.)weblagu\\.com$\n(^|\\.)webmproject\\.org$\n(^|\\.)webrtc\\.org$\n(^|\\.)webrush\\.net$\n(^|\\.)website\\.informer\\.com$\n(^|\\.)websitepulse\\.com$\n(^|\\.)webs-tv\\.net$\n(^|\\.)webwarper\\.net$\n(^|\\.)webworkerdaily\\.com$\n(^|\\.)weekmag\\.info$\n(^|\\.)wefightcensorship\\.org$\n(^|\\.)wefong\\.com$\n(^|\\.)wego\\.here\\.com$\n(^|\\.)weiboleak\\.com$\n(^|\\.)weiboscope\\.jmsc\\.hku\\.hk$\n(^|\\.)weihuo\\.org$\n(^|\\.)weijingsheng\\.org$\n(^|\\.)weiming\\.info$\n(^|\\.)weiquanwang\\.org$\n(^|\\.)weisuo\\.ws$\n(^|\\.)welovecock\\.com$\n(^|\\.)wemigrate\\.org$\n(^|\\.)wengewang\\.com$\n(^|\\.)wengewang\\.org$\n(^|\\.)wenhui\\.ch$\n(^|\\.)wenxuecity\\.com$\n(^|\\.)wenyunchao\\.com$\n(^|\\.)wenzhao\\.ca$\n(^|\\.)westca\\.com$\n(^|\\.)westernshugdensociety\\.org$\n(^|\\.)westernwolves\\.com$\n(^|\\.)westkit\\.net$\n(^|\\.)westpoint\\.edu$\n(^|\\.)wetplace\\.com$\n(^|\\.)wetpussygames\\.com$\n(^|\\.)wexiaobo\\.org$\n(^|\\.)wezhiyong\\.org$\n(^|\\.)wezone\\.net$\n(^|\\.)wforum\\.com$\n(^|\\.)wha\\.la$\n(^|\\.)whatblocked\\.com$\n(^|\\.)whatbrowser\\.org$\n(^|\\.)whatsapp\\.com$\n(^|\\.)whatsapp\\.net$\n(^|\\.)whatsonweibo\\.com$\n(^|\\.)wheatseeds\\.org$\n(^|\\.)wheelockslatin\\.com$\n(^|\\.)whereiswerner\\.com$\n(^|\\.)wheretowatch\\.com$\n(^|\\.)whippedass\\.com$\n(^|\\.)whitebear\\.freebearblog\\.org$\n(^|\\.)whodns\\.xyz$\n(^|\\.)whoer\\.net$\n(^|\\.)whotalking\\.com$\n(^|\\.)whylover\\.com$\n(^|\\.)whyx\\.org$\n(^|\\.)w\\.idaiwan\\.com$\n(^|\\.)widevine\\.com$\n(^|\\.)wikaba\\.com$\n(^|\\.)wiki\\.cnitter\\.com$\n(^|\\.)wiki\\.esu\\.im$\n(^|\\.)wiki\\.gamerp\\.jp$\n(^|\\.)wiki\\.jqueryui\\.com$\n(^|\\.)wiki\\.keso\\.cn$\n(^|\\.)wikileaks\\.ch$\n(^|\\.)wikileaks\\.com$\n(^|\\.)wikileaks\\.de$\n(^|\\.)wikileaks\\.eu$\n(^|\\.)wikileaks-forum\\.com$\n(^|\\.)wikileaks\\.lu$\n(^|\\.)wikileaks\\.org$\n(^|\\.)wikileaks\\.pl$\n(^|\\.)wikilivres\\.info$\n(^|\\.)wikimapia\\.org$\n(^|\\.)wiki\\.moegirl\\.org$\n(^|\\.)wiki\\.oauth\\.net$\n(^|\\.)wikipedia\\.org$\n(^|\\.)wiki\\.phonegap\\.com$\n(^|\\.)wikiwiki\\.jp$\n(^|\\.)wildammo\\.com$\n(^|\\.)williamhill\\.com$\n(^|\\.)willw\\.net$\n(^|\\.)windowsphoneme\\.com$\n(^|\\.)windscribe\\.com$\n(^|\\.)wingamestore\\.com$\n(^|\\.)wingy\\.site$\n(^|\\.)winning11\\.com$\n(^|\\.)winwhispers\\.info$\n(^|\\.)wire\\.com$\n(^|\\.)wiredbytes\\.com$\n(^|\\.)wiredpen\\.com$\n(^|\\.)wisdompubs\\.org$\n(^|\\.)wisevid\\.com$\n(^|\\.)withgoogle\\.com$\n(^|\\.)withyoutube\\.com$\n(^|\\.)witnessleeteaching\\.com$\n(^|\\.)witopia\\.net$\n(^|\\.)wizcrafts\\.net$\n(^|\\.)wjbk\\.org$\n(^|\\.)wlcnew\\.jigsy\\.com$\n(^|\\.)wlx\\.sowiki\\.net$\n(^|\\.)wnacg\\.com$\n(^|\\.)wnacg\\.org$\n(^|\\.)wn\\.com$\n(^|\\.)wo3ttt\\.wordpress\\.com$\n(^|\\.)woeser\\.com$\n(^|\\.)woesermiddle-way\\.net$\n(^|\\.)wokar\\.org$\n(^|\\.)wolfax\\.com$\n(^|\\.)woolyss\\.com$\n(^|\\.)woopie\\.jp$\n(^|\\.)woopie\\.tv$\n(^|\\.)wordpress\\.com$\n(^|\\.)workatruna\\.com$\n(^|\\.)workerdemo\\.org\\.hk$\n(^|\\.)workerempowerment\\.org$\n(^|\\.)workersthebig\\.net$\n(^|\\.)worldcat\\.org$\n(^|\\.)worldjournal\\.com$\n(^|\\.)worldvpn\\.net$\n(^|\\.)wo\\.tc$\n(^|\\.)wow\\.com$\n(^|\\.)wowgirls\\.com$\n(^|\\.)wowlegacy\\.ml$\n(^|\\.)wow-life\\.net$\n(^|\\.)wowporn\\.com$\n(^|\\.)wowrk\\.com$\n(^|\\.)woxinghuiguo\\.com$\n(^|\\.)woyaolian\\.org$\n(^|\\.)wozy\\.in$\n(^|\\.)wp\\.com$\n(^|\\.)wpoforum\\.com$\n(^|\\.)wqyd\\.org$\n(^|\\.)wrchina\\.org$\n(^|\\.)wretch\\.cc$\n(^|\\.)writer\\.zoho\\.com$\n(^|\\.)wsgzao\\.github\\.io$\n(^|\\.)wsj\\.com$\n(^|\\.)wsjhk\\.com$\n(^|\\.)wsj\\.net$\n(^|\\.)wtbn\\.org$\n(^|\\.)wtfpeople\\.com$\n(^|\\.)wuerkaixi\\.com$\n(^|\\.)wufafangwen\\.com$\n(^|\\.)wufi\\.org\\.tw$\n(^|\\.)wuguoguang\\.com$\n(^|\\.)wujieliulan\\.com$\n(^|\\.)wujie\\.net$\n(^|\\.)wukangrui\\.net$\n(^|\\.)wuw\\.red$\n(^|\\.)wuyanblog\\.com$\n(^|\\.)wwitv\\.com$\n(^|\\.)www1\\.american\\.edu$\n(^|\\.)www1\\.biz$\n(^|\\.)www2\\.ohchr\\.org$\n(^|\\.)www2\\.rocketbbs\\.com$\n(^|\\.)www\\.abclite\\.net$\n(^|\\.)www\\.ajsands\\.com$\n(^|\\.)www\\.americorps\\.gov$\n(^|\\.)www\\.antd\\.org$\n(^|\\.)www\\.aolnews\\.com$\n(^|\\.)www\\.businessinsider\\.com\\.au$\n(^|\\.)www\\.citizenlab\\.org$\n(^|\\.)www\\.cmoinc\\.org$\n(^|\\.)www\\.cool18\\.com$\n(^|\\.)www\\.dmm\\.com$\n(^|\\.)www\\.dwheeler\\.com$\n(^|\\.)www\\.eastturkistan\\.net$\n(^|\\.)www\\.gmiddle\\.com$\n(^|\\.)www\\.gmiddle\\.net$\n(^|\\.)wwwhost\\.biz$\n(^|\\.)www\\.hustlercash\\.com$\n(^|\\.)www\\.idlcoyote\\.com$\n(^|\\.)www\\.imdb\\.com$\n(^|\\.)www\\.kindleren\\.com$\n(^|\\.)www\\.klip\\.me$\n(^|\\.)www\\.lamenhu\\.com$\n(^|\\.)www\\.lib\\.virginia\\.edu$\n(^|\\.)www\\.linksalpha\\.com$\n(^|\\.)www\\.metro\\.taipei$\n(^|\\.)www\\.monlamit\\.org$\n(^|\\.)www\\.moztw\\.org$\n(^|\\.)www\\.m-sport\\.co\\.uk$\n(^|\\.)www\\.nbc\\.com$\n(^|\\.)www\\.orchidbbs\\.com$\n(^|\\.)www\\.owind\\.com$\n(^|\\.)www\\.oxid\\.it$\n(^|\\.)www\\.powerpointninja\\.com$\n(^|\\.)www\\.s4miniarchive\\.com$\n(^|\\.)www\\.sciencemag\\.org$\n(^|\\.)www\\.shadowsocks\\.com$\n(^|\\.)www\\.shwchurch\\.org$\n(^|\\.)www\\.skype\\.com$\n(^|\\.)www\\.tablesgenerator\\.com$\n(^|\\.)www\\.taiwanonline\\.cc$\n(^|\\.)www\\.taup\\.org\\.tw$\n(^|\\.)www\\.thechinastory\\.org$\n(^|\\.)www\\.wangruowang\\.org$\n(^|\\.)www\\.wan-press\\.org$\n(^|\\.)www\\.websnapr\\.com$\n(^|\\.)www\\.zensur\\.freerk\\.com$\n(^|\\.)wzyboy\\.im$\n(^|\\.)x1949x\\.com$\n(^|\\.)x24hr\\.com$\n(^|\\.)x365x\\.com$\n(^|\\.)xanga\\.com$\n(^|\\.)x-art\\.com$\n(^|\\.)xa\\.yimg\\.com$\n(^|\\.)xbabe\\.com$\n(^|\\.)x-berry\\.com$\n(^|\\.)xbookcn\\.com$\n(^|\\.)xbtce\\.com$\n(^|\\.)xcafe\\.in$\n(^|\\.)xcity\\.jp$\n(^|\\.)x\\.company$\n(^|\\.)xcritic\\.com$\n(^|\\.)xda-developers\\.com$\n(^|\\.)xerotica\\.com$\n(^|\\.)xfinity\\.com$\n(^|\\.)xfm\\.pp\\.ru$\n(^|\\.)xgmyd\\.com$\n(^|\\.)xhamster\\.com$\n(^|\\.)xianba\\.net$\n(^|\\.)xianchawang\\.net$\n(^|\\.)xianjian\\.tw$\n(^|\\.)xianqiao\\.net$\n(^|\\.)xiaobaiwu\\.com$\n(^|\\.)xiaochuncnjp\\.com$\n(^|\\.)xiaod\\.in$\n(^|\\.)xiaohexie\\.com$\n(^|\\.)xiaolan\\.me$\n(^|\\.)xiaoma\\.org$\n(^|\\.)xiezhua\\.com$\n(^|\\.)xihua\\.es$\n(^|\\.)xijie\\.wordpress\\.com$\n(^|\\.)xing\\.com$\n(^|\\.)xinhuanet\\.org$\n(^|\\.)xinmiao\\.com\\.hk$\n(^|\\.)xinqimeng\\.over-blog\\.com$\n(^|\\.)xinsheng\\.net$\n(^|\\.)xinshijue\\.com$\n(^|\\.)xinyubbs\\.net$\n(^|\\.)xiongpian\\.com$\n(^|\\.)xiuren\\.org$\n(^|\\.)xizang-zhiye\\.org$\n(^|\\.)xjp\\.cc$\n(^|\\.)xjtravelguide\\.com$\n(^|\\.)xkiwi\\.tk$\n(^|\\.)xlfmtalk\\.com$\n(^|\\.)xlfmwz\\.info$\n(^|\\.)xm\\.com$\n(^|\\.)xml-training-guide\\.com$\n(^|\\.)xmovies\\.com$\n(^|\\.)xn--4gq171p\\.com$\n(^|\\.)xn--czq75pvv1aj5c\\.org$\n(^|\\.)xn--i2ru8q2qg\\.com$\n(^|\\.)xn--ngstr-lra8j\\.com$\n(^|\\.)xn--oiq\\.cc$\n(^|\\.)xn--p8j9a0d9c9a\\.xn--q9jyb4c$\n(^|\\.)xnxx\\.com$\n(^|\\.)xpdo\\.net$\n(^|\\.)xpud\\.org$\n(^|\\.)xrentdvd\\.com$\n(^|\\.)xskywalker\\.com$\n(^|\\.)xskywalker\\.net$\n(^|\\.)xtube\\.com$\n(^|\\.)xuchao\\.net$\n(^|\\.)xuchao\\.org$\n(^|\\.)xuehua\\.us$\n(^|\\.)xuzhiyong\\.net$\n(^|\\.)xvideo\\.cc$\n(^|\\.)xvideos\\.com$\n(^|\\.)xvideos\\.es$\n(^|\\.)x-wall\\.org$\n(^|\\.)xxbbx\\.com$\n(^|\\.)xxlmovies\\.com$\n(^|\\.)xxuz\\.com$\n(^|\\.)xxx\\.com$\n(^|\\.)xxxfuckmom\\.com$\n(^|\\.)xxxx\\.com\\.au$\n(^|\\.)xxx\\.xxx$\n(^|\\.)xxxy\\.biz$\n(^|\\.)xxxy\\.info$\n(^|\\.)xxxymovies\\.com$\n(^|\\.)xysblogs\\.org$\n(^|\\.)xys\\.dxiong\\.com$\n(^|\\.)xys\\.org$\n(^|\\.)xyy69\\.com$\n(^|\\.)xyy69\\.info$\n(^|\\.)yahoo\\.com\\.hk$\n(^|\\.)yakbutterblues\\.com$\n(^|\\.)yam\\.com$\n(^|\\.)yam\\.org\\.tw$\n(^|\\.)yanghengjun\\.com$\n(^|\\.)yangjianli\\.com$\n(^|\\.)yasni\\.co\\.uk$\n(^|\\.)yayabay\\.com$\n(^|\\.)ydy\\.com$\n(^|\\.)yeahteentube\\.com$\n(^|\\.)yecl\\.net$\n(^|\\.)yeelou\\.com$\n(^|\\.)yeeyi\\.com$\n(^|\\.)yegle\\.net$\n(^|\\.)yes123\\.com\\.tw$\n(^|\\.)yesasia\\.com$\n(^|\\.)yesasia\\.com\\.hk$\n(^|\\.)yes-news\\.com$\n(^|\\.)yespornplease\\.com$\n(^|\\.)yes\\.xxx$\n(^|\\.)yeyeclub\\.com$\n(^|\\.)ygto\\.com$\n(^|\\.)yhcw\\.net$\n(^|\\.)yibada\\.com$\n(^|\\.)yibaochina\\.com$\n(^|\\.)yidio\\.com$\n(^|\\.)yigeni\\.com$\n(^|\\.)yilubbs\\.com$\n(^|\\.)yingsuoss\\.com$\n(^|\\.)yinlei\\.org$\n(^|\\.)yipub\\.com$\n(^|\\.)yizhihongxing\\.com$\n(^|\\.)yobit\\.net$\n(^|\\.)yobt\\.com$\n(^|\\.)yobt\\.tv$\n(^|\\.)yogichen\\.org$\n(^|\\.)yolasite\\.com$\n(^|\\.)yomiuri\\.co\\.jp$\n(^|\\.)yong\\.hu$\n(^|\\.)yorkbbs\\.ca$\n(^|\\.)youdontcare\\.com$\n(^|\\.)you-get\\.org$\n(^|\\.)youjizz\\.com$\n(^|\\.)youmaker\\.com$\n(^|\\.)youngpornvideos\\.com$\n(^|\\.)youngspiration\\.hk$\n(^|\\.)youpai\\.org$\n(^|\\.)youporn\\.com$\n(^|\\.)youporngay\\.com$\n(^|\\.)yourepeat\\.com$\n(^|\\.)your-freedom\\.net$\n(^|\\.)yourlisten\\.com$\n(^|\\.)yourlust\\.com$\n(^|\\.)yourprivatevpn\\.com$\n(^|\\.)yourtrap\\.com$\n(^|\\.)yousendit\\.com$\n(^|\\.)youshun12\\.com$\n(^|\\.)youthnetradio\\.org$\n(^|\\.)youtu\\.be$\n(^|\\.)youtubecn\\.com$\n(^|\\.)youtube\\.com$\n(^|\\.)youtubeeducation\\.com$\n(^|\\.)youtubegaming\\.com$\n(^|\\.)youtube-nocookie\\.com$\n(^|\\.)youversion\\.com$\n(^|\\.)youwin\\.com$\n(^|\\.)youxu\\.info$\n(^|\\.)yt\\.be$\n(^|\\.)ytht\\.net$\n(^|\\.)ytimg\\.com$\n(^|\\.)ytn\\.co\\.kr$\n(^|\\.)yuanming\\.net$\n(^|\\.)yuanzhengtang\\.org$\n(^|\\.)yulghun\\.com$\n(^|\\.)yunchao\\.net$\n(^|\\.)yuntipub\\.com$\n(^|\\.)yuvutu\\.com$\n(^|\\.)yvesgeleyn\\.com$\n(^|\\.)ywpw\\.com$\n(^|\\.)yx51\\.net$\n(^|\\.)yyii\\.org$\n(^|\\.)yzzk\\.com$\n(^|\\.)zacebook\\.com$\n(^|\\.)zalmos\\.com$\n(^|\\.)zannel\\.com$\n(^|\\.)zaobao\\.com$\n(^|\\.)zaobao\\.com\\.sg$\n(^|\\.)zaozon\\.com$\n(^|\\.)zapto\\.org$\n(^|\\.)zattoo\\.com$\n(^|\\.)zb\\.com$\n(^|\\.)zdnet\\.com\\.tw$\n(^|\\.)zello\\.com$\n(^|\\.)zengjinyan\\.org$\n(^|\\.)zenmate\\.com$\n(^|\\.)zenmate\\.com\\.ru$\n(^|\\.)zeronet\\.io$\n(^|\\.)zeutch\\.com$\n(^|\\.)zfreet\\.com$\n(^|\\.)zgsddh\\.com$\n(^|\\.)zgzcjj\\.net$\n(^|\\.)zhanbin\\.net$\n(^|\\.)zhangboli\\.net$\n(^|\\.)zhangtianliang\\.com$\n(^|\\.)zhanlve\\.org$\n(^|\\.)zhao\\.1984\\.city$\n(^|\\.)zhao\\.jinhai\\.de$\n(^|\\.)zh\\.bitterwinter\\.org$\n(^|\\.)zh\\.ecdm\\.wikia\\.com$\n(^|\\.)zhenghui\\.org$\n(^|\\.)zhengjian\\.org$\n(^|\\.)zhengwunet\\.org$\n(^|\\.)zhenlibu1984\\.com$\n(^|\\.)zhenlibu\\.info$\n(^|\\.)zhenxiang\\.biz$\n(^|\\.)zhinengluyou\\.com$\n(^|\\.)zhongguo\\.ca$\n(^|\\.)zhongguorenquan\\.org$\n(^|\\.)zhongguotese\\.net$\n(^|\\.)zhongmeng\\.org$\n(^|\\.)zhoushuguang\\.com$\n(^|\\.)zh\\.pokerstrategy\\.com$\n(^|\\.)zh\\.pttpedia\\.wikia\\.com$\n(^|\\.)zhreader\\.com$\n(^|\\.)zhuangbi\\.me$\n(^|\\.)zhuanxing\\.cn$\n(^|\\.)zhuatieba\\.com$\n(^|\\.)zhuichaguoji\\.org$\n(^|\\.)zh\\.uncyclopedia\\.wikia\\.com$\n(^|\\.)zh\\.wikinews\\.org$\n(^|\\.)zh\\.wikisource\\.org$\n(^|\\.)ziddu\\.com$\n(^|\\.)zillionk\\.com$\n(^|\\.)zim\\.vn$\n(^|\\.)zinio\\.com$\n(^|\\.)ziporn\\.com$\n(^|\\.)zippyshare\\.com$\n(^|\\.)zkaip\\.com$\n(^|\\.)zmw\\.cn$\n(^|\\.)zodgame\\.us$\n(^|\\.)zomobo\\.net$\n(^|\\.)zonaeuropa\\.com$\n(^|\\.)zonghexinwen\\.com$\n(^|\\.)zonghexinwen\\.net$\n(^|\\.)zoogvpn\\.com$\n(^|\\.)zootool\\.com$\n(^|\\.)zoozle\\.net$\n(^|\\.)zorrovpn\\.com$\n(^|\\.)zozotown\\.com$\n(^|\\.)zpn\\.im$\n(^|\\.)zspeeder\\.me$\n(^|\\.)zsrhao\\.com$\n(^|\\.)zuobiao\\.me$\n(^|\\.)zuo\\.la$\n(^|\\.)zuola\\.com$\n(^|\\.)zvereff\\.com$\n(^|\\.)zynaima\\.com$\n(^|\\.)zynamics\\.com$\n(^|\\.)zyns\\.com$\n(^|\\.)zyzc9\\.com$\n(^|\\.)zzcartoon\\.com$\n(^|\\.)zzcloud\\.me$\n(^|\\.)zzux\\.com$\n"
  },
  {
    "path": "acl/local.acl",
    "content": "[reject_all]\n\n[white_list]\n0.0.0.0/8\n10.0.0.0/8\n100.64.0.0/10\n127.0.0.0/8\n169.254.0.0/16\n172.16.0.0/12\n192.0.0.0/24\n192.0.2.0/24\n192.88.99.0/24\n192.168.0.0/16\n198.18.0.0/15\n198.51.100.0/24\n203.0.113.0/24\n224.0.0.0/4\n240.0.0.0/4\n255.255.255.255/32\n::1/128\nfc00::/7\nfe80::/10\n"
  },
  {
    "path": "acl/server_block_chn.acl",
    "content": "# All IPs listed here will be blocked while the ss-server try to outbound.\n# Only IP is allowed, *NOT* domain name.\n#\n# The IPs bellow are all IPs in CHN. It'll block ss-server to access all\n# CHN hosts by command\n# `ss-server -s:: -p 8388 -k 123456 --acl acl/server_block_chn.acl`\n\n[outbound_block_list]\n1.0.1.0/24\n1.0.2.0/23\n1.0.8.0/21\n1.0.32.0/19\n1.1.0.0/24\n1.1.2.0/23\n1.1.4.0/22\n1.1.8.0/21\n1.1.16.0/20\n1.1.32.0/19\n1.2.0.0/23\n1.2.2.0/24\n1.2.5.0/24\n1.2.6.0/23\n1.2.8.0/21\n1.2.16.0/20\n1.2.32.0/19\n1.2.64.0/18\n1.3.0.0/16\n1.4.1.0/24\n1.4.2.0/23\n1.4.4.0/22\n1.4.8.0/21\n1.4.16.0/20\n1.4.32.0/19\n1.4.64.0/18\n1.8.0.0/18\n1.8.64.0/19\n1.8.96.0/22\n1.8.100.0/23\n1.8.112.0/20\n1.8.128.0/20\n1.8.144.0/22\n1.8.148.0/23\n1.8.154.0/23\n1.8.156.0/22\n1.8.160.0/19\n1.8.192.0/19\n1.8.224.0/20\n1.8.244.0/22\n1.8.248.0/21\n1.10.0.0/21\n1.10.8.0/23\n1.10.11.0/24\n1.10.12.0/22\n1.10.16.0/20\n1.10.32.0/19\n1.10.64.0/18\n1.12.0.0/14\n1.18.128.0/24\n1.24.0.0/13\n1.45.0.0/16\n1.48.0.0/14\n1.56.0.0/13\n1.68.0.0/14\n1.80.0.0/12\n1.116.0.0/15\n1.118.1.0/24\n1.118.2.0/23\n1.118.4.0/22\n1.118.8.0/21\n1.118.16.0/20\n1.118.32.0/19\n1.118.64.0/18\n1.118.128.0/17\n1.119.0.0/16\n1.180.0.0/14\n1.184.0.0/15\n1.188.0.0/14\n1.192.0.0/13\n1.202.0.0/15\n1.204.0.0/14\n2.20.54.23/32\n8.128.0.0/10\n8.209.36.0/22\n8.209.40.0/21\n8.209.48.0/20\n8.209.192.0/18\n8.210.0.0/15\n8.212.0.0/14\n8.216.0.0/13\n14.0.0.0/21\n14.0.12.0/22\n14.1.0.0/22\n14.1.24.0/22\n14.1.108.0/22\n14.16.0.0/12\n14.102.128.0/22\n14.102.180.0/22\n14.103.0.0/16\n14.104.0.0/13\n14.112.0.0/12\n14.130.0.0/15\n14.134.0.0/15\n14.144.0.0/12\n14.192.60.0/22\n14.192.76.0/22\n14.196.0.0/15\n14.204.0.0/15\n14.208.0.0/12\n20.81.0.0/24\n20.134.160.0/20\n20.139.160.0/20\n20.249.255.0/24\n20.251.0.0/22\n23.236.64.0/25\n23.236.64.128/26\n23.236.64.192/27\n27.0.128.0/21\n27.0.160.0/21\n27.0.188.0/22\n27.0.204.0/22\n27.0.208.0/21\n27.8.0.0/13\n27.16.0.0/12\n27.34.232.0/21\n27.36.0.0/14\n27.40.0.0/13\n27.50.40.0/21\n27.50.128.0/17\n27.54.72.0/21\n27.54.152.0/21\n27.54.192.0/18\n27.98.208.0/20\n27.98.224.0/19\n27.99.128.0/17\n27.103.0.0/16\n27.106.128.0/18\n27.106.204.0/22\n27.109.32.0/19\n27.109.124.0/22\n27.112.0.0/18\n27.112.80.0/20\n27.112.112.0/21\n27.113.128.0/18\n27.115.0.0/17\n27.116.44.0/22\n27.121.72.0/21\n27.121.120.0/21\n27.128.0.0/15\n27.131.220.0/22\n27.144.0.0/16\n27.148.0.0/14\n27.152.0.0/13\n27.184.0.0/13\n27.192.0.0/11\n27.224.0.0/14\n36.0.0.0/22\n36.0.16.0/20\n36.0.32.0/19\n36.0.64.0/18\n36.0.128.0/17\n36.1.0.0/16\n36.4.0.0/14\n36.16.0.0/12\n36.32.0.0/14\n36.36.0.0/16\n36.37.0.0/19\n36.37.36.0/23\n36.37.39.0/24\n36.37.40.0/21\n36.37.48.0/20\n36.40.0.0/13\n36.48.0.0/15\n36.51.0.0/17\n36.51.128.0/18\n36.51.192.0/19\n36.51.224.0/20\n36.51.240.0/21\n36.51.248.0/22\n36.51.252.0/23\n36.56.0.0/13\n36.96.0.0/11\n36.128.0.0/10\n36.192.0.0/11\n36.248.0.0/14\n36.254.0.0/16\n36.255.116.0/22\n36.255.128.0/22\n36.255.164.0/22\n36.255.172.0/22\n36.255.176.0/22\n38.142.239.114/32\n39.0.0.0/24\n39.0.2.0/23\n39.0.4.0/22\n39.0.8.0/21\n39.0.16.0/20\n39.0.32.0/19\n39.0.64.0/18\n39.0.128.0/17\n39.64.0.0/11\n39.96.0.0/13\n39.104.0.0/14\n39.108.0.0/16\n39.109.120.0/23\n39.128.0.0/10\n40.0.176.0/20\n40.0.247.0/24\n40.0.248.0/22\n40.0.252.0/23\n40.0.255.0/24\n40.72.0.0/15\n40.77.136.112/28\n40.77.236.224/27\n40.77.254.64/27\n40.125.128.0/17\n40.126.64.0/18\n40.198.10.0/24\n40.198.16.0/21\n40.198.24.0/23\n40.251.225.0/24\n40.251.227.0/24\n42.0.0.0/22\n42.0.8.0/21\n42.0.16.0/21\n42.0.24.0/22\n42.0.32.0/19\n42.0.128.0/17\n42.1.0.0/19\n42.1.32.0/20\n42.1.48.0/21\n42.1.56.0/22\n42.4.0.0/14\n42.48.0.0/13\n42.56.0.0/14\n42.62.0.0/17\n42.62.128.0/19\n42.62.160.0/20\n42.62.180.0/22\n42.62.184.0/21\n42.63.0.0/16\n42.80.0.0/15\n42.83.64.0/20\n42.83.80.0/22\n42.83.88.0/21\n42.83.96.0/19\n42.83.128.0/23\n42.83.134.0/24\n42.83.139.0/24\n42.83.140.0/22\n42.83.144.0/20\n42.83.160.0/19\n42.83.192.0/18\n42.84.0.0/14\n42.88.0.0/13\n42.96.64.0/19\n42.96.96.0/21\n42.96.108.0/22\n42.96.112.0/20\n42.96.128.0/17\n42.97.0.0/16\n42.99.0.0/18\n42.99.64.0/19\n42.99.96.0/20\n42.99.112.0/22\n42.99.120.0/21\n42.100.0.0/14\n42.120.0.0/15\n42.122.0.0/16\n42.123.0.0/19\n42.123.36.0/22\n42.123.40.0/21\n42.123.48.0/20\n42.123.64.0/18\n42.123.128.0/17\n42.128.0.0/12\n42.156.0.0/19\n42.156.36.0/22\n42.156.40.0/21\n42.156.48.0/20\n42.156.64.0/18\n42.156.128.0/17\n42.157.0.0/21\n42.157.8.0/22\n42.157.14.0/23\n42.157.16.0/20\n42.157.32.0/19\n42.157.64.0/18\n42.157.128.0/17\n42.158.0.0/15\n42.160.0.0/12\n42.176.0.0/13\n42.184.0.0/15\n42.186.0.0/16\n42.187.0.0/18\n42.187.64.0/19\n42.187.96.0/20\n42.187.112.0/21\n42.187.120.0/22\n42.187.128.0/17\n42.192.0.0/13\n42.201.0.0/17\n42.202.0.0/15\n42.204.0.0/14\n42.208.0.0/12\n42.224.0.0/12\n42.240.0.0/16\n42.242.0.0/15\n42.244.0.0/15\n42.246.0.0/16\n42.247.0.0/22\n42.247.4.0/24\n42.247.5.0/25\n42.247.5.128/26\n42.247.5.204/30\n42.247.5.208/28\n42.247.5.224/27\n42.247.6.0/23\n42.247.8.0/21\n42.247.16.0/20\n42.247.32.0/19\n42.247.64.0/18\n42.247.128.0/17\n42.248.0.0/13\n43.224.12.0/22\n43.224.24.0/22\n43.224.44.0/22\n43.224.52.0/22\n43.224.56.0/22\n43.224.68.0/22\n43.224.72.0/22\n43.224.80.0/22\n43.224.100.0/22\n43.224.144.0/22\n43.224.160.0/22\n43.224.176.0/22\n43.224.184.0/22\n43.224.200.0/21\n43.224.208.0/21\n43.224.216.0/22\n43.224.240.0/22\n43.225.76.0/22\n43.225.86.0/24\n43.225.120.0/22\n43.225.180.0/22\n43.225.208.0/22\n43.225.216.0/21\n43.225.224.0/20\n43.225.240.0/21\n43.225.252.0/22\n43.226.32.0/19\n43.226.64.0/19\n43.226.96.0/20\n43.226.112.0/21\n43.226.120.0/22\n43.226.128.0/19\n43.226.160.0/21\n43.226.236.0/22\n43.226.240.0/20\n43.227.0.0/21\n43.227.8.0/22\n43.227.32.0/19\n43.227.64.0/19\n43.227.104.0/22\n43.227.136.0/21\n43.227.144.0/22\n43.227.152.0/21\n43.227.160.0/20\n43.227.176.0/21\n43.227.188.0/22\n43.227.192.0/19\n43.227.232.0/22\n43.227.248.0/21\n43.228.0.0/18\n43.228.64.0/21\n43.228.76.0/22\n43.228.100.0/22\n43.228.116.0/24\n43.228.118.0/23\n43.228.132.0/22\n43.228.136.0/22\n43.228.148.0/22\n43.228.152.0/22\n43.228.188.0/22\n43.229.40.0/22\n43.229.48.0/22\n43.229.56.0/22\n43.229.96.0/22\n43.229.136.0/21\n43.229.168.0/21\n43.229.176.0/20\n43.229.192.0/21\n43.229.216.0/21\n43.229.232.0/21\n43.230.20.0/22\n43.230.32.0/22\n43.230.68.0/22\n43.230.72.0/22\n43.230.84.0/22\n43.230.124.0/22\n43.230.220.0/22\n43.230.224.0/19\n43.231.12.0/22\n43.231.32.0/20\n43.231.80.0/20\n43.231.96.0/20\n43.231.136.0/21\n43.231.144.0/20\n43.231.160.0/20\n43.231.176.0/21\n43.236.0.0/15\n43.238.0.0/16\n43.239.0.0/19\n43.239.32.0/20\n43.239.48.0/22\n43.239.116.0/22\n43.239.120.0/22\n43.239.172.0/22\n43.240.0.0/22\n43.240.56.0/21\n43.240.68.0/22\n43.240.72.0/21\n43.240.84.0/22\n43.240.124.0/22\n43.240.128.0/21\n43.240.136.0/22\n43.240.156.0/22\n43.240.160.0/19\n43.240.192.0/19\n43.240.240.0/20\n43.241.0.0/20\n43.241.16.0/21\n43.241.48.0/22\n43.241.76.0/22\n43.241.80.0/20\n43.241.112.0/22\n43.241.168.0/21\n43.241.176.0/21\n43.241.184.0/22\n43.241.208.0/20\n43.241.224.0/20\n43.241.240.0/22\n43.241.248.0/22\n43.242.8.0/21\n43.242.16.0/20\n43.242.48.0/22\n43.242.53.0/24\n43.242.54.0/23\n43.242.56.0/21\n43.242.64.0/22\n43.242.72.0/21\n43.242.80.0/20\n43.242.96.0/22\n43.242.144.0/20\n43.242.160.0/21\n43.242.180.0/22\n43.242.188.0/22\n43.242.192.0/21\n43.242.204.0/22\n43.242.216.0/21\n43.242.252.0/22\n43.243.4.0/22\n43.243.8.0/21\n43.243.16.0/22\n43.243.88.0/22\n43.243.128.0/22\n43.243.136.0/22\n43.243.144.0/21\n43.243.156.0/22\n43.243.180.0/22\n43.243.228.0/22\n43.243.232.0/22\n43.243.244.0/22\n43.246.0.0/18\n43.246.64.0/19\n43.246.96.0/22\n43.246.228.0/22\n43.247.4.0/22\n43.247.8.0/22\n43.247.44.0/22\n43.247.48.0/22\n43.247.68.0/22\n43.247.76.0/22\n43.247.84.0/22\n43.247.88.0/21\n43.247.96.0/21\n43.247.108.0/22\n43.247.112.0/22\n43.247.148.0/22\n43.247.152.0/22\n43.247.176.0/20\n43.247.196.0/22\n43.247.200.0/21\n43.247.208.0/20\n43.247.224.0/19\n43.248.0.0/21\n43.248.20.0/22\n43.248.28.0/22\n43.248.48.0/22\n43.248.76.0/22\n43.248.80.0/20\n43.248.96.0/19\n43.248.128.0/20\n43.248.144.0/21\n43.248.176.0/20\n43.248.192.0/20\n43.248.208.0/22\n43.248.228.0/22\n43.248.232.0/22\n43.248.244.0/22\n43.249.4.0/22\n43.249.120.0/22\n43.249.132.0/22\n43.249.136.0/22\n43.249.144.0/20\n43.249.160.0/21\n43.249.168.0/22\n43.249.192.0/22\n43.249.236.0/22\n43.250.4.0/22\n43.250.12.0/22\n43.250.16.0/21\n43.250.28.0/22\n43.250.32.0/22\n43.250.96.0/21\n43.250.108.0/22\n43.250.112.0/21\n43.250.128.0/22\n43.250.144.0/21\n43.250.160.0/22\n43.250.168.0/22\n43.250.176.0/22\n43.250.200.0/22\n43.250.212.0/22\n43.250.216.0/21\n43.250.236.0/22\n43.250.244.0/22\n43.251.4.0/22\n43.251.36.0/22\n43.251.192.0/22\n43.251.232.0/22\n43.251.244.0/22\n43.252.48.0/22\n43.252.56.0/22\n43.252.224.0/22\n43.254.0.0/21\n43.254.8.0/22\n43.254.24.0/22\n43.254.36.0/22\n43.254.44.0/22\n43.254.52.0/22\n43.254.64.0/22\n43.254.72.0/22\n43.254.84.0/22\n43.254.88.0/21\n43.254.100.0/22\n43.254.104.0/22\n43.254.112.0/21\n43.254.128.0/22\n43.254.136.0/21\n43.254.144.0/20\n43.254.168.0/21\n43.254.180.0/22\n43.254.184.0/21\n43.254.192.0/22\n43.254.200.0/22\n43.254.208.0/22\n43.254.220.0/22\n43.254.224.0/20\n43.254.240.0/22\n43.254.248.0/21\n43.255.0.0/21\n43.255.8.0/22\n43.255.16.0/22\n43.255.48.0/22\n43.255.64.0/20\n43.255.84.0/22\n43.255.96.0/22\n43.255.144.0/22\n43.255.176.0/22\n43.255.184.0/22\n43.255.192.0/22\n43.255.200.0/21\n43.255.208.0/21\n43.255.224.0/21\n43.255.232.0/22\n43.255.244.0/22\n45.40.192.0/20\n45.40.208.0/21\n45.40.224.0/19\n45.65.16.0/20\n45.112.132.0/22\n45.112.188.0/22\n45.112.208.0/22\n45.112.216.0/21\n45.112.228.0/22\n45.112.232.0/21\n45.113.12.0/22\n45.113.16.0/20\n45.113.40.0/22\n45.113.52.0/22\n45.113.72.0/22\n45.113.144.0/21\n45.113.168.0/22\n45.113.184.0/22\n45.113.200.0/21\n45.113.208.0/20\n45.113.240.0/22\n45.113.252.0/22\n45.114.0.0/22\n45.114.32.0/22\n45.114.52.0/22\n45.114.96.0/22\n45.114.136.0/22\n45.114.196.0/22\n45.114.200.0/22\n45.114.228.0/22\n45.114.237.0/24\n45.114.238.0/23\n45.114.252.0/22\n45.115.44.0/22\n45.115.100.0/22\n45.115.120.0/22\n45.115.132.0/22\n45.115.144.0/22\n45.115.156.0/22\n45.115.164.0/22\n45.115.200.0/22\n45.115.212.0/22\n45.115.244.0/22\n45.115.248.0/22\n45.116.16.0/22\n45.116.24.0/22\n45.116.32.0/21\n45.116.52.0/22\n45.116.96.0/21\n45.116.140.0/22\n45.116.152.0/22\n45.116.208.0/22\n45.117.8.0/22\n45.117.20.0/22\n45.117.68.0/22\n45.117.124.0/22\n45.117.252.0/22\n45.119.60.0/22\n45.119.64.0/21\n45.119.72.0/22\n45.119.104.0/22\n45.119.232.0/22\n45.120.100.0/22\n45.120.140.0/22\n45.120.164.0/22\n45.120.180.128/27\n45.120.240.0/22\n45.121.52.0/22\n45.121.64.0/21\n45.121.72.0/22\n45.121.92.0/22\n45.121.96.0/22\n45.121.172.0/22\n45.121.176.0/22\n45.121.240.0/20\n45.122.0.0/19\n45.122.32.0/21\n45.122.40.0/22\n45.122.60.0/22\n45.122.64.0/19\n45.122.96.0/20\n45.122.112.0/21\n45.122.160.0/19\n45.122.192.0/20\n45.122.208.0/21\n45.122.216.0/22\n45.123.28.0/22\n45.123.32.0/21\n45.123.44.0/22\n45.123.48.0/20\n45.123.64.0/20\n45.123.80.0/21\n45.123.120.0/22\n45.123.128.0/21\n45.123.136.0/22\n45.123.148.0/22\n45.123.152.0/21\n45.123.164.0/22\n45.123.168.0/21\n45.123.176.0/21\n45.123.184.0/22\n45.123.204.0/22\n45.123.212.0/22\n45.123.224.0/19\n45.124.0.0/22\n45.124.20.0/22\n45.124.28.0/22\n45.124.32.0/21\n45.124.44.0/22\n45.124.68.0/22\n45.124.76.0/22\n45.124.80.0/22\n45.124.100.0/22\n45.124.124.0/22\n45.124.172.0/22\n45.124.176.0/22\n45.124.208.0/22\n45.124.248.0/22\n45.125.24.0/22\n45.125.44.0/22\n45.125.52.0/22\n45.125.56.0/22\n45.125.76.0/22\n45.125.80.0/20\n45.125.96.0/21\n45.125.136.0/22\n45.126.48.0/21\n45.126.108.0/22\n45.126.112.0/21\n45.126.120.0/22\n45.126.220.0/22\n45.127.8.0/21\n45.127.128.0/22\n45.127.144.0/21\n45.127.156.0/22\n45.248.8.0/22\n45.248.80.0/22\n45.248.88.0/22\n45.248.96.0/20\n45.248.128.0/21\n45.248.204.0/22\n45.248.208.0/20\n45.248.224.0/19\n45.249.0.0/21\n45.249.12.0/22\n45.249.16.0/20\n45.249.32.0/21\n45.249.112.0/22\n45.249.188.0/22\n45.249.192.0/20\n45.249.208.0/21\n45.250.12.0/22\n45.250.16.0/22\n45.250.28.0/22\n45.250.32.0/21\n45.250.40.0/22\n45.250.76.0/22\n45.250.80.0/20\n45.250.96.0/22\n45.250.104.0/21\n45.250.112.0/20\n45.250.128.0/20\n45.250.144.0/21\n45.250.152.0/22\n45.250.164.0/22\n45.250.180.0/22\n45.250.184.0/21\n45.250.192.0/22\n45.251.0.0/22\n45.251.8.0/22\n45.251.16.0/21\n45.251.52.0/22\n45.251.84.0/22\n45.251.88.0/21\n45.251.96.0/21\n45.251.120.0/21\n45.251.137.0/24\n45.251.138.0/23\n45.251.140.0/22\n45.251.144.0/20\n45.251.160.0/19\n45.251.192.0/19\n45.251.224.0/22\n45.252.0.0/19\n45.252.32.0/20\n45.252.48.0/22\n45.252.84.0/22\n45.252.88.0/21\n45.252.96.0/19\n45.252.128.0/19\n45.252.160.0/20\n45.252.176.0/22\n45.252.192.0/19\n45.252.224.0/21\n45.252.232.0/22\n45.253.0.0/18\n45.253.64.0/20\n45.253.80.0/21\n45.253.92.0/22\n45.253.96.0/20\n45.253.112.0/21\n45.253.120.0/22\n45.253.130.0/23\n45.253.132.0/22\n45.253.136.0/21\n45.253.144.0/20\n45.253.160.0/19\n45.253.192.0/19\n45.253.224.0/20\n45.253.240.0/22\n45.254.0.0/20\n45.254.16.0/21\n45.254.28.0/22\n45.254.40.0/22\n45.254.48.0/20\n45.254.64.0/18\n45.254.128.0/18\n45.254.192.0/19\n45.254.224.0/21\n45.254.236.0/22\n45.254.240.0/22\n45.254.248.0/22\n45.255.0.0/18\n45.255.64.0/19\n45.255.96.0/20\n45.255.112.0/21\n45.255.120.0/22\n45.255.136.0/21\n45.255.144.0/20\n45.255.160.0/19\n45.255.192.0/19\n45.255.224.0/20\n45.255.240.0/21\n45.255.248.0/22\n46.248.24.0/23\n47.92.0.0/14\n47.96.0.0/11\n49.4.0.0/14\n49.51.56.0/22\n49.51.60.0/23\n49.51.110.0/23\n49.51.112.0/20\n49.52.0.0/14\n49.64.0.0/11\n49.112.0.0/13\n49.120.0.0/14\n49.128.0.0/24\n49.128.2.0/23\n49.128.4.0/22\n49.140.0.0/15\n49.152.0.0/14\n49.208.0.0/14\n49.220.0.0/14\n49.232.0.0/14\n49.239.0.0/18\n49.239.192.0/18\n52.80.0.0/14\n52.94.249.0/27\n52.130.0.0/15\n54.222.0.0/15\n54.231.208.0/20\n54.240.224.0/24\n57.92.96.0/20\n58.14.0.0/15\n58.16.0.0/13\n58.24.0.0/15\n58.30.0.0/15\n58.32.0.0/11\n58.65.232.0/21\n58.66.0.0/15\n58.68.128.0/19\n58.68.160.0/23\n58.68.163.0/24\n58.68.164.0/22\n58.68.179.0/24\n58.68.180.0/24\n58.68.200.0/21\n58.68.208.0/20\n58.68.224.0/19\n58.82.0.0/17\n58.83.0.0/16\n58.87.64.0/18\n58.99.128.0/17\n58.100.0.0/15\n58.116.0.0/14\n58.128.0.0/13\n58.144.0.0/16\n58.154.0.0/15\n58.192.0.0/11\n58.240.0.0/12\n59.32.0.0/11\n59.64.0.0/12\n59.80.0.0/15\n59.82.0.0/16\n59.83.0.0/18\n59.83.132.0/22\n59.83.136.0/21\n59.83.144.0/20\n59.83.160.0/19\n59.83.192.0/19\n59.83.224.0/20\n59.83.240.0/21\n59.83.248.0/22\n59.83.252.0/23\n59.83.254.0/24\n59.107.0.0/16\n59.108.0.0/14\n59.151.0.0/17\n59.152.16.0/20\n59.152.36.0/22\n59.152.64.0/20\n59.152.112.0/21\n59.153.4.0/22\n59.153.32.0/22\n59.153.64.0/21\n59.153.72.0/22\n59.153.92.0/22\n59.153.136.0/22\n59.153.152.0/21\n59.153.164.0/22\n59.153.168.0/21\n59.153.176.0/20\n59.153.192.0/22\n59.155.0.0/16\n59.172.0.0/14\n59.191.0.0/17\n59.192.0.0/10\n60.0.0.0/11\n60.55.0.0/16\n60.63.0.0/16\n60.160.0.0/11\n60.194.0.0/15\n60.200.0.0/13\n60.208.0.0/12\n60.232.0.0/15\n60.235.0.0/16\n60.245.128.0/17\n60.247.0.0/16\n60.252.0.0/16\n60.253.128.0/17\n60.255.0.0/16\n61.4.81.0/24\n61.4.82.0/23\n61.4.84.0/22\n61.4.88.0/21\n61.4.176.0/20\n61.8.160.0/20\n61.14.212.0/22\n61.14.216.0/21\n61.14.240.0/21\n61.28.0.0/17\n61.29.128.0/18\n61.29.192.0/19\n61.29.224.0/20\n61.45.128.0/18\n61.45.224.0/20\n61.47.128.0/18\n61.48.0.0/13\n61.87.192.0/18\n61.128.0.0/10\n61.232.0.0/14\n61.236.0.0/15\n61.240.0.0/14\n62.234.0.0/16\n68.79.0.0/18\n69.230.192.0/18\n69.231.128.0/18\n69.234.192.0/18\n69.235.128.0/18\n71.131.192.0/18\n71.132.0.0/18\n71.136.64.0/18\n71.137.0.0/18\n72.163.240.0/23\n72.163.248.0/22\n81.68.0.0/14\n81.161.63.0/24\n82.156.0.0/15\n87.254.207.0/24\n91.223.53.0/24\n91.239.190.0/24\n93.183.14.0/24\n93.183.18.0/24\n94.191.0.0/17\n101.0.0.0/22\n101.1.0.0/22\n101.2.172.0/22\n101.4.0.0/14\n101.16.0.0/12\n101.32.0.0/14\n101.36.0.0/18\n101.36.64.0/20\n101.36.88.0/21\n101.36.96.0/19\n101.36.128.0/17\n101.37.0.0/16\n101.38.0.0/15\n101.40.0.0/13\n101.48.0.0/15\n101.50.8.0/21\n101.50.56.0/22\n101.52.0.0/16\n101.53.100.0/22\n101.54.0.0/16\n101.55.224.0/21\n101.64.0.0/13\n101.72.0.0/14\n101.76.0.0/15\n101.78.0.0/22\n101.78.32.0/19\n101.80.0.0/12\n101.96.0.0/21\n101.96.8.0/22\n101.96.16.0/20\n101.96.128.0/17\n101.99.96.0/19\n101.101.64.0/19\n101.101.100.0/24\n101.101.102.0/23\n101.101.104.0/21\n101.101.112.0/20\n101.102.64.0/19\n101.102.100.0/23\n101.102.102.0/24\n101.102.104.0/21\n101.102.112.0/20\n101.104.0.0/14\n101.110.64.0/19\n101.110.96.0/20\n101.110.116.0/22\n101.110.120.0/21\n101.120.0.0/14\n101.124.0.0/15\n101.126.0.0/16\n101.128.0.0/22\n101.128.8.0/21\n101.128.16.0/20\n101.128.32.0/19\n101.129.0.0/16\n101.130.0.0/15\n101.132.0.0/15\n101.134.0.0/17\n101.134.128.0/19\n101.134.160.0/20\n101.134.176.0/21\n101.134.184.0/22\n101.134.189.0/24\n101.134.190.0/23\n101.134.192.0/18\n101.135.0.0/16\n101.144.0.0/12\n101.192.0.0/14\n101.196.0.0/16\n101.198.128.0/18\n101.198.194.0/24\n101.198.196.0/23\n101.198.200.0/22\n101.198.224.0/19\n101.199.0.0/19\n101.199.48.0/20\n101.199.64.0/18\n101.199.128.0/17\n101.200.0.0/15\n101.203.128.0/19\n101.203.160.0/21\n101.203.172.0/22\n101.203.176.0/20\n101.204.0.0/14\n101.224.0.0/13\n101.232.0.0/15\n101.234.64.0/21\n101.234.76.0/22\n101.234.80.0/20\n101.234.96.0/19\n101.236.0.0/14\n101.240.0.0/13\n101.248.0.0/15\n101.251.0.0/22\n101.251.8.0/21\n101.251.16.0/20\n101.251.32.0/19\n101.251.64.0/18\n101.251.128.0/17\n101.252.0.0/15\n101.254.0.0/16\n102.176.130.0/24\n103.1.8.0/22\n103.1.20.0/22\n103.1.24.0/22\n103.1.88.0/22\n103.1.168.0/22\n103.2.108.0/22\n103.2.156.0/22\n103.2.164.0/22\n103.2.200.0/21\n103.2.208.0/21\n103.3.84.0/22\n103.3.88.0/21\n103.3.96.0/19\n103.3.128.0/20\n103.3.148.0/22\n103.3.152.0/21\n103.4.56.0/22\n103.4.168.0/22\n103.4.184.0/22\n103.5.36.0/22\n103.5.52.0/23\n103.5.56.0/22\n103.5.152.0/22\n103.5.168.0/22\n103.5.192.0/22\n103.5.252.0/22\n103.6.76.0/22\n103.6.108.0/22\n103.6.120.0/22\n103.6.220.0/22\n103.6.228.0/22\n103.7.140.0/22\n103.7.212.0/22\n103.7.216.0/21\n103.8.0.0/21\n103.8.8.0/22\n103.8.32.0/22\n103.8.52.0/22\n103.8.68.0/22\n103.8.108.0/22\n103.8.156.0/22\n103.8.200.0/21\n103.8.220.0/22\n103.9.8.0/22\n103.9.24.0/22\n103.9.108.0/22\n103.9.152.0/22\n103.9.248.0/21\n103.10.0.0/22\n103.10.16.0/22\n103.10.84.0/22\n103.10.111.0/24\n103.10.140.0/22\n103.11.16.0/22\n103.11.168.0/22\n103.11.180.0/22\n103.12.32.0/22\n103.12.136.0/22\n103.12.184.0/22\n103.12.232.0/22\n103.13.12.0/22\n103.13.124.0/22\n103.13.144.0/22\n103.13.196.0/22\n103.13.244.0/22\n103.14.84.0/22\n103.14.132.0/22\n103.14.136.0/22\n103.14.156.0/22\n103.14.240.0/22\n103.15.4.0/22\n103.15.8.0/22\n103.15.16.0/22\n103.15.96.0/22\n103.15.200.0/22\n103.16.52.0/22\n103.16.80.0/21\n103.16.88.0/22\n103.16.108.0/22\n103.16.124.0/22\n103.17.40.0/22\n103.17.64.0/22\n103.17.120.0/23\n103.17.136.0/22\n103.17.160.0/22\n103.17.204.0/22\n103.17.228.0/22\n103.18.192.0/22\n103.18.208.0/21\n103.18.224.0/22\n103.19.12.0/22\n103.19.40.0/21\n103.19.64.0/21\n103.19.72.0/22\n103.19.232.0/22\n103.20.12.0/22\n103.20.32.0/23\n103.20.34.0/24\n103.20.68.0/22\n103.20.112.0/22\n103.20.128.0/22\n103.20.160.0/22\n103.20.248.0/22\n103.21.112.0/21\n103.21.140.0/22\n103.21.176.0/22\n103.21.240.0/22\n103.22.0.0/18\n103.22.64.0/19\n103.22.100.0/22\n103.22.104.0/21\n103.22.112.0/20\n103.22.188.0/22\n103.22.228.0/22\n103.22.252.0/22\n103.23.8.0/22\n103.23.56.0/22\n103.23.160.0/21\n103.23.176.0/22\n103.23.228.0/22\n103.24.24.0/22\n103.24.116.0/22\n103.24.128.0/22\n103.24.144.0/22\n103.24.176.0/22\n103.24.184.0/22\n103.24.228.0/22\n103.24.252.0/22\n103.25.20.0/22\n103.25.24.0/21\n103.25.32.0/21\n103.25.40.0/22\n103.25.48.0/22\n103.25.64.0/21\n103.25.148.0/22\n103.25.156.0/22\n103.25.216.0/22\n103.26.0.0/22\n103.26.64.0/22\n103.26.76.0/22\n103.26.116.0/22\n103.26.156.0/22\n103.26.160.0/22\n103.26.228.0/22\n103.26.240.0/22\n103.27.4.0/22\n103.27.12.0/22\n103.27.24.0/22\n103.27.56.0/22\n103.27.96.0/22\n103.27.240.0/22\n103.28.4.0/22\n103.28.8.0/22\n103.28.184.0/22\n103.28.204.0/22\n103.28.212.0/22\n103.29.16.0/22\n103.29.128.0/21\n103.29.136.0/22\n103.30.20.0/22\n103.30.96.0/22\n103.30.148.0/22\n103.30.202.0/23\n103.30.228.0/22\n103.30.236.0/22\n103.31.0.0/22\n103.31.48.0/21\n103.31.60.0/22\n103.31.64.0/21\n103.31.72.0/24\n103.31.148.0/22\n103.31.160.0/22\n103.31.168.0/22\n103.31.200.0/22\n103.31.236.0/22\n103.32.0.0/15\n103.34.0.0/16\n103.35.0.0/19\n103.35.32.0/20\n103.35.48.0/22\n103.35.104.0/22\n103.35.220.0/22\n103.36.28.0/22\n103.36.36.0/22\n103.36.56.0/21\n103.36.64.0/22\n103.36.72.0/22\n103.36.96.0/22\n103.36.132.0/22\n103.36.136.0/22\n103.36.160.0/19\n103.36.192.0/19\n103.36.224.0/20\n103.36.240.0/21\n103.37.12.0/22\n103.37.16.0/22\n103.37.24.0/22\n103.37.44.0/22\n103.37.52.0/22\n103.37.56.0/22\n103.37.72.0/22\n103.37.100.0/22\n103.37.104.0/22\n103.37.136.0/21\n103.37.144.0/20\n103.37.160.0/21\n103.37.172.0/22\n103.37.176.0/22\n103.37.188.0/22\n103.37.208.0/20\n103.37.252.0/22\n103.38.0.0/22\n103.38.32.0/22\n103.38.40.0/21\n103.38.76.0/22\n103.38.84.0/22\n103.38.92.0/22\n103.38.96.0/22\n103.38.116.0/22\n103.38.132.0/22\n103.38.140.0/22\n103.38.220.0/22\n103.38.224.0/21\n103.38.232.0/22\n103.38.252.0/23\n103.39.64.0/22\n103.39.88.0/22\n103.39.100.0/22\n103.39.104.0/22\n103.39.160.0/19\n103.39.200.0/21\n103.39.208.0/20\n103.39.224.0/21\n103.39.232.0/22\n103.40.12.0/22\n103.40.16.0/20\n103.40.32.0/20\n103.40.88.0/22\n103.40.192.0/22\n103.40.212.0/22\n103.40.220.0/22\n103.40.228.0/22\n103.40.232.0/21\n103.40.240.0/20\n103.41.0.0/22\n103.41.52.0/22\n103.41.140.0/22\n103.41.148.0/22\n103.41.152.0/22\n103.41.160.0/21\n103.41.220.0/22\n103.41.224.0/21\n103.41.232.0/22\n103.42.8.0/22\n103.42.24.0/22\n103.42.32.0/22\n103.42.64.0/21\n103.42.76.0/22\n103.42.232.0/22\n103.43.26.0/23\n103.43.96.0/21\n103.43.104.0/22\n103.43.124.0/22\n103.43.184.0/22\n103.43.192.0/21\n103.43.208.0/22\n103.43.220.0/22\n103.43.224.0/22\n103.43.240.0/22\n103.44.58.0/23\n103.44.80.0/22\n103.44.120.0/21\n103.44.144.0/22\n103.44.152.0/22\n103.44.168.0/22\n103.44.176.0/20\n103.44.192.0/20\n103.44.224.0/22\n103.44.236.0/22\n103.44.240.0/20\n103.45.0.0/18\n103.45.72.0/21\n103.45.80.0/20\n103.45.96.0/19\n103.45.128.0/18\n103.45.192.0/19\n103.45.224.0/22\n103.45.248.0/22\n103.46.0.0/22\n103.46.12.0/22\n103.46.16.0/20\n103.46.32.0/19\n103.46.64.0/18\n103.46.128.0/21\n103.46.136.0/22\n103.46.152.0/21\n103.46.160.0/20\n103.46.176.0/21\n103.46.244.0/22\n103.46.248.0/22\n103.47.4.0/22\n103.47.20.0/22\n103.47.36.0/22\n103.47.40.0/22\n103.47.48.0/22\n103.47.80.0/22\n103.47.96.0/22\n103.47.116.0/22\n103.47.120.0/22\n103.47.136.0/21\n103.47.212.0/22\n103.48.52.0/22\n103.48.92.0/22\n103.48.148.0/22\n103.48.152.0/22\n103.48.202.0/23\n103.48.216.0/21\n103.48.224.0/20\n103.48.240.0/21\n103.49.12.0/22\n103.49.20.0/22\n103.49.72.0/21\n103.49.96.0/22\n103.49.108.0/22\n103.49.128.0/22\n103.49.176.0/21\n103.50.36.0/22\n103.50.44.0/22\n103.50.48.0/20\n103.50.64.0/21\n103.50.72.0/22\n103.50.92.0/22\n103.50.108.0/22\n103.50.112.0/20\n103.50.132.0/22\n103.50.136.0/21\n103.50.172.0/22\n103.50.176.0/20\n103.50.192.0/21\n103.50.200.0/22\n103.50.220.0/22\n103.50.224.0/20\n103.50.240.0/21\n103.50.248.0/22\n103.52.40.0/22\n103.52.72.0/21\n103.52.80.0/21\n103.52.96.0/21\n103.52.104.0/22\n103.52.160.0/21\n103.52.172.0/22\n103.52.176.0/22\n103.52.184.0/22\n103.52.196.0/22\n103.53.64.0/21\n103.53.92.0/22\n103.53.124.0/22\n103.53.128.0/20\n103.53.144.0/22\n103.53.160.0/22\n103.53.180.0/22\n103.53.204.0/22\n103.53.208.0/21\n103.53.236.0/22\n103.53.248.0/22\n103.54.8.0/22\n103.54.48.0/22\n103.54.160.0/21\n103.54.212.0/22\n103.54.228.0/22\n103.54.240.0/22\n103.55.80.0/22\n103.55.120.0/22\n103.55.152.0/22\n103.55.172.0/22\n103.55.204.0/22\n103.55.208.0/22\n103.55.228.0/22\n103.55.236.0/22\n103.55.240.0/22\n103.56.20.0/22\n103.56.32.0/22\n103.56.56.0/21\n103.56.72.0/21\n103.56.140.0/22\n103.56.152.0/22\n103.56.184.0/22\n103.56.200.0/22\n103.57.12.0/22\n103.57.52.0/22\n103.57.56.0/22\n103.57.76.0/22\n103.57.136.0/22\n103.57.196.0/22\n103.58.24.0/22\n103.59.76.0/22\n103.59.112.0/21\n103.59.120.0/24\n103.59.123.0/24\n103.59.124.0/22\n103.59.128.0/22\n103.59.148.0/22\n103.60.32.0/22\n103.60.44.0/22\n103.60.164.0/22\n103.60.228.0/22\n103.60.236.0/22\n103.61.60.0/24\n103.61.104.0/22\n103.61.140.0/22\n103.61.152.0/21\n103.61.160.0/22\n103.61.172.0/22\n103.61.176.0/22\n103.62.24.0/22\n103.62.72.0/21\n103.62.80.0/21\n103.62.88.0/22\n103.62.96.0/19\n103.62.128.0/21\n103.62.156.0/22\n103.62.160.0/19\n103.62.192.0/22\n103.62.204.0/22\n103.62.208.0/20\n103.62.224.0/22\n103.63.32.0/19\n103.63.64.0/20\n103.63.80.0/21\n103.63.88.0/22\n103.63.140.0/22\n103.63.144.0/22\n103.63.152.0/22\n103.63.160.0/20\n103.63.176.0/21\n103.63.184.0/22\n103.63.192.0/20\n103.63.208.0/22\n103.63.240.0/20\n103.64.0.0/21\n103.64.24.0/21\n103.64.32.0/19\n103.64.64.0/18\n103.64.140.0/22\n103.64.144.0/22\n103.64.152.0/21\n103.64.160.0/19\n103.64.192.0/18\n103.65.0.0/21\n103.65.12.0/22\n103.65.16.0/22\n103.65.48.0/20\n103.65.64.0/19\n103.65.100.0/22\n103.65.104.0/21\n103.65.112.0/20\n103.65.128.0/21\n103.65.136.0/22\n103.65.144.0/20\n103.65.160.0/20\n103.66.32.0/22\n103.66.40.0/22\n103.66.108.0/22\n103.66.200.0/22\n103.66.240.0/20\n103.67.0.0/21\n103.67.8.0/22\n103.67.40.0/21\n103.67.48.0/20\n103.67.64.0/18\n103.67.128.0/20\n103.67.144.0/21\n103.67.172.0/24\n103.67.175.0/24\n103.67.192.0/22\n103.67.212.0/22\n103.68.88.0/22\n103.68.100.0/22\n103.68.128.0/22\n103.69.16.0/22\n103.69.212.0/23\n103.70.8.0/22\n103.70.148.0/22\n103.70.236.0/22\n103.70.252.0/22\n103.71.0.0/22\n103.71.68.0/22\n103.71.72.0/22\n103.71.80.0/21\n103.71.88.0/22\n103.71.120.0/21\n103.71.128.0/22\n103.71.196.0/22\n103.71.200.0/22\n103.71.232.0/22\n103.72.12.0/22\n103.72.16.0/20\n103.72.32.0/20\n103.72.48.0/21\n103.72.112.0/21\n103.72.124.0/22\n103.72.128.0/21\n103.72.149.0/24\n103.72.150.0/23\n103.72.172.0/22\n103.72.180.0/22\n103.72.224.0/19\n103.73.0.0/19\n103.73.48.0/22\n103.73.116.0/22\n103.73.120.0/22\n103.73.128.0/20\n103.73.168.0/22\n103.73.176.0/22\n103.73.204.0/22\n103.73.208.0/22\n103.73.240.0/23\n103.73.244.0/22\n103.73.248.0/22\n103.74.24.0/21\n103.74.32.0/20\n103.74.48.0/22\n103.74.56.0/21\n103.74.80.0/22\n103.74.124.0/22\n103.74.148.0/22\n103.74.152.0/21\n103.74.204.0/22\n103.74.232.0/22\n103.75.87.0/24\n103.75.88.0/21\n103.75.104.0/21\n103.75.112.0/22\n103.75.120.0/22\n103.75.128.0/22\n103.75.144.0/22\n103.75.152.0/22\n103.76.60.0/22\n103.76.64.0/21\n103.76.72.0/22\n103.76.92.0/22\n103.76.216.0/21\n103.76.224.0/22\n103.77.28.0/22\n103.77.52.0/22\n103.77.56.0/22\n103.77.88.0/22\n103.77.132.0/22\n103.77.148.0/22\n103.77.220.0/22\n103.78.56.0/21\n103.78.64.0/22\n103.78.124.0/22\n103.78.172.0/22\n103.78.176.0/22\n103.78.196.0/22\n103.78.228.0/22\n103.79.24.0/21\n103.79.36.0/22\n103.79.40.0/21\n103.79.56.0/21\n103.79.64.0/21\n103.79.80.0/21\n103.79.136.0/22\n103.79.188.0/22\n103.79.192.0/20\n103.79.208.0/21\n103.79.243.0/24\n103.80.44.0/22\n103.80.72.0/22\n103.80.176.0/21\n103.80.184.0/22\n103.80.192.0/22\n103.80.200.0/22\n103.80.232.0/22\n103.81.4.0/22\n103.81.44.0/22\n103.81.48.0/22\n103.81.96.0/22\n103.81.120.0/22\n103.81.148.0/22\n103.81.164.0/22\n103.81.200.0/22\n103.81.232.0/22\n103.82.60.0/22\n103.82.68.0/22\n103.82.84.0/22\n103.82.104.0/22\n103.82.224.0/22\n103.82.236.0/22\n103.83.44.0/22\n103.83.52.0/22\n103.83.60.0/22\n103.83.72.0/22\n103.83.112.0/22\n103.83.132.0/22\n103.83.180.0/22\n103.84.0.0/22\n103.84.12.0/22\n103.84.20.0/22\n103.84.24.0/21\n103.84.48.0/22\n103.84.56.0/22\n103.84.64.0/22\n103.84.72.0/22\n103.85.44.0/22\n103.85.48.0/21\n103.85.56.0/22\n103.85.84.0/22\n103.85.136.0/22\n103.85.144.0/22\n103.85.164.0/22\n103.85.168.0/21\n103.85.176.0/22\n103.86.28.0/22\n103.86.32.0/22\n103.86.60.0/22\n103.86.129.0/24\n103.86.204.0/22\n103.86.208.0/20\n103.86.224.0/19\n103.87.0.0/21\n103.87.20.0/22\n103.87.32.0/22\n103.87.96.0/22\n103.87.132.0/22\n103.87.180.0/22\n103.87.224.0/22\n103.88.4.0/22\n103.88.8.0/21\n103.88.16.0/21\n103.88.32.0/21\n103.88.60.0/22\n103.88.64.0/22\n103.88.72.0/22\n103.88.96.0/21\n103.88.152.0/23\n103.88.164.0/22\n103.88.212.0/22\n103.89.28.0/22\n103.89.96.0/20\n103.89.112.0/22\n103.89.148.0/22\n103.89.172.0/22\n103.89.184.0/21\n103.89.192.0/19\n103.89.224.0/21\n103.90.52.0/22\n103.90.92.0/22\n103.90.100.0/22\n103.90.104.0/21\n103.90.112.0/20\n103.90.128.0/21\n103.90.152.0/22\n103.90.168.0/22\n103.90.173.0/24\n103.90.176.0/22\n103.90.188.0/22\n103.90.192.0/22\n103.91.36.0/22\n103.91.40.0/22\n103.91.108.0/22\n103.91.152.0/22\n103.91.176.0/22\n103.91.200.0/22\n103.91.208.0/21\n103.91.236.0/22\n103.92.48.0/20\n103.92.64.0/20\n103.92.80.0/22\n103.92.88.0/22\n103.92.108.0/22\n103.92.124.0/22\n103.92.132.0/22\n103.92.156.0/22\n103.92.164.0/22\n103.92.168.0/21\n103.92.176.0/20\n103.92.192.0/22\n103.92.236.0/22\n103.92.240.0/20\n103.93.0.0/21\n103.93.28.0/22\n103.93.84.0/22\n103.93.152.0/22\n103.93.180.0/22\n103.93.204.0/22\n103.94.12.0/22\n103.94.20.0/22\n103.94.28.0/22\n103.94.32.0/20\n103.94.72.0/22\n103.94.88.0/22\n103.94.116.0/22\n103.94.160.0/22\n103.94.182.0/24\n103.94.200.0/22\n103.95.31.0/24\n103.95.52.0/22\n103.95.70.0/23\n103.95.88.0/21\n103.95.136.0/21\n103.95.144.0/22\n103.95.152.0/22\n103.95.216.0/21\n103.95.224.0/22\n103.95.236.0/22\n103.95.240.0/20\n103.96.8.0/22\n103.96.124.0/22\n103.96.136.0/22\n103.96.152.0/21\n103.96.160.0/19\n103.96.192.0/20\n103.96.208.0/21\n103.96.216.0/22\n103.97.40.0/22\n103.97.60.0/23\n103.97.112.0/21\n103.97.148.0/22\n103.97.188.0/22\n103.97.192.0/22\n103.98.40.0/21\n103.98.48.0/22\n103.98.56.0/22\n103.98.80.0/22\n103.98.88.0/22\n103.98.100.0/22\n103.98.124.0/24\n103.98.126.0/23\n103.98.136.0/21\n103.98.144.0/22\n103.98.164.0/22\n103.98.168.0/22\n103.98.180.0/22\n103.98.196.0/22\n103.98.216.0/21\n103.98.224.0/21\n103.98.232.0/22\n103.98.240.0/21\n103.98.248.0/23\n103.98.250.0/24\n103.98.252.0/22\n103.99.56.0/22\n103.99.104.0/22\n103.99.116.0/22\n103.99.120.0/22\n103.99.132.0/22\n103.99.136.0/21\n103.99.144.0/22\n103.99.152.0/22\n103.99.220.0/22\n103.99.232.0/21\n103.100.0.0/22\n103.100.32.0/22\n103.100.40.0/22\n103.100.48.0/22\n103.100.56.0/22\n103.100.64.0/22\n103.100.88.0/22\n103.100.116.0/22\n103.100.144.0/22\n103.100.240.0/22\n103.100.248.0/21\n103.101.4.0/22\n103.101.8.0/21\n103.101.60.0/22\n103.101.121.0/24\n103.101.122.0/23\n103.101.124.0/24\n103.101.126.0/23\n103.101.144.0/21\n103.101.180.0/22\n103.101.184.0/22\n103.102.76.0/22\n103.102.80.0/22\n103.102.168.0/21\n103.102.180.0/22\n103.102.184.0/21\n103.102.192.0/22\n103.102.196.0/24\n103.102.200.0/22\n103.102.208.0/21\n103.103.12.0/22\n103.103.16.0/22\n103.103.36.0/22\n103.103.72.0/22\n103.103.188.0/22\n103.103.204.0/22\n103.104.36.0/22\n103.104.40.0/22\n103.104.64.0/22\n103.104.152.0/22\n103.104.252.0/22\n103.105.0.0/21\n103.105.12.0/22\n103.105.16.0/22\n103.105.60.0/22\n103.105.116.0/22\n103.105.180.0/22\n103.105.184.0/22\n103.105.200.0/21\n103.105.220.0/22\n103.106.36.0/22\n103.106.40.0/21\n103.106.60.0/22\n103.106.68.0/22\n103.106.96.0/22\n103.106.120.0/22\n103.106.128.0/21\n103.106.190.0/23\n103.106.196.0/22\n103.106.212.0/22\n103.106.252.0/22\n103.107.0.0/22\n103.107.28.0/22\n103.107.32.0/22\n103.107.44.0/22\n103.107.72.0/22\n103.107.164.0/22\n103.107.168.0/22\n103.107.188.0/22\n103.107.192.0/22\n103.107.208.0/20\n103.108.52.0/22\n103.108.160.0/21\n103.108.194.0/24\n103.108.196.0/22\n103.108.208.0/21\n103.108.224.0/22\n103.108.244.0/22\n103.108.251.0/24\n103.109.20.0/22\n103.109.48.0/22\n103.109.88.0/22\n103.109.106.0/23\n103.109.248.0/22\n103.110.32.0/22\n103.110.92.0/22\n103.110.119.0/24\n103.110.127.0/24\n103.110.128.0/23\n103.110.131.0/24\n103.110.132.0/22\n103.110.136.0/22\n103.110.156.0/22\n103.110.188.0/22\n103.110.204.0/22\n103.111.64.0/22\n103.111.172.0/22\n103.111.252.0/22\n103.112.72.0/22\n103.112.88.0/21\n103.112.108.0/22\n103.112.112.0/22\n103.112.140.0/22\n103.113.4.0/22\n103.113.144.0/22\n103.113.220.0/22\n103.113.232.0/21\n103.114.4.0/22\n103.114.68.0/22\n103.114.100.0/22\n103.114.148.0/22\n103.114.156.0/23\n103.114.159.0/24\n103.114.212.0/22\n103.114.236.0/22\n103.114.240.0/22\n103.115.52.0/22\n103.115.68.0/22\n103.115.92.0/22\n103.115.120.0/22\n103.115.148.0/22\n103.115.248.0/22\n103.116.76.0/22\n103.116.92.0/22\n103.116.120.0/22\n103.116.128.0/22\n103.116.150.0/23\n103.116.184.0/22\n103.116.220.0/22\n103.116.224.0/21\n103.117.16.0/22\n103.117.88.0/22\n103.117.188.0/22\n103.117.220.0/22\n103.118.19.0/24\n103.118.52.0/22\n103.118.56.0/21\n103.118.64.0/21\n103.118.72.0/22\n103.118.88.0/22\n103.118.173.0/24\n103.119.115.0/24\n103.119.156.0/22\n103.119.180.0/22\n103.119.200.0/22\n103.119.224.0/22\n103.120.52.0/22\n103.120.72.0/22\n103.120.76.0/24\n103.120.88.0/22\n103.120.96.0/22\n103.120.140.0/22\n103.120.196.0/22\n103.120.224.0/22\n103.121.52.0/22\n103.121.160.0/21\n103.121.250.0/24\n103.121.252.0/22\n103.122.48.0/22\n103.122.178.0/23\n103.122.192.0/22\n103.122.240.0/23\n103.122.242.0/24\n103.123.4.0/22\n103.123.56.0/22\n103.123.88.0/21\n103.123.116.0/22\n103.123.176.0/22\n103.123.200.0/21\n103.123.208.0/21\n103.124.24.0/22\n103.124.48.0/22\n103.124.64.0/22\n103.124.212.0/22\n103.124.216.0/22\n103.125.20.0/22\n103.125.44.0/22\n103.125.132.0/22\n103.125.164.0/22\n103.125.196.0/22\n103.125.236.0/22\n103.126.0.0/22\n103.126.16.0/23\n103.126.44.0/22\n103.126.124.0/22\n103.126.128.0/22\n103.129.53.0/24\n103.129.54.0/23\n103.129.148.0/22\n103.130.132.0/22\n103.130.160.0/22\n103.130.228.0/22\n103.131.20.0/22\n103.131.36.0/22\n103.131.152.0/22\n103.131.168.0/22\n103.131.224.0/21\n103.131.240.0/22\n103.132.60.0/22\n103.132.64.0/20\n103.132.80.0/22\n103.132.104.0/21\n103.132.112.0/21\n103.132.120.0/22\n103.132.188.0/22\n103.132.208.0/21\n103.133.12.0/22\n103.133.40.0/22\n103.133.128.0/22\n103.133.232.0/22\n103.134.196.0/22\n103.135.80.0/22\n103.135.124.0/22\n103.135.148.0/22\n103.135.156.0/22\n103.135.160.0/21\n103.135.176.0/22\n103.135.184.0/22\n103.135.192.0/21\n103.135.236.0/22\n103.136.128.0/22\n103.136.232.0/22\n103.137.58.0/23\n103.137.60.0/24\n103.137.136.0/23\n103.137.149.0/24\n103.137.180.0/22\n103.137.236.0/22\n103.138.2.0/23\n103.138.134.0/23\n103.138.208.0/23\n103.138.220.0/23\n103.138.248.0/23\n103.139.22.0/23\n103.139.134.0/23\n103.139.136.0/23\n103.139.172.0/23\n103.139.204.0/23\n103.139.212.0/23\n103.140.14.0/23\n103.140.46.0/23\n103.140.140.0/23\n103.140.144.0/23\n103.140.192.0/23\n103.141.10.0/23\n103.141.58.0/23\n103.141.128.0/23\n103.141.186.0/23\n103.141.242.0/23\n103.142.0.0/23\n103.142.28.0/23\n103.142.58.0/23\n103.142.82.0/23\n103.142.96.0/23\n103.142.122.0/23\n103.142.128.0/23\n103.142.154.0/23\n103.142.156.0/23\n103.142.180.0/23\n103.142.186.0/23\n103.142.220.0/23\n103.142.230.0/24\n103.142.234.0/23\n103.142.238.0/23\n103.143.16.0/22\n103.143.31.0/24\n103.143.74.0/23\n103.143.124.0/23\n103.143.132.0/22\n103.143.174.0/23\n103.143.228.0/23\n103.144.66.0/23\n103.144.70.0/23\n103.144.72.0/23\n103.144.136.0/23\n103.144.158.0/23\n103.145.40.0/22\n103.145.73.0/24\n103.145.80.0/23\n103.145.90.0/23\n103.145.92.0/22\n103.145.98.0/23\n103.145.107.0/24\n103.145.188.0/23\n103.146.6.0/23\n103.146.72.0/23\n103.146.90.0/23\n103.146.126.0/23\n103.146.138.0/23\n103.146.236.0/23\n103.146.252.0/23\n103.147.124.0/23\n103.147.198.0/23\n103.147.206.0/23\n103.148.174.0/23\n103.192.0.0/19\n103.192.48.0/21\n103.192.56.0/22\n103.192.84.0/22\n103.192.88.0/21\n103.192.96.0/20\n103.192.112.0/22\n103.192.128.0/20\n103.192.144.0/22\n103.192.164.0/22\n103.192.188.0/22\n103.192.208.0/21\n103.192.216.0/22\n103.192.252.0/22\n103.193.40.0/21\n103.193.120.0/22\n103.193.140.0/22\n103.193.160.0/22\n103.193.188.0/22\n103.193.192.0/22\n103.193.212.0/22\n103.193.216.0/21\n103.193.224.0/20\n103.194.16.0/22\n103.194.230.0/23\n103.195.112.0/22\n103.195.152.0/22\n103.195.160.0/22\n103.196.64.0/22\n103.196.72.0/22\n103.196.88.0/21\n103.196.96.0/22\n103.196.168.0/22\n103.196.185.0/24\n103.196.186.0/23\n103.197.181.0/24\n103.197.183.0/24\n103.197.228.0/22\n103.197.253.0/24\n103.197.254.0/23\n103.198.20.0/22\n103.198.60.0/22\n103.198.64.0/22\n103.198.72.0/22\n103.198.124.0/22\n103.198.156.0/22\n103.198.180.0/22\n103.198.196.0/22\n103.198.200.0/22\n103.198.216.0/21\n103.198.224.0/20\n103.198.240.0/21\n103.199.164.0/22\n103.199.196.0/22\n103.199.228.0/22\n103.199.252.0/22\n103.200.52.0/22\n103.200.64.0/21\n103.200.136.0/21\n103.200.144.0/20\n103.200.160.0/19\n103.200.192.0/22\n103.200.220.0/22\n103.200.224.0/19\n103.201.0.0/20\n103.201.16.0/21\n103.201.28.0/22\n103.201.32.0/19\n103.201.64.0/22\n103.201.76.0/22\n103.201.80.0/20\n103.201.96.0/20\n103.201.112.0/21\n103.201.120.0/22\n103.201.152.0/21\n103.201.160.0/19\n103.201.192.0/18\n103.202.0.0/19\n103.202.32.0/20\n103.202.56.0/21\n103.202.64.0/18\n103.202.128.0/20\n103.202.144.0/22\n103.202.152.0/21\n103.202.160.0/19\n103.202.192.0/20\n103.202.212.0/22\n103.202.228.0/22\n103.202.236.0/22\n103.202.240.0/20\n103.203.0.0/19\n103.203.32.0/22\n103.203.96.0/19\n103.203.128.0/22\n103.203.140.0/22\n103.203.164.0/22\n103.203.168.0/22\n103.203.192.0/22\n103.203.200.0/22\n103.203.212.0/22\n103.203.216.0/22\n103.204.24.0/22\n103.204.88.0/22\n103.204.112.0/22\n103.204.136.0/21\n103.204.144.0/21\n103.204.152.0/22\n103.204.196.0/22\n103.204.232.0/21\n103.205.4.0/22\n103.205.40.0/21\n103.205.52.0/22\n103.205.108.0/22\n103.205.116.0/22\n103.205.120.0/24\n103.205.136.0/22\n103.205.162.0/24\n103.205.188.0/22\n103.205.192.0/21\n103.205.200.0/22\n103.205.236.0/22\n103.205.248.0/21\n103.206.0.0/22\n103.206.44.0/22\n103.206.148.0/22\n103.207.104.0/22\n103.207.184.0/21\n103.207.192.0/20\n103.207.208.0/21\n103.207.220.0/22\n103.207.228.0/22\n103.207.232.0/22\n103.208.12.0/22\n103.208.16.0/22\n103.208.28.0/22\n103.208.48.0/22\n103.208.148.0/22\n103.209.112.0/22\n103.209.136.0/22\n103.209.200.0/22\n103.209.208.0/22\n103.209.216.0/22\n103.210.0.0/22\n103.210.96.0/22\n103.210.156.0/22\n103.210.160.0/19\n103.210.217.0/24\n103.210.218.0/23\n103.211.44.0/22\n103.211.96.0/23\n103.211.98.0/24\n103.211.100.0/22\n103.211.156.0/22\n103.211.165.0/24\n103.211.168.0/22\n103.211.220.0/22\n103.211.248.0/22\n103.212.0.0/20\n103.212.44.0/22\n103.212.48.0/22\n103.212.84.0/22\n103.212.100.0/22\n103.212.148.0/22\n103.212.164.0/22\n103.212.196.0/22\n103.212.200.0/22\n103.212.252.0/22\n103.213.40.0/21\n103.213.48.0/20\n103.213.64.0/19\n103.213.96.0/22\n103.213.132.0/22\n103.213.136.0/21\n103.213.144.0/20\n103.213.160.0/19\n103.213.252.0/22\n103.214.48.0/22\n103.214.84.0/22\n103.214.212.0/22\n103.214.240.0/21\n103.215.28.0/22\n103.215.32.0/21\n103.215.44.0/22\n103.215.100.0/23\n103.215.108.0/22\n103.215.116.0/22\n103.215.120.0/22\n103.215.140.0/22\n103.216.4.0/22\n103.216.8.0/21\n103.216.16.0/20\n103.216.32.0/20\n103.216.64.0/22\n103.216.108.0/22\n103.216.136.0/22\n103.216.152.0/22\n103.216.224.0/21\n103.216.240.0/20\n103.217.0.0/18\n103.217.168.0/22\n103.217.180.0/22\n103.217.184.0/21\n103.217.192.0/20\n103.218.8.0/21\n103.218.16.0/21\n103.218.29.0/24\n103.218.30.0/23\n103.218.32.0/19\n103.218.64.0/19\n103.218.192.0/20\n103.218.208.0/21\n103.218.216.0/22\n103.219.24.0/21\n103.219.32.0/21\n103.219.64.0/22\n103.219.84.0/22\n103.219.88.0/21\n103.219.96.0/21\n103.219.176.0/22\n103.219.184.0/22\n103.220.48.0/20\n103.220.64.0/22\n103.220.92.0/22\n103.220.96.0/22\n103.220.104.0/21\n103.220.116.0/22\n103.220.120.0/21\n103.220.128.0/20\n103.220.144.0/21\n103.220.152.0/22\n103.220.160.0/19\n103.220.192.0/21\n103.220.200.0/22\n103.220.240.0/20\n103.221.0.0/19\n103.221.32.0/21\n103.221.88.0/21\n103.221.96.0/19\n103.221.128.0/18\n103.221.192.0/20\n103.222.0.0/20\n103.222.16.0/22\n103.222.24.0/21\n103.222.33.0/24\n103.222.34.0/23\n103.222.36.0/22\n103.222.40.0/21\n103.222.48.0/20\n103.222.64.0/18\n103.222.128.0/18\n103.222.192.0/19\n103.222.224.0/21\n103.222.232.0/22\n103.222.240.0/21\n103.223.16.0/20\n103.223.32.0/19\n103.223.64.0/19\n103.223.96.0/20\n103.223.112.0/21\n103.223.124.0/22\n103.223.128.0/21\n103.223.140.0/22\n103.223.144.0/20\n103.223.160.0/20\n103.223.176.0/21\n103.223.188.0/22\n103.223.192.0/18\n103.224.0.0/22\n103.224.40.0/21\n103.224.60.0/22\n103.224.220.0/22\n103.224.224.0/21\n103.224.232.0/22\n103.226.40.0/22\n103.226.56.0/21\n103.226.80.0/22\n103.226.116.0/22\n103.226.132.0/22\n103.226.156.0/22\n103.226.180.0/22\n103.226.196.0/22\n103.227.48.0/22\n103.227.72.0/21\n103.227.80.0/22\n103.227.100.0/22\n103.227.120.0/22\n103.227.132.0/22\n103.227.136.0/22\n103.227.196.0/22\n103.227.204.0/23\n103.227.206.0/24\n103.227.212.0/22\n103.227.228.0/22\n103.228.12.0/22\n103.228.88.0/22\n103.228.136.0/22\n103.228.160.0/22\n103.228.176.0/22\n103.228.204.0/22\n103.228.208.0/22\n103.228.228.0/22\n103.228.232.0/22\n103.229.20.0/22\n103.229.136.0/22\n103.229.148.0/22\n103.229.172.0/22\n103.229.212.0/22\n103.229.216.0/21\n103.229.228.0/22\n103.229.236.0/22\n103.229.240.0/22\n103.230.0.0/22\n103.230.28.0/22\n103.230.40.0/21\n103.230.96.0/22\n103.230.196.0/22\n103.230.200.0/21\n103.230.212.0/22\n103.230.236.0/22\n103.231.16.0/21\n103.231.64.0/21\n103.231.144.0/22\n103.231.180.0/22\n103.231.244.0/22\n103.232.4.0/22\n103.232.17.168/29\n103.232.144.0/22\n103.233.4.0/22\n103.233.44.0/22\n103.233.52.0/22\n103.233.104.0/22\n103.233.128.0/22\n103.233.136.0/22\n103.233.228.0/22\n103.234.0.0/22\n103.234.20.0/22\n103.234.56.0/22\n103.234.124.0/22\n103.234.128.0/22\n103.234.172.0/22\n103.234.180.0/22\n103.235.56.0/21\n103.235.80.0/22\n103.235.85.0/24\n103.235.86.0/23\n103.235.128.0/20\n103.235.144.0/21\n103.235.184.0/22\n103.235.192.0/22\n103.235.200.0/22\n103.235.220.0/22\n103.235.224.0/19\n103.236.0.0/18\n103.236.64.0/19\n103.236.96.0/22\n103.236.120.0/22\n103.236.184.0/22\n103.236.240.0/20\n103.237.0.0/20\n103.237.24.0/21\n103.237.68.0/22\n103.237.88.0/22\n103.237.152.0/22\n103.237.176.0/20\n103.237.192.0/18\n103.238.0.0/21\n103.238.18.0/23\n103.238.20.0/22\n103.238.24.0/21\n103.238.32.0/20\n103.238.48.0/21\n103.238.56.0/22\n103.238.88.0/21\n103.238.96.0/22\n103.238.132.0/22\n103.238.140.0/22\n103.238.144.0/22\n103.238.160.0/22\n103.238.165.0/24\n103.238.166.0/23\n103.238.168.0/21\n103.238.176.0/20\n103.238.196.0/22\n103.238.204.0/22\n103.238.252.0/22\n103.239.0.0/22\n103.239.44.0/22\n103.239.68.0/22\n103.239.152.0/21\n103.239.180.0/22\n103.239.184.0/22\n103.239.192.0/21\n103.239.204.0/22\n103.239.208.0/22\n103.239.224.0/22\n103.239.244.0/22\n103.240.16.0/22\n103.240.36.0/22\n103.240.72.0/22\n103.240.84.0/22\n103.240.124.0/22\n103.240.172.0/22\n103.240.188.0/22\n103.240.244.0/22\n103.241.12.0/22\n103.241.92.0/22\n103.241.96.0/22\n103.241.160.0/22\n103.241.184.0/21\n103.241.220.0/22\n103.242.64.0/23\n103.242.128.0/23\n103.242.160.0/22\n103.242.168.0/21\n103.242.176.0/22\n103.242.200.0/22\n103.242.212.0/22\n103.242.220.0/22\n103.242.240.0/22\n103.243.136.0/22\n103.243.252.0/22\n103.244.16.0/22\n103.244.58.0/23\n103.244.60.0/22\n103.244.64.0/20\n103.244.80.0/21\n103.244.116.0/22\n103.244.164.0/22\n103.244.232.0/22\n103.244.252.0/22\n103.245.23.0/24\n103.245.52.0/22\n103.245.60.0/22\n103.245.80.0/22\n103.245.124.0/22\n103.245.128.0/22\n103.246.8.0/21\n103.246.120.0/21\n103.246.132.0/22\n103.246.152.0/22\n103.247.168.0/21\n103.247.176.0/22\n103.247.200.0/22\n103.247.212.0/22\n103.248.64.0/23\n103.248.100.0/22\n103.248.124.0/22\n103.248.152.0/22\n103.248.168.0/22\n103.248.192.0/22\n103.248.212.0/22\n103.248.224.0/21\n103.249.8.0/21\n103.249.52.0/22\n103.249.128.0/22\n103.249.136.0/22\n103.249.144.0/22\n103.249.164.0/22\n103.249.168.0/21\n103.249.176.0/22\n103.249.188.0/22\n103.249.192.0/22\n103.249.244.0/22\n103.249.252.0/22\n103.250.32.0/22\n103.250.104.0/22\n103.250.124.0/22\n103.250.180.0/22\n103.250.192.0/22\n103.250.216.0/22\n103.250.224.0/22\n103.250.236.0/22\n103.250.248.0/21\n103.251.32.0/22\n103.251.84.0/22\n103.251.96.0/22\n103.251.124.0/22\n103.251.160.0/22\n103.251.192.0/22\n103.251.204.0/22\n103.251.240.0/22\n103.252.28.0/22\n103.252.36.0/22\n103.252.64.0/22\n103.252.96.0/22\n103.252.104.0/22\n103.252.172.0/22\n103.252.204.0/22\n103.252.208.0/22\n103.252.232.0/22\n103.252.248.0/22\n103.253.4.0/22\n103.253.60.0/22\n103.253.204.0/22\n103.253.220.0/22\n103.253.224.0/22\n103.253.232.0/22\n103.254.8.0/22\n103.254.20.0/22\n103.254.64.0/21\n103.254.76.0/22\n103.254.112.0/22\n103.254.176.0/22\n103.254.188.0/22\n103.255.68.0/22\n103.255.88.0/21\n103.255.136.0/21\n103.255.184.0/22\n103.255.200.0/22\n103.255.208.0/22\n103.255.228.0/22\n104.222.196.0/24\n106.0.0.0/24\n106.0.2.0/23\n106.0.4.0/22\n106.0.8.0/21\n106.0.16.0/20\n106.0.44.0/22\n106.0.64.0/18\n106.2.0.0/23\n106.2.3.0/24\n106.2.4.0/22\n106.2.8.0/21\n106.2.16.0/20\n106.2.32.0/19\n106.2.64.0/18\n106.2.128.0/17\n106.3.16.0/20\n106.3.32.0/19\n106.3.64.0/20\n106.3.80.0/22\n106.3.88.0/21\n106.3.96.0/19\n106.3.128.0/19\n106.3.164.0/22\n106.3.168.0/21\n106.3.176.0/20\n106.3.192.0/18\n106.4.0.0/14\n106.8.0.0/15\n106.11.0.0/16\n106.12.0.0/14\n106.16.0.0/12\n106.32.0.0/12\n106.48.0.0/21\n106.48.8.0/22\n106.48.16.0/20\n106.48.32.0/20\n106.48.57.0/24\n106.48.60.0/24\n106.48.63.0/24\n106.48.64.0/18\n106.48.128.0/17\n106.49.1.0/24\n106.49.2.0/23\n106.49.4.0/22\n106.49.8.0/21\n106.49.16.0/20\n106.49.32.0/19\n106.49.64.0/19\n106.49.96.0/24\n106.49.98.0/23\n106.49.100.0/22\n106.49.104.0/21\n106.49.112.0/20\n106.49.128.0/17\n106.50.0.0/16\n106.52.0.0/14\n106.56.0.0/13\n106.74.0.0/16\n106.75.0.0/17\n106.75.128.0/18\n106.75.201.0/24\n106.75.204.0/22\n106.75.208.0/20\n106.75.224.0/19\n106.80.0.0/12\n106.108.0.0/14\n106.112.0.0/12\n106.224.0.0/12\n109.71.4.0/24\n109.244.0.0/16\n110.6.0.0/15\n110.16.0.0/14\n110.34.40.0/21\n110.40.0.0/15\n110.42.0.0/16\n110.43.0.0/18\n110.43.64.0/21\n110.43.72.0/22\n110.43.76.0/23\n110.43.80.0/20\n110.43.96.0/19\n110.43.128.0/17\n110.44.12.0/22\n110.44.144.0/20\n110.48.0.0/16\n110.51.0.0/16\n110.52.0.0/15\n110.56.0.0/13\n110.64.0.0/15\n110.72.0.0/15\n110.75.0.0/16\n110.76.0.0/20\n110.76.16.0/22\n110.76.20.0/24\n110.76.22.0/24\n110.76.24.0/21\n110.76.32.0/19\n110.76.132.0/22\n110.76.156.0/22\n110.76.184.0/22\n110.76.192.0/18\n110.77.0.0/17\n110.80.0.0/13\n110.88.0.0/14\n110.92.68.0/22\n110.93.32.0/19\n110.94.0.0/15\n110.96.0.0/11\n110.152.0.0/14\n110.156.0.0/15\n110.166.0.0/15\n110.172.192.0/18\n110.173.0.0/19\n110.173.32.0/20\n110.173.64.0/19\n110.173.192.0/19\n110.176.0.0/12\n110.192.0.0/11\n110.228.0.0/14\n110.232.32.0/19\n110.236.0.0/15\n110.240.0.0/12\n111.0.0.0/10\n111.66.0.0/16\n111.67.192.0/20\n111.68.64.0/19\n111.72.0.0/13\n111.85.0.0/16\n111.91.192.0/19\n111.92.248.0/21\n111.112.0.0/14\n111.116.0.0/15\n111.118.200.0/21\n111.119.64.0/18\n111.119.128.0/19\n111.120.0.0/14\n111.124.0.0/16\n111.126.0.0/15\n111.128.0.0/11\n111.160.0.0/13\n111.170.0.0/16\n111.172.0.0/14\n111.176.0.0/13\n111.186.0.0/15\n111.192.0.0/12\n111.208.0.0/13\n111.221.28.0/24\n111.221.128.0/17\n111.222.0.0/16\n111.223.4.0/22\n111.223.8.0/21\n111.223.16.0/22\n111.223.240.0/22\n111.223.249.0/24\n111.223.250.0/23\n111.224.0.0/13\n111.235.96.0/19\n111.235.156.0/22\n111.235.160.0/21\n111.235.170.0/23\n111.235.172.0/22\n111.235.176.0/20\n112.0.0.0/10\n112.64.0.0/14\n112.73.64.0/18\n112.74.0.0/16\n112.80.0.0/12\n112.96.0.0/13\n112.109.128.0/17\n112.111.0.0/16\n112.112.0.0/14\n112.116.0.0/15\n112.122.0.0/15\n112.124.0.0/14\n112.128.0.0/14\n112.132.0.0/16\n112.137.48.0/21\n112.192.0.0/14\n112.224.0.0/11\n113.0.0.0/13\n113.8.0.0/15\n113.11.192.0/19\n113.12.0.0/14\n113.16.0.0/15\n113.18.0.0/16\n113.21.232.0/21\n113.24.0.0/14\n113.31.0.0/16\n113.44.0.0/14\n113.48.0.0/14\n113.52.160.0/19\n113.52.228.0/22\n113.54.0.0/15\n113.56.0.0/15\n113.58.0.0/16\n113.59.0.0/17\n113.59.224.0/22\n113.62.0.0/15\n113.64.0.0/10\n113.128.0.0/15\n113.130.96.0/20\n113.130.112.0/21\n113.132.0.0/14\n113.136.0.0/13\n113.194.0.0/15\n113.197.100.0/23\n113.197.102.0/24\n113.197.104.0/22\n113.200.0.0/15\n113.202.0.0/16\n113.204.0.0/14\n113.208.96.0/19\n113.208.128.0/17\n113.209.0.0/16\n113.212.0.0/18\n113.212.100.0/22\n113.212.184.0/21\n113.213.0.0/17\n113.214.0.0/15\n113.218.0.0/15\n113.220.0.0/14\n113.224.0.0/12\n113.240.0.0/13\n113.248.0.0/14\n114.28.0.0/17\n114.28.128.0/18\n114.28.192.0/19\n114.28.232.0/22\n114.28.236.0/23\n114.28.240.0/20\n114.31.64.0/21\n114.54.0.0/15\n114.60.0.0/14\n114.64.0.0/14\n114.68.0.0/16\n114.79.64.0/18\n114.80.0.0/12\n114.96.0.0/13\n114.104.0.0/14\n114.110.0.0/20\n114.110.64.0/18\n114.111.0.0/19\n114.111.160.0/19\n114.112.4.0/22\n114.112.8.0/22\n114.112.24.0/21\n114.112.32.0/19\n114.112.64.0/19\n114.112.96.0/20\n114.112.116.0/22\n114.112.120.0/21\n114.112.136.0/21\n114.112.144.0/20\n114.112.160.0/19\n114.112.192.0/19\n114.113.0.0/17\n114.113.128.0/21\n114.113.140.0/22\n114.113.144.0/20\n114.113.160.0/19\n114.113.196.0/22\n114.113.200.0/21\n114.113.208.0/20\n114.113.224.0/20\n114.114.0.0/15\n114.116.0.0/15\n114.118.0.0/16\n114.119.0.0/17\n114.119.192.0/18\n114.132.0.0/16\n114.135.0.0/16\n114.138.0.0/15\n114.141.64.0/21\n114.141.80.0/21\n114.141.128.0/18\n114.196.0.0/15\n114.198.248.0/21\n114.208.0.0/12\n114.224.0.0/11\n115.24.0.0/14\n115.28.0.0/15\n115.31.64.0/20\n115.32.0.0/14\n115.42.56.0/22\n115.44.0.0/14\n115.48.0.0/12\n115.69.64.0/20\n115.84.0.0/18\n115.84.192.0/19\n115.85.192.0/18\n115.100.0.0/14\n115.104.0.0/14\n115.120.0.0/14\n115.124.16.0/20\n115.148.0.0/14\n115.152.0.0/13\n115.166.64.0/19\n115.168.0.0/16\n115.169.0.0/23\n115.169.3.0/24\n115.169.6.0/24\n115.169.9.0/24\n115.169.14.0/23\n115.169.16.0/20\n115.169.39.0/24\n115.169.42.0/23\n115.169.44.0/22\n115.169.48.0/20\n115.169.64.0/18\n115.169.128.0/17\n115.170.0.0/15\n115.172.0.0/14\n115.180.0.0/14\n115.187.0.0/20\n115.190.0.0/15\n115.192.0.0/11\n115.224.0.0/12\n116.0.8.0/21\n116.0.24.0/21\n116.1.0.0/16\n116.2.0.0/15\n116.4.0.0/14\n116.8.0.0/14\n116.13.0.0/16\n116.16.0.0/12\n116.50.0.0/20\n116.52.0.0/14\n116.56.0.0/15\n116.58.128.0/20\n116.58.208.0/20\n116.60.0.0/14\n116.66.0.0/18\n116.66.64.0/19\n116.66.96.0/20\n116.66.120.0/22\n116.68.136.0/21\n116.68.176.0/21\n116.69.0.0/16\n116.70.0.0/17\n116.76.0.0/14\n116.85.0.0/17\n116.85.128.0/18\n116.85.192.0/19\n116.85.224.0/20\n116.85.240.0/21\n116.85.248.0/23\n116.85.250.0/24\n116.85.252.0/22\n116.89.144.0/20\n116.90.80.0/20\n116.90.184.0/21\n116.95.0.0/16\n116.112.0.0/14\n116.116.0.0/15\n116.128.0.0/10\n116.192.0.0/16\n116.193.16.0/20\n116.193.32.0/19\n116.193.176.0/21\n116.194.0.0/15\n116.196.0.0/21\n116.196.8.0/22\n116.196.12.0/23\n116.196.16.0/20\n116.196.32.0/19\n116.196.64.0/18\n116.196.128.0/18\n116.196.192.0/21\n116.196.200.0/23\n116.196.203.0/24\n116.196.204.0/22\n116.196.208.0/20\n116.196.224.0/19\n116.197.160.0/21\n116.197.180.0/23\n116.198.0.0/16\n116.199.0.0/17\n116.199.128.0/19\n116.204.0.0/17\n116.204.232.0/22\n116.205.0.0/16\n116.207.0.0/16\n116.208.0.0/14\n116.212.160.0/20\n116.213.64.0/18\n116.213.128.0/17\n116.214.32.0/19\n116.214.64.0/20\n116.214.128.0/17\n116.215.0.0/16\n116.216.0.0/14\n116.224.0.0/12\n116.242.0.0/15\n116.244.0.0/14\n116.248.0.0/15\n116.252.0.0/15\n116.254.104.0/21\n116.254.129.0/24\n116.254.130.0/23\n116.254.132.0/22\n116.254.136.0/21\n116.254.144.0/20\n116.254.160.0/19\n116.254.192.0/18\n116.255.128.0/17\n117.8.0.0/13\n117.21.0.0/16\n117.22.0.0/15\n117.24.0.0/13\n117.32.0.0/13\n117.40.0.0/14\n117.44.0.0/15\n117.48.0.0/15\n117.50.0.0/16\n117.51.128.0/23\n117.51.131.0/24\n117.51.132.0/22\n117.51.136.0/21\n117.51.144.0/20\n117.51.160.0/19\n117.51.192.0/18\n117.53.48.0/20\n117.53.176.0/20\n117.57.0.0/16\n117.58.0.0/18\n117.59.0.0/16\n117.60.0.0/14\n117.64.0.0/13\n117.72.0.0/15\n117.74.64.0/19\n117.74.128.0/17\n117.75.0.0/16\n117.76.0.0/14\n117.80.0.0/12\n117.100.0.0/15\n117.103.16.0/20\n117.103.40.0/21\n117.103.72.0/21\n117.103.128.0/20\n117.104.168.0/21\n117.106.0.0/15\n117.112.0.0/13\n117.120.64.0/18\n117.120.128.0/17\n117.121.0.0/19\n117.121.32.0/21\n117.121.40.0/22\n117.121.44.0/23\n117.121.46.0/24\n117.121.48.0/20\n117.121.64.0/18\n117.121.128.0/20\n117.121.148.0/22\n117.121.152.0/21\n117.121.160.0/19\n117.121.192.0/21\n117.122.128.0/17\n117.124.0.0/14\n117.128.0.0/10\n118.24.0.0/15\n118.26.0.0/19\n118.26.36.0/22\n118.26.40.0/21\n118.26.48.0/20\n118.26.64.0/19\n118.26.104.0/21\n118.26.112.0/20\n118.26.128.0/17\n118.28.0.0/15\n118.30.0.0/20\n118.30.16.0/21\n118.30.24.0/22\n118.30.32.0/19\n118.30.64.0/18\n118.30.128.0/17\n118.31.0.0/16\n118.64.0.0/15\n118.66.0.0/16\n118.67.112.0/20\n118.72.0.0/13\n118.80.0.0/15\n118.84.0.0/15\n118.88.32.0/19\n118.88.64.0/18\n118.88.128.0/17\n118.89.0.0/16\n118.102.16.0/20\n118.102.32.0/21\n118.103.164.0/22\n118.103.168.0/21\n118.103.176.0/22\n118.103.245.0/24\n118.103.246.0/23\n118.112.0.0/13\n118.120.0.0/14\n118.124.0.0/15\n118.126.1.0/24\n118.126.2.0/23\n118.126.4.0/22\n118.126.8.0/21\n118.126.16.0/23\n118.126.18.0/24\n118.126.32.0/19\n118.126.64.0/18\n118.126.128.0/17\n118.127.128.0/19\n118.132.0.0/14\n118.144.0.0/14\n118.178.0.0/16\n118.180.0.0/14\n118.184.5.0/24\n118.184.10.0/24\n118.184.115.0/24\n118.184.116.0/22\n118.184.120.0/23\n118.184.122.0/24\n118.184.128.0/18\n118.184.192.0/19\n118.184.240.0/20\n118.186.0.0/15\n118.188.0.0/16\n118.190.0.0/16\n118.191.0.0/20\n118.191.24.0/21\n118.191.32.0/19\n118.191.64.0/18\n118.191.144.0/21\n118.191.153.0/24\n118.191.154.0/23\n118.191.156.0/22\n118.191.160.0/19\n118.191.192.0/20\n118.191.209.0/24\n118.191.210.0/23\n118.191.212.0/22\n118.191.248.0/21\n118.192.0.0/16\n118.193.0.0/22\n118.193.32.0/20\n118.193.56.0/21\n118.193.68.0/22\n118.193.72.0/24\n118.193.77.0/24\n118.193.96.0/19\n118.194.0.0/17\n118.194.128.0/18\n118.194.192.0/19\n118.194.232.0/21\n118.194.240.0/20\n118.195.0.0/16\n118.196.0.0/14\n118.202.0.0/15\n118.204.0.0/14\n118.212.0.0/15\n118.215.192.0/18\n118.224.0.0/14\n118.228.0.0/17\n118.228.128.0/20\n118.228.144.0/21\n118.228.156.0/22\n118.228.160.0/19\n118.228.192.0/18\n118.229.0.0/16\n118.230.0.0/16\n118.239.0.0/16\n118.242.0.0/16\n118.244.0.0/14\n118.248.0.0/13\n119.0.0.0/15\n119.2.0.0/19\n119.2.128.0/17\n119.3.0.0/16\n119.4.0.0/14\n119.10.0.0/17\n119.15.136.0/21\n119.16.0.0/16\n119.18.192.0/20\n119.18.208.0/21\n119.18.224.0/19\n119.19.0.0/16\n119.20.0.0/14\n119.27.64.0/18\n119.27.128.0/17\n119.28.28.0/24\n119.29.0.0/16\n119.30.48.0/20\n119.31.192.0/19\n119.32.0.0/14\n119.36.0.0/15\n119.38.0.0/17\n119.38.128.0/18\n119.38.192.0/20\n119.38.208.0/22\n119.38.212.0/23\n119.38.214.0/27\n119.38.214.56/29\n119.38.214.64/26\n119.38.214.128/25\n119.38.215.0/24\n119.38.216.0/21\n119.39.0.0/16\n119.40.0.0/18\n119.40.64.0/20\n119.40.128.0/17\n119.41.0.0/16\n119.42.0.0/19\n119.42.52.0/22\n119.42.128.0/20\n119.42.224.0/19\n119.44.0.0/15\n119.48.0.0/13\n119.57.0.0/16\n119.58.0.0/16\n119.59.128.0/17\n119.60.0.0/15\n119.62.0.0/16\n119.63.32.0/19\n119.75.208.0/20\n119.78.0.0/15\n119.80.0.0/16\n119.82.208.0/20\n119.84.0.0/14\n119.88.0.0/16\n119.89.0.0/17\n119.89.128.0/21\n119.89.136.0/23\n119.89.139.0/24\n119.89.140.0/22\n119.89.144.0/20\n119.89.160.0/20\n119.89.176.0/22\n119.89.180.0/23\n119.89.183.0/24\n119.89.184.0/21\n119.89.192.0/23\n119.89.194.0/24\n119.89.196.0/22\n119.89.200.0/21\n119.89.208.0/21\n119.89.217.0/24\n119.89.218.0/23\n119.89.220.0/22\n119.89.224.0/19\n119.90.0.0/15\n119.96.0.0/13\n119.108.0.0/15\n119.112.0.0/12\n119.128.0.0/12\n119.144.0.0/14\n119.148.160.0/19\n119.151.192.0/18\n119.160.200.0/21\n119.161.120.0/21\n119.161.128.0/21\n119.161.160.0/19\n119.161.192.0/18\n119.162.0.0/15\n119.164.0.0/14\n119.176.0.0/12\n119.232.0.0/15\n119.235.128.0/19\n119.235.160.0/20\n119.235.184.0/22\n119.248.0.0/14\n119.252.96.0/21\n119.252.240.0/21\n119.252.249.0/24\n119.252.252.0/23\n119.253.0.0/16\n119.254.0.0/15\n120.0.0.0/12\n120.24.0.0/14\n120.30.0.0/15\n120.32.0.0/12\n120.48.0.0/15\n120.52.0.0/14\n120.64.0.0/13\n120.72.32.0/19\n120.72.128.0/17\n120.76.0.0/14\n120.80.0.0/13\n120.88.8.0/21\n120.90.0.0/15\n120.92.0.0/17\n120.92.128.0/18\n120.92.192.0/22\n120.92.198.0/23\n120.92.200.0/21\n120.92.208.0/20\n120.92.224.0/19\n120.94.0.0/15\n120.128.0.0/13\n120.136.16.0/21\n120.136.128.0/18\n120.137.0.0/17\n120.143.128.0/19\n120.192.0.0/10\n121.0.8.0/21\n121.0.16.0/20\n121.4.0.0/15\n121.8.0.0/13\n121.16.0.0/12\n121.32.0.0/13\n121.40.0.0/14\n121.46.0.0/18\n121.46.76.0/22\n121.46.128.0/17\n121.47.0.0/16\n121.48.0.0/15\n121.50.8.0/21\n121.51.0.0/16\n121.52.160.0/19\n121.52.208.0/20\n121.52.224.0/19\n121.54.176.0/21\n121.55.0.0/18\n121.56.0.0/15\n121.58.0.0/17\n121.58.136.0/21\n121.58.144.0/20\n121.58.160.0/21\n121.59.0.0/16\n121.60.0.0/14\n121.68.0.0/14\n121.76.0.0/15\n121.79.128.0/18\n121.89.0.0/16\n121.100.128.0/17\n121.101.0.0/18\n121.101.208.0/20\n121.192.0.0/13\n121.200.192.0/21\n121.201.0.0/16\n121.204.0.0/14\n121.224.0.0/12\n121.248.0.0/14\n121.255.0.0/16\n122.0.64.0/18\n122.0.128.0/17\n122.4.0.0/14\n122.10.132.0/23\n122.10.136.0/23\n122.10.196.0/23\n122.10.216.0/22\n122.10.228.0/22\n122.10.232.0/21\n122.10.240.0/21\n122.10.248.0/22\n122.11.0.0/17\n122.12.0.0/15\n122.14.0.0/17\n122.14.192.0/18\n122.48.0.0/16\n122.49.0.0/18\n122.51.0.0/16\n122.64.0.0/11\n122.96.0.0/15\n122.98.144.0/20\n122.98.160.0/21\n122.98.172.0/22\n122.98.176.0/20\n122.98.192.0/21\n122.98.232.0/21\n122.98.240.0/20\n122.102.0.0/20\n122.102.64.0/19\n122.112.0.0/18\n122.112.64.0/19\n122.112.96.0/22\n122.112.107.0/24\n122.112.118.0/24\n122.112.122.0/24\n122.112.125.0/24\n122.112.128.0/17\n122.113.0.0/16\n122.114.0.0/16\n122.115.0.0/18\n122.115.80.0/20\n122.115.96.0/19\n122.115.128.0/17\n122.119.0.0/16\n122.128.100.0/22\n122.128.120.0/21\n122.136.0.0/13\n122.144.128.0/17\n122.152.192.0/18\n122.156.0.0/14\n122.188.0.0/14\n122.192.0.0/14\n122.198.0.0/16\n122.200.40.0/21\n122.200.64.0/18\n122.201.48.0/20\n122.204.0.0/14\n122.224.0.0/12\n122.240.0.0/13\n122.248.24.0/21\n122.248.48.0/20\n122.255.64.0/21\n123.0.128.0/21\n123.0.136.0/23\n123.0.139.0/24\n123.0.140.0/22\n123.0.144.0/20\n123.0.160.0/19\n123.4.0.0/14\n123.8.0.0/13\n123.49.130.0/23\n123.49.132.0/22\n123.49.136.0/22\n123.49.152.0/21\n123.49.160.0/19\n123.49.192.0/18\n123.50.160.0/19\n123.52.0.0/14\n123.56.0.0/15\n123.58.0.0/18\n123.58.64.0/20\n123.58.80.0/21\n123.58.88.0/22\n123.58.96.0/19\n123.58.128.0/17\n123.59.0.0/16\n123.61.0.0/16\n123.62.0.0/16\n123.64.0.0/11\n123.96.0.0/15\n123.98.0.0/17\n123.99.128.0/17\n123.100.0.0/19\n123.100.232.0/24\n123.101.0.0/16\n123.103.0.0/20\n123.103.16.0/21\n123.103.24.0/22\n123.103.28.0/23\n123.103.30.0/24\n123.103.32.0/19\n123.103.64.0/18\n123.108.134.0/24\n123.108.138.0/23\n123.108.140.0/24\n123.108.142.0/24\n123.108.208.0/20\n123.112.0.0/12\n123.128.0.0/13\n123.137.0.0/16\n123.138.0.0/15\n123.144.0.0/12\n123.160.0.0/12\n123.176.60.0/22\n123.176.80.0/20\n123.177.0.0/16\n123.178.0.0/15\n123.180.0.0/14\n123.184.0.0/13\n123.196.0.0/15\n123.199.128.0/17\n123.206.0.0/15\n123.232.0.0/14\n123.242.0.0/17\n123.242.192.0/21\n123.244.0.0/14\n123.249.0.0/16\n123.253.109.0/24\n123.253.110.0/24\n123.253.240.0/22\n123.254.96.0/21\n124.6.64.0/18\n124.14.0.0/15\n124.16.0.0/15\n124.20.0.0/14\n124.28.192.0/18\n124.29.0.0/17\n124.31.0.0/16\n124.40.112.0/20\n124.40.128.0/18\n124.40.192.0/19\n124.40.240.0/22\n124.42.0.0/16\n124.47.0.0/18\n124.64.0.0/15\n124.66.0.0/17\n124.67.0.0/16\n124.68.0.0/17\n124.68.128.0/18\n124.68.192.0/19\n124.68.224.0/20\n124.68.240.0/23\n124.68.242.0/24\n124.68.244.0/23\n124.68.254.0/23\n124.69.0.0/16\n124.70.0.0/15\n124.72.0.0/13\n124.88.0.0/13\n124.108.8.0/21\n124.108.40.0/21\n124.109.96.0/21\n124.112.0.0/14\n124.116.0.0/15\n124.118.0.0/16\n124.119.0.0/17\n124.119.128.0/18\n124.119.192.0/19\n124.119.224.0/20\n124.119.240.0/22\n124.119.244.0/23\n124.119.246.0/25\n124.119.246.128/26\n124.119.246.192/27\n124.119.246.224/28\n124.119.246.240/29\n124.119.246.248/30\n124.119.246.254/31\n124.119.247.0/24\n124.119.248.0/21\n124.126.0.0/15\n124.128.0.0/13\n124.147.128.0/17\n124.150.137.0/24\n124.151.0.0/16\n124.152.0.0/16\n124.160.0.0/13\n124.172.0.0/14\n124.192.0.0/15\n124.196.0.0/16\n124.200.0.0/13\n124.220.0.0/14\n124.224.0.0/12\n124.240.0.0/17\n124.240.128.0/18\n124.242.0.0/16\n124.243.192.0/18\n124.248.0.0/17\n124.249.0.0/16\n124.250.0.0/15\n124.254.0.0/18\n125.31.192.0/18\n125.32.0.0/12\n125.58.128.0/17\n125.61.128.0/17\n125.62.0.0/18\n125.64.0.0/11\n125.96.0.0/15\n125.98.0.0/16\n125.104.0.0/13\n125.112.0.0/12\n125.169.0.0/16\n125.171.0.0/16\n125.208.0.0/19\n125.208.37.0/24\n125.208.40.0/24\n125.208.45.0/24\n125.208.46.0/23\n125.208.48.0/20\n125.210.0.0/15\n125.213.0.0/17\n125.214.96.0/19\n125.215.0.0/18\n125.216.0.0/13\n125.254.128.0/17\n128.108.0.0/16\n129.28.0.0/16\n129.204.0.0/16\n129.211.0.0/16\n129.223.254.0/24\n129.227.99.0/24\n130.36.146.0/23\n130.214.218.0/23\n131.228.96.0/24\n131.253.12.0/29\n131.253.12.80/28\n131.253.12.240/29\n132.232.0.0/16\n132.237.134.0/24\n132.237.150.0/24\n134.175.0.0/16\n135.159.208.0/20\n135.244.80.0/20\n137.59.59.0/24\n137.59.88.0/22\n138.32.244.0/22\n139.5.56.0/21\n139.5.80.0/22\n139.5.92.0/22\n139.5.128.0/22\n139.5.160.0/22\n139.5.192.0/22\n139.5.204.0/22\n139.5.244.0/22\n139.9.0.0/16\n139.129.0.0/16\n139.138.238.0/28\n139.148.0.0/16\n139.155.0.0/16\n139.159.0.0/19\n139.159.32.0/21\n139.159.40.0/22\n139.159.52.0/22\n139.159.56.0/21\n139.159.64.0/19\n139.159.96.0/20\n139.159.112.0/22\n139.159.116.0/23\n139.159.120.0/21\n139.159.128.0/17\n139.170.0.0/16\n139.176.0.0/16\n139.183.0.0/16\n139.186.0.0/16\n139.189.0.0/16\n139.196.0.0/15\n139.198.0.0/21\n139.198.8.0/23\n139.198.11.0/24\n139.198.12.0/22\n139.198.16.0/20\n139.198.32.0/19\n139.198.66.0/23\n139.198.68.0/22\n139.198.72.0/21\n139.198.80.0/20\n139.198.96.0/20\n139.198.113.0/24\n139.198.114.0/23\n139.198.116.0/22\n139.198.122.0/23\n139.198.124.0/22\n139.198.128.0/17\n139.199.0.0/16\n139.200.0.0/13\n139.208.0.0/13\n139.217.0.0/16\n139.219.0.0/16\n139.220.0.0/17\n139.220.128.0/18\n139.220.192.0/22\n139.220.196.0/23\n139.220.200.0/21\n139.220.208.0/23\n139.220.212.0/22\n139.220.216.0/21\n139.220.224.0/19\n139.221.0.0/16\n139.224.0.0/16\n139.226.0.0/15\n140.75.0.0/16\n140.101.208.0/24\n140.143.0.0/16\n140.179.0.0/16\n140.205.0.0/18\n140.205.64.0/19\n140.205.96.0/20\n140.205.112.0/21\n140.205.120.0/23\n140.205.123.0/24\n140.205.124.0/22\n140.205.128.0/17\n140.206.0.0/15\n140.210.0.0/16\n140.224.0.0/16\n140.237.0.0/16\n140.240.0.0/16\n140.242.223.0/24\n140.242.224.0/24\n140.243.0.0/16\n140.246.0.0/16\n140.249.0.0/16\n140.250.0.0/16\n140.255.0.0/16\n144.0.0.0/16\n144.7.0.0/16\n144.12.0.0/16\n144.36.146.0/23\n144.48.64.0/22\n144.48.88.0/22\n144.48.156.0/22\n144.48.180.0/22\n144.48.184.0/22\n144.48.204.0/22\n144.48.208.0/21\n144.52.0.0/16\n144.123.0.0/16\n144.211.80.0/24\n144.211.138.0/24\n144.255.0.0/16\n146.56.192.0/18\n146.196.56.0/22\n146.196.68.0/22\n146.196.92.0/22\n146.196.112.0/21\n146.196.124.0/22\n146.217.137.0/24\n146.222.79.0/24\n146.222.81.0/24\n146.222.94.0/24\n147.243.13.32/27\n147.243.13.64/27\n147.243.14.32/27\n148.70.0.0/16\n150.0.0.0/16\n150.115.0.0/16\n150.121.0.0/16\n150.122.0.0/16\n150.129.136.0/22\n150.129.192.0/22\n150.129.252.0/22\n150.138.0.0/15\n150.158.0.0/16\n150.222.88.0/23\n150.223.0.0/16\n150.242.0.0/21\n150.242.8.0/22\n150.242.28.0/22\n150.242.44.0/22\n150.242.48.0/21\n150.242.56.0/22\n150.242.76.0/22\n150.242.80.0/22\n150.242.92.0/22\n150.242.96.0/22\n150.242.112.0/21\n150.242.120.0/22\n150.242.152.0/22\n150.242.158.0/24\n150.242.160.0/21\n150.242.168.0/22\n150.242.184.0/21\n150.242.192.0/22\n150.242.224.0/22\n150.242.232.0/21\n150.242.240.0/21\n150.242.248.0/22\n150.255.0.0/16\n152.32.178.0/23\n152.104.128.0/17\n152.136.0.0/16\n153.0.0.0/16\n153.3.0.0/16\n153.34.0.0/15\n153.36.0.0/15\n153.99.0.0/16\n153.101.0.0/16\n153.118.0.0/15\n154.8.128.0/17\n155.126.176.0/23\n156.107.160.0/24\n156.107.170.0/24\n156.107.179.0/24\n156.107.181.0/24\n156.154.62.0/23\n157.0.0.0/16\n157.18.0.0/16\n157.61.0.0/16\n157.119.8.0/21\n157.119.16.0/22\n157.119.28.0/22\n157.119.132.0/22\n157.119.136.0/21\n157.119.144.0/20\n157.119.160.0/21\n157.119.172.0/22\n157.119.192.0/21\n157.119.240.0/22\n157.119.252.0/22\n157.122.0.0/16\n157.133.186.0/23\n157.133.192.0/21\n157.133.212.0/24\n157.133.236.0/24\n157.148.0.0/16\n157.156.0.0/16\n157.255.0.0/16\n159.75.0.0/16\n159.221.232.0/22\n159.226.0.0/16\n160.19.208.0/21\n160.19.216.0/22\n160.20.48.0/22\n160.62.10.0/24\n160.83.109.0/24\n160.83.110.0/23\n160.202.60.0/23\n160.202.62.0/24\n160.202.148.0/22\n160.202.152.0/22\n160.202.212.0/22\n160.202.216.0/21\n160.202.224.0/19\n160.238.64.0/22\n161.163.0.0/21\n161.163.28.0/23\n161.163.176.0/24\n161.163.178.0/23\n161.163.180.0/22\n161.189.0.0/16\n161.207.0.0/16\n162.14.0.0/16\n162.105.0.0/16\n163.0.0.0/16\n163.47.4.0/22\n163.53.0.0/20\n163.53.36.0/22\n163.53.40.0/22\n163.53.48.0/20\n163.53.64.0/22\n163.53.88.0/21\n163.53.96.0/19\n163.53.128.0/21\n163.53.136.0/22\n163.53.160.0/20\n163.53.188.0/22\n163.53.220.0/22\n163.53.236.0/22\n163.53.240.0/22\n163.116.202.0/23\n163.125.0.0/16\n163.142.0.0/16\n163.177.0.0/16\n163.179.0.0/16\n163.204.0.0/16\n163.244.246.0/24\n164.52.80.0/24\n165.156.30.0/24\n166.111.0.0/16\n167.139.0.0/16\n167.189.0.0/16\n167.220.244.0/22\n168.159.144.0/21\n168.159.152.0/22\n168.159.156.0/23\n168.159.158.0/24\n168.160.0.0/16\n168.230.0.0/24\n170.179.0.0/16\n170.225.224.0/23\n170.252.152.0/21\n171.8.0.0/13\n171.22.147.0/24\n171.34.0.0/15\n171.36.0.0/14\n171.40.0.0/13\n171.80.0.0/12\n171.104.0.0/13\n171.112.0.0/12\n171.208.0.0/12\n172.60.2.0/24\n172.81.192.0/18\n173.39.200.0/23\n175.0.0.0/12\n175.16.0.0/13\n175.24.0.0/14\n175.30.0.0/15\n175.42.0.0/15\n175.44.0.0/16\n175.46.0.0/15\n175.48.0.0/12\n175.64.0.0/11\n175.102.0.0/16\n175.106.128.0/17\n175.111.144.0/20\n175.111.160.0/20\n175.111.184.0/22\n175.146.0.0/15\n175.148.0.0/14\n175.152.0.0/14\n175.158.96.0/22\n175.160.0.0/12\n175.176.156.0/22\n175.176.188.0/22\n175.178.0.0/16\n175.184.128.0/18\n175.185.0.0/16\n175.186.0.0/15\n175.188.0.0/14\n180.76.16.0/20\n180.76.32.0/19\n180.76.64.0/18\n180.76.128.0/18\n180.76.192.0/19\n180.76.224.0/20\n180.76.240.0/24\n180.76.242.0/23\n180.76.244.0/22\n180.76.248.0/22\n180.76.252.0/23\n180.76.255.0/24\n180.77.0.0/16\n180.78.0.0/15\n180.84.0.0/15\n180.86.0.0/16\n180.88.0.0/14\n180.94.56.0/21\n180.94.96.0/20\n180.94.120.0/21\n180.95.128.0/17\n180.96.0.0/11\n180.129.128.0/17\n180.130.0.0/16\n180.136.0.0/13\n180.148.16.0/21\n180.148.152.0/21\n180.148.216.0/21\n180.148.224.0/19\n180.149.128.0/19\n180.150.160.0/21\n180.150.176.0/20\n180.152.0.0/13\n180.160.0.0/12\n180.178.112.0/21\n180.178.192.0/18\n180.184.0.0/14\n180.188.0.0/17\n180.189.148.0/22\n180.200.252.0/22\n180.201.0.0/16\n180.202.0.0/15\n180.208.0.0/15\n180.210.212.0/22\n180.210.233.0/24\n180.210.236.0/22\n180.212.0.0/15\n180.222.224.0/19\n180.223.0.0/19\n180.223.32.0/20\n180.223.48.0/21\n180.223.57.0/24\n180.223.58.0/23\n180.223.60.0/22\n180.223.80.0/20\n180.223.96.0/19\n180.223.128.0/17\n180.233.0.0/18\n180.233.64.0/19\n180.233.144.0/22\n180.235.64.0/19\n180.235.112.0/22\n182.16.144.0/21\n182.16.192.0/19\n182.18.0.0/17\n182.23.184.0/21\n182.23.200.0/21\n182.32.0.0/12\n182.48.96.0/19\n182.49.0.0/16\n182.50.0.0/22\n182.50.8.0/21\n182.50.112.0/20\n182.51.0.0/16\n182.54.0.0/17\n182.61.0.0/18\n182.61.128.0/19\n182.61.192.0/18\n182.80.0.0/13\n182.88.0.0/14\n182.92.0.0/16\n182.96.0.0/11\n182.128.0.0/12\n182.144.0.0/13\n182.157.0.0/16\n182.160.64.0/19\n182.174.0.0/15\n182.200.0.0/13\n182.236.128.0/17\n182.237.24.0/21\n182.238.0.0/16\n182.239.0.0/19\n182.240.0.0/13\n182.254.0.0/17\n182.254.128.0/18\n182.254.192.0/19\n182.254.224.0/20\n182.254.240.0/21\n182.254.248.0/23\n182.254.251.0/24\n182.254.252.0/22\n183.0.0.0/10\n183.64.0.0/13\n183.78.160.0/21\n183.78.180.0/22\n183.81.180.0/22\n183.84.0.0/15\n183.91.128.0/22\n183.91.136.0/21\n183.91.144.0/20\n183.92.0.0/14\n183.128.0.0/11\n183.160.0.0/13\n183.168.0.0/15\n183.170.0.0/16\n183.172.0.0/14\n183.184.0.0/13\n183.192.0.0/10\n185.109.236.0/24\n185.216.118.0/24\n188.131.128.0/17\n192.11.23.0/24\n192.11.26.0/24\n192.11.39.0/24\n192.11.236.0/24\n192.23.191.0/24\n192.55.10.0/23\n192.55.40.0/24\n192.55.46.0/24\n192.55.68.0/22\n192.102.204.0/22\n192.124.154.0/24\n192.137.31.0/24\n192.139.136.0/24\n192.140.128.0/21\n192.140.136.0/22\n192.140.156.0/22\n192.140.160.0/19\n192.140.192.0/20\n192.140.208.0/21\n192.144.128.0/17\n192.163.11.0/24\n192.232.97.0/24\n193.9.22.0/24\n193.17.120.0/22\n193.20.64.0/22\n193.112.0.0/16\n193.200.196.0/24\n193.200.222.160/28\n194.138.136.0/24\n194.138.202.0/23\n194.138.245.0/24\n198.175.100.0/22\n198.208.17.0/24\n198.208.19.0/24\n199.7.72.0/24\n199.65.192.0/21\n199.244.144.0/24\n202.0.100.0/23\n202.0.122.0/23\n202.1.105.0/24\n202.1.106.0/24\n202.3.128.0/23\n202.4.128.0/19\n202.4.252.0/22\n202.5.208.0/21\n202.5.216.0/22\n202.6.6.0/23\n202.6.66.0/23\n202.6.72.0/23\n202.6.87.0/24\n202.6.88.0/23\n202.6.92.0/23\n202.6.103.0/24\n202.6.108.0/24\n202.6.110.0/23\n202.6.114.0/24\n202.6.176.0/20\n202.8.0.0/24\n202.8.2.0/23\n202.8.4.0/23\n202.8.12.0/24\n202.8.24.0/24\n202.8.77.0/24\n202.8.128.0/19\n202.8.192.0/20\n202.9.32.0/24\n202.9.34.0/23\n202.9.48.0/23\n202.9.51.0/24\n202.9.52.0/23\n202.9.54.0/24\n202.9.57.0/24\n202.9.58.0/23\n202.10.64.0/21\n202.10.74.0/23\n202.10.76.0/22\n202.10.112.0/20\n202.12.1.0/24\n202.12.2.0/24\n202.12.17.0/24\n202.12.18.0/23\n202.12.72.0/24\n202.12.84.0/23\n202.12.96.0/24\n202.12.98.0/23\n202.12.106.0/24\n202.12.111.0/24\n202.12.116.0/24\n202.14.64.0/23\n202.14.69.0/24\n202.14.73.0/24\n202.14.74.0/23\n202.14.76.0/24\n202.14.78.0/23\n202.14.88.0/24\n202.14.97.0/24\n202.14.104.0/23\n202.14.108.0/23\n202.14.111.0/24\n202.14.114.0/23\n202.14.118.0/23\n202.14.124.0/23\n202.14.127.0/24\n202.14.129.0/24\n202.14.135.0/24\n202.14.136.0/24\n202.14.149.0/24\n202.14.151.0/24\n202.14.157.0/24\n202.14.158.0/23\n202.14.169.0/24\n202.14.170.0/23\n202.14.172.0/22\n202.14.176.0/24\n202.14.184.0/23\n202.14.208.0/23\n202.14.213.0/24\n202.14.219.0/24\n202.14.220.0/24\n202.14.222.0/23\n202.14.225.0/24\n202.14.226.0/23\n202.14.231.0/24\n202.14.235.0/24\n202.14.236.0/22\n202.14.246.0/24\n202.14.251.0/24\n202.20.66.0/24\n202.20.79.0/24\n202.20.87.0/24\n202.20.88.0/23\n202.20.90.0/24\n202.20.94.0/23\n202.20.114.0/24\n202.20.117.0/24\n202.20.120.0/24\n202.20.125.0/24\n202.20.126.0/23\n202.21.48.0/20\n202.21.131.0/24\n202.21.132.0/24\n202.21.141.0/24\n202.21.142.0/24\n202.21.147.0/24\n202.21.148.0/24\n202.21.150.0/23\n202.21.152.0/23\n202.21.154.0/24\n202.21.156.0/24\n202.21.208.0/24\n202.22.248.0/21\n202.27.12.0/24\n202.27.14.0/24\n202.27.136.0/23\n202.36.226.0/24\n202.38.0.0/22\n202.38.8.0/21\n202.38.48.0/20\n202.38.64.0/18\n202.38.128.0/21\n202.38.136.0/23\n202.38.138.0/24\n202.38.140.0/22\n202.38.146.0/23\n202.38.149.0/24\n202.38.150.0/23\n202.38.152.0/22\n202.38.156.0/24\n202.38.158.0/23\n202.38.160.0/23\n202.38.164.0/22\n202.38.168.0/22\n202.38.176.0/23\n202.38.184.0/21\n202.38.192.0/18\n202.40.4.0/23\n202.40.7.0/24\n202.40.15.0/24\n202.40.135.0/24\n202.40.136.0/24\n202.40.140.0/24\n202.40.143.0/24\n202.40.144.0/23\n202.40.150.0/24\n202.40.155.0/24\n202.40.156.0/24\n202.40.158.0/23\n202.40.162.0/24\n202.41.8.0/23\n202.41.11.0/24\n202.41.12.0/23\n202.41.128.0/24\n202.41.130.0/23\n202.41.142.0/24\n202.41.152.0/21\n202.41.192.0/24\n202.41.196.0/22\n202.41.200.0/22\n202.41.240.0/20\n202.43.76.0/22\n202.43.144.0/20\n202.44.16.0/20\n202.44.48.0/22\n202.44.67.0/24\n202.44.74.0/24\n202.44.97.0/24\n202.44.129.0/24\n202.44.132.0/23\n202.44.146.0/23\n202.45.0.0/23\n202.45.2.0/24\n202.45.15.0/24\n202.45.16.0/20\n202.46.16.0/23\n202.46.18.0/24\n202.46.20.0/23\n202.46.128.0/24\n202.46.224.0/20\n202.47.82.0/23\n202.47.96.0/20\n202.47.126.0/24\n202.47.128.0/24\n202.47.130.0/23\n202.52.34.0/24\n202.52.143.0/24\n202.53.140.0/24\n202.53.143.0/24\n202.53.202.0/24\n202.57.212.0/22\n202.57.216.0/22\n202.57.240.0/20\n202.58.0.0/24\n202.58.112.0/22\n202.59.0.0/23\n202.59.212.0/22\n202.59.236.0/24\n202.59.240.0/24\n202.60.48.0/21\n202.60.96.0/21\n202.60.112.0/20\n202.60.132.0/22\n202.60.136.0/21\n202.60.144.0/20\n202.61.68.0/22\n202.61.76.0/22\n202.61.88.0/22\n202.61.123.0/24\n202.61.127.0/24\n202.62.112.0/22\n202.62.248.0/22\n202.62.252.0/24\n202.62.255.0/24\n202.63.80.0/20\n202.63.160.0/19\n202.63.248.0/22\n202.63.253.0/24\n202.65.0.0/21\n202.65.8.0/23\n202.67.0.0/22\n202.69.4.0/23\n202.69.16.0/20\n202.70.0.0/19\n202.70.96.0/20\n202.70.192.0/20\n202.71.32.0/20\n202.72.40.0/21\n202.72.80.0/20\n202.72.112.0/20\n202.73.128.0/22\n202.73.240.0/20\n202.74.8.0/21\n202.74.36.0/24\n202.74.42.0/24\n202.74.52.0/24\n202.74.80.0/20\n202.74.254.0/23\n202.75.208.0/20\n202.75.252.0/22\n202.76.247.0/24\n202.76.252.0/22\n202.77.80.0/21\n202.77.92.0/22\n202.78.8.0/21\n202.79.224.0/21\n202.79.248.0/22\n202.80.192.0/20\n202.81.0.0/22\n202.81.176.0/20\n202.83.252.0/22\n202.84.0.0/20\n202.84.16.0/23\n202.84.22.0/24\n202.84.24.0/21\n202.85.208.0/20\n202.86.249.0/24\n202.87.80.0/20\n202.88.32.0/22\n202.89.8.0/21\n202.89.96.0/22\n202.89.108.0/22\n202.89.119.0/24\n202.89.232.0/21\n202.90.0.0/22\n202.90.16.0/20\n202.90.37.0/24\n202.90.96.0/19\n202.90.193.0/24\n202.90.196.0/24\n202.90.205.0/24\n202.90.224.0/20\n202.91.0.0/22\n202.91.96.0/20\n202.91.128.0/22\n202.91.176.0/20\n202.91.224.0/19\n202.92.0.0/22\n202.92.8.0/21\n202.92.48.0/20\n202.92.252.0/22\n202.93.0.0/22\n202.93.252.0/22\n202.94.0.0/19\n202.94.74.0/24\n202.94.81.0/24\n202.94.92.0/22\n202.95.240.0/21\n202.95.252.0/22\n202.96.0.0/12\n202.112.0.0/13\n202.120.0.0/15\n202.122.0.0/21\n202.122.32.0/21\n202.122.64.0/19\n202.122.112.0/20\n202.122.128.0/24\n202.122.132.0/24\n202.123.96.0/20\n202.123.116.0/22\n202.123.120.0/22\n202.124.16.0/21\n202.124.24.0/22\n202.125.107.0/24\n202.125.109.0/24\n202.125.112.0/20\n202.125.176.0/20\n202.127.0.0/21\n202.127.12.0/22\n202.127.16.0/20\n202.127.40.0/21\n202.127.48.0/20\n202.127.112.0/20\n202.127.128.0/19\n202.127.160.0/21\n202.127.192.0/20\n202.127.208.0/23\n202.127.212.0/22\n202.127.216.0/21\n202.127.224.0/19\n202.129.208.0/24\n202.130.0.0/19\n202.130.39.0/24\n202.130.224.0/19\n202.131.16.0/21\n202.131.59.0/24\n202.131.208.0/20\n202.133.32.0/20\n202.134.58.0/24\n202.134.128.0/20\n202.134.208.0/20\n202.136.48.0/20\n202.136.208.0/20\n202.136.224.0/20\n202.136.248.0/22\n202.136.254.0/23\n202.137.231.0/24\n202.140.140.0/22\n202.140.144.0/20\n202.141.160.0/19\n202.142.16.0/20\n202.143.4.0/22\n202.143.16.0/20\n202.143.32.0/20\n202.143.56.0/21\n202.143.100.0/22\n202.143.104.0/22\n202.146.160.0/20\n202.146.186.0/24\n202.146.188.0/22\n202.146.196.0/22\n202.146.200.0/21\n202.147.144.0/20\n202.148.32.0/20\n202.148.64.0/18\n202.149.32.0/19\n202.149.160.0/19\n202.149.224.0/19\n202.150.16.0/20\n202.150.32.0/20\n202.150.56.0/22\n202.150.192.0/20\n202.150.224.0/19\n202.151.0.0/22\n202.151.128.0/19\n202.152.176.0/20\n202.153.0.0/22\n202.153.7.0/24\n202.153.48.0/20\n202.157.192.0/19\n202.158.160.0/19\n202.158.242.0/24\n202.160.140.0/22\n202.160.156.0/22\n202.160.176.0/20\n202.162.67.0/24\n202.162.75.0/24\n202.164.0.0/20\n202.164.96.0/19\n202.165.176.0/20\n202.165.208.0/20\n202.165.239.0/24\n202.165.240.0/23\n202.165.243.0/24\n202.165.245.0/24\n202.165.251.0/24\n202.165.252.0/22\n202.166.224.0/19\n202.168.80.0/22\n202.168.128.0/20\n202.168.160.0/19\n202.170.128.0/19\n202.170.216.0/21\n202.170.224.0/19\n202.171.216.0/21\n202.171.232.0/24\n202.171.235.0/24\n202.172.0.0/22\n202.172.7.0/24\n202.173.0.0/22\n202.173.6.0/24\n202.173.8.0/21\n202.173.112.0/22\n202.173.224.0/19\n202.174.64.0/20\n202.174.124.0/22\n202.176.224.0/19\n202.179.160.0/20\n202.179.240.0/20\n202.180.128.0/19\n202.180.208.0/21\n202.181.8.0/22\n202.181.28.0/22\n202.181.112.0/20\n202.182.32.0/20\n202.182.192.0/19\n202.189.0.0/18\n202.189.80.0/20\n202.189.184.0/21\n202.191.0.0/24\n202.191.68.0/22\n202.191.72.0/21\n202.191.80.0/20\n202.192.0.0/12\n203.0.4.0/22\n203.0.10.0/23\n203.0.18.0/24\n203.0.24.0/24\n203.0.42.0/23\n203.0.45.0/24\n203.0.46.0/23\n203.0.81.0/24\n203.0.82.0/23\n203.0.90.0/23\n203.0.96.0/23\n203.0.104.0/21\n203.0.114.0/23\n203.0.122.0/24\n203.0.128.0/24\n203.0.130.0/23\n203.0.132.0/22\n203.0.137.0/24\n203.0.142.0/24\n203.0.144.0/24\n203.0.146.0/24\n203.0.148.0/24\n203.0.150.0/23\n203.0.152.0/24\n203.0.177.0/24\n203.0.224.0/24\n203.1.4.0/22\n203.1.18.0/24\n203.1.26.0/23\n203.1.65.0/24\n203.1.66.0/23\n203.1.70.0/23\n203.1.76.0/23\n203.1.90.0/24\n203.1.97.0/24\n203.1.98.0/23\n203.1.100.0/22\n203.1.108.0/24\n203.1.253.0/24\n203.1.254.0/24\n203.2.64.0/21\n203.2.73.0/24\n203.2.112.0/21\n203.2.126.0/23\n203.2.140.0/24\n203.2.150.0/24\n203.2.152.0/22\n203.2.156.0/23\n203.2.160.0/21\n203.2.180.0/23\n203.2.196.0/23\n203.2.209.0/24\n203.2.214.0/23\n203.2.226.0/23\n203.2.229.0/24\n203.2.236.0/23\n203.3.68.0/24\n203.3.72.0/23\n203.3.75.0/24\n203.3.80.0/21\n203.3.96.0/22\n203.3.105.0/24\n203.3.112.0/21\n203.3.120.0/24\n203.3.123.0/24\n203.3.135.0/24\n203.3.139.0/24\n203.3.143.0/24\n203.4.132.0/23\n203.4.134.0/24\n203.4.151.0/24\n203.4.152.0/22\n203.4.174.0/23\n203.4.180.0/24\n203.4.186.0/24\n203.4.205.0/24\n203.4.208.0/22\n203.4.227.0/24\n203.4.230.0/23\n203.5.4.0/23\n203.5.7.0/24\n203.5.8.0/23\n203.5.11.0/24\n203.5.21.0/24\n203.5.22.0/24\n203.5.44.0/24\n203.5.46.0/23\n203.5.52.0/22\n203.5.56.0/23\n203.5.60.0/23\n203.5.114.0/23\n203.5.118.0/24\n203.5.120.0/24\n203.5.172.0/24\n203.5.180.0/23\n203.5.182.0/24\n203.5.185.0/24\n203.5.186.0/24\n203.5.188.0/23\n203.5.190.0/24\n203.5.195.0/24\n203.5.214.0/23\n203.5.218.0/23\n203.6.131.0/24\n203.6.136.0/24\n203.6.138.0/23\n203.6.142.0/24\n203.6.150.0/23\n203.6.157.0/24\n203.6.159.0/24\n203.6.224.0/20\n203.6.248.0/23\n203.7.129.0/24\n203.7.138.0/23\n203.7.147.0/24\n203.7.150.0/23\n203.7.158.0/24\n203.7.192.0/23\n203.7.200.0/24\n203.8.0.0/24\n203.8.8.0/24\n203.8.23.0/24\n203.8.70.0/24\n203.8.82.0/24\n203.8.86.0/23\n203.8.91.0/24\n203.8.110.0/23\n203.8.115.0/24\n203.8.166.0/23\n203.8.169.0/24\n203.8.173.0/24\n203.8.184.0/24\n203.8.186.0/23\n203.8.190.0/23\n203.8.192.0/24\n203.8.197.0/24\n203.8.198.0/23\n203.8.203.0/24\n203.8.209.0/24\n203.8.210.0/23\n203.8.212.0/22\n203.8.217.0/24\n203.8.220.0/24\n203.9.32.0/24\n203.9.36.0/23\n203.9.57.0/24\n203.9.63.0/24\n203.9.65.0/24\n203.9.70.0/23\n203.9.72.0/24\n203.9.75.0/24\n203.9.76.0/23\n203.9.96.0/22\n203.9.100.0/23\n203.9.108.0/24\n203.9.158.0/24\n203.10.34.0/24\n203.10.56.0/24\n203.10.74.0/23\n203.10.84.0/22\n203.10.88.0/24\n203.10.95.0/24\n203.10.125.0/24\n203.11.70.0/24\n203.11.76.0/22\n203.11.82.0/24\n203.11.84.0/22\n203.11.100.0/22\n203.11.109.0/24\n203.11.117.0/24\n203.11.122.0/24\n203.11.126.0/24\n203.11.136.0/22\n203.11.141.0/24\n203.11.142.0/23\n203.11.180.0/22\n203.11.208.0/22\n203.12.16.0/24\n203.12.19.0/24\n203.12.24.0/24\n203.12.57.0/24\n203.12.65.0/24\n203.12.66.0/24\n203.12.70.0/23\n203.12.87.0/24\n203.12.90.0/24\n203.12.92.0/22\n203.12.100.0/23\n203.12.103.0/24\n203.12.114.0/24\n203.12.118.0/24\n203.12.130.0/24\n203.12.137.0/24\n203.12.196.0/22\n203.12.211.0/24\n203.12.219.0/24\n203.12.226.0/24\n203.12.240.0/22\n203.13.18.0/24\n203.13.24.0/24\n203.13.44.0/23\n203.13.88.0/23\n203.13.92.0/22\n203.13.173.0/24\n203.13.224.0/23\n203.13.227.0/24\n203.13.233.0/24\n203.14.24.0/22\n203.14.33.0/24\n203.14.56.0/24\n203.14.61.0/24\n203.14.62.0/24\n203.14.104.0/24\n203.14.114.0/23\n203.14.118.0/24\n203.14.162.0/24\n203.14.184.0/21\n203.14.192.0/24\n203.14.194.0/23\n203.14.214.0/24\n203.14.231.0/24\n203.14.246.0/24\n203.15.0.0/20\n203.15.20.0/23\n203.15.22.0/24\n203.15.87.0/24\n203.15.88.0/23\n203.15.105.0/24\n203.15.112.0/21\n203.15.130.0/23\n203.15.149.0/24\n203.15.151.0/24\n203.15.156.0/22\n203.15.174.0/24\n203.15.227.0/24\n203.15.232.0/22\n203.15.238.0/23\n203.15.240.0/23\n203.15.246.0/24\n203.16.10.0/24\n203.16.12.0/23\n203.16.16.0/21\n203.16.27.0/24\n203.16.38.0/24\n203.16.49.0/24\n203.16.50.0/23\n203.16.58.0/24\n203.16.63.0/24\n203.16.133.0/24\n203.16.161.0/24\n203.16.162.0/24\n203.16.186.0/23\n203.16.228.0/24\n203.16.238.0/24\n203.16.240.0/24\n203.16.245.0/24\n203.17.2.0/24\n203.17.18.0/24\n203.17.28.0/24\n203.17.39.0/24\n203.17.56.0/24\n203.17.74.0/23\n203.17.88.0/23\n203.17.136.0/24\n203.17.164.0/24\n203.17.187.0/24\n203.17.190.0/23\n203.17.231.0/24\n203.17.233.0/24\n203.17.248.0/23\n203.17.255.0/24\n203.18.2.0/23\n203.18.4.0/24\n203.18.7.0/24\n203.18.31.0/24\n203.18.37.0/24\n203.18.48.0/23\n203.18.52.0/24\n203.18.72.0/22\n203.18.80.0/23\n203.18.87.0/24\n203.18.100.0/23\n203.18.105.0/24\n203.18.107.0/24\n203.18.110.0/24\n203.18.129.0/24\n203.18.131.0/24\n203.18.132.0/23\n203.18.144.0/24\n203.18.153.0/24\n203.18.199.0/24\n203.18.208.0/24\n203.18.211.0/24\n203.18.215.0/24\n203.19.1.0/24\n203.19.18.0/24\n203.19.24.0/24\n203.19.30.0/24\n203.19.41.0/24\n203.19.44.0/23\n203.19.46.0/24\n203.19.58.0/24\n203.19.60.0/23\n203.19.64.0/24\n203.19.68.0/24\n203.19.72.0/24\n203.19.101.0/24\n203.19.111.0/24\n203.19.131.0/24\n203.19.133.0/24\n203.19.144.0/24\n203.19.147.0/24\n203.19.149.0/24\n203.19.156.0/24\n203.19.176.0/24\n203.19.178.0/23\n203.19.208.0/24\n203.19.228.0/22\n203.19.233.0/24\n203.19.242.0/24\n203.19.248.0/23\n203.19.255.0/24\n203.20.17.0/24\n203.20.40.0/23\n203.20.44.0/24\n203.20.48.0/24\n203.20.61.0/24\n203.20.65.0/24\n203.20.84.0/23\n203.20.89.0/24\n203.20.106.0/23\n203.20.115.0/24\n203.20.117.0/24\n203.20.118.0/23\n203.20.122.0/24\n203.20.126.0/23\n203.20.135.0/24\n203.20.140.0/22\n203.20.150.0/24\n203.20.230.0/24\n203.20.232.0/24\n203.20.236.0/24\n203.21.0.0/23\n203.21.2.0/24\n203.21.8.0/24\n203.21.10.0/24\n203.21.18.0/24\n203.21.33.0/24\n203.21.34.0/24\n203.21.41.0/24\n203.21.44.0/24\n203.21.68.0/24\n203.21.82.0/24\n203.21.96.0/22\n203.21.124.0/24\n203.21.136.0/23\n203.21.145.0/24\n203.21.206.0/24\n203.22.24.0/24\n203.22.28.0/23\n203.22.31.0/24\n203.22.68.0/24\n203.22.76.0/24\n203.22.84.0/24\n203.22.87.0/24\n203.22.92.0/22\n203.22.99.0/24\n203.22.106.0/24\n203.22.122.0/23\n203.22.131.0/24\n203.22.163.0/24\n203.22.166.0/24\n203.22.170.0/24\n203.22.176.0/21\n203.22.194.0/24\n203.22.242.0/23\n203.22.245.0/24\n203.22.246.0/24\n203.22.252.0/23\n203.23.0.0/24\n203.23.47.0/24\n203.23.61.0/24\n203.23.62.0/23\n203.23.73.0/24\n203.23.85.0/24\n203.23.92.0/22\n203.23.98.0/24\n203.23.107.0/24\n203.23.112.0/24\n203.23.130.0/24\n203.23.140.0/23\n203.23.172.0/24\n203.23.182.0/24\n203.23.186.0/23\n203.23.192.0/24\n203.23.197.0/24\n203.23.198.0/24\n203.23.204.0/22\n203.23.224.0/24\n203.23.226.0/23\n203.23.228.0/22\n203.23.249.0/24\n203.23.251.0/24\n203.24.13.0/24\n203.24.18.0/24\n203.24.27.0/24\n203.24.43.0/24\n203.24.56.0/24\n203.24.58.0/24\n203.24.67.0/24\n203.24.74.0/24\n203.24.79.0/24\n203.24.80.0/23\n203.24.84.0/23\n203.24.86.0/24\n203.24.90.0/24\n203.24.111.0/24\n203.24.112.0/24\n203.24.116.0/24\n203.24.122.0/23\n203.24.145.0/24\n203.24.152.0/23\n203.24.157.0/24\n203.24.161.0/24\n203.24.167.0/24\n203.24.186.0/23\n203.24.199.0/24\n203.24.202.0/24\n203.24.212.0/23\n203.24.217.0/24\n203.24.219.0/24\n203.24.244.0/24\n203.25.19.0/24\n203.25.20.0/23\n203.25.46.0/24\n203.25.64.0/23\n203.25.91.0/24\n203.25.99.0/24\n203.25.100.0/24\n203.25.106.0/24\n203.25.131.0/24\n203.25.135.0/24\n203.25.138.0/24\n203.25.147.0/24\n203.25.153.0/24\n203.25.154.0/23\n203.25.164.0/24\n203.25.166.0/24\n203.25.174.0/23\n203.25.180.0/24\n203.25.182.0/24\n203.25.191.0/24\n203.25.199.0/24\n203.25.200.0/24\n203.25.202.0/23\n203.25.208.0/20\n203.25.229.0/24\n203.25.235.0/24\n203.25.236.0/24\n203.25.242.0/24\n203.26.12.0/24\n203.26.34.0/24\n203.26.49.0/24\n203.26.50.0/24\n203.26.55.0/24\n203.26.56.0/23\n203.26.60.0/24\n203.26.65.0/24\n203.26.68.0/24\n203.26.76.0/24\n203.26.80.0/24\n203.26.84.0/24\n203.26.97.0/24\n203.26.102.0/23\n203.26.115.0/24\n203.26.116.0/24\n203.26.129.0/24\n203.26.143.0/24\n203.26.144.0/24\n203.26.148.0/23\n203.26.154.0/24\n203.26.158.0/23\n203.26.161.0/24\n203.26.170.0/24\n203.26.173.0/24\n203.26.176.0/24\n203.26.185.0/24\n203.26.202.0/23\n203.26.210.0/24\n203.26.214.0/24\n203.26.222.0/24\n203.26.224.0/24\n203.26.228.0/24\n203.26.232.0/24\n203.27.0.0/24\n203.27.10.0/24\n203.27.15.0/24\n203.27.16.0/24\n203.27.20.0/24\n203.27.22.0/23\n203.27.40.0/24\n203.27.45.0/24\n203.27.53.0/24\n203.27.65.0/24\n203.27.66.0/24\n203.27.81.0/24\n203.27.88.0/24\n203.27.102.0/24\n203.27.109.0/24\n203.27.117.0/24\n203.27.121.0/24\n203.27.122.0/23\n203.27.125.0/24\n203.27.200.0/24\n203.27.202.0/24\n203.27.233.0/24\n203.27.241.0/24\n203.27.250.0/24\n203.28.10.0/24\n203.28.12.0/24\n203.28.33.0/24\n203.28.34.0/23\n203.28.43.0/24\n203.28.44.0/24\n203.28.54.0/24\n203.28.56.0/24\n203.28.73.0/24\n203.28.74.0/24\n203.28.76.0/24\n203.28.86.0/24\n203.28.88.0/24\n203.28.112.0/24\n203.28.131.0/24\n203.28.136.0/24\n203.28.140.0/24\n203.28.145.0/24\n203.28.165.0/24\n203.28.169.0/24\n203.28.170.0/24\n203.28.178.0/23\n203.28.185.0/24\n203.28.187.0/24\n203.28.196.0/24\n203.28.226.0/23\n203.28.239.0/24\n203.29.2.0/24\n203.29.8.0/23\n203.29.13.0/24\n203.29.14.0/24\n203.29.28.0/24\n203.29.46.0/24\n203.29.57.0/24\n203.29.61.0/24\n203.29.63.0/24\n203.29.69.0/24\n203.29.73.0/24\n203.29.81.0/24\n203.29.90.0/24\n203.29.95.0/24\n203.29.100.0/24\n203.29.103.0/24\n203.29.112.0/24\n203.29.120.0/22\n203.29.182.0/23\n203.29.187.0/24\n203.29.189.0/24\n203.29.190.0/24\n203.29.205.0/24\n203.29.210.0/24\n203.29.217.0/24\n203.29.227.0/24\n203.29.231.0/24\n203.29.233.0/24\n203.29.234.0/24\n203.29.248.0/24\n203.29.254.0/23\n203.30.16.0/23\n203.30.25.0/24\n203.30.29.0/24\n203.30.66.0/24\n203.30.81.0/24\n203.30.87.0/24\n203.30.111.0/24\n203.30.121.0/24\n203.30.123.0/24\n203.30.152.0/24\n203.30.156.0/24\n203.30.162.0/24\n203.30.173.0/24\n203.30.175.0/24\n203.30.187.0/24\n203.30.194.0/24\n203.30.217.0/24\n203.30.220.0/24\n203.30.222.0/24\n203.30.232.0/23\n203.30.235.0/24\n203.30.240.0/23\n203.30.246.0/24\n203.30.250.0/23\n203.31.45.0/24\n203.31.46.0/24\n203.31.49.0/24\n203.31.51.0/24\n203.31.54.0/23\n203.31.69.0/24\n203.31.72.0/24\n203.31.80.0/24\n203.31.85.0/24\n203.31.97.0/24\n203.31.105.0/24\n203.31.106.0/24\n203.31.108.0/23\n203.31.124.0/24\n203.31.162.0/24\n203.31.174.0/24\n203.31.177.0/24\n203.31.181.0/24\n203.31.187.0/24\n203.31.189.0/24\n203.31.204.0/24\n203.31.220.0/24\n203.31.222.0/23\n203.31.225.0/24\n203.31.229.0/24\n203.31.248.0/23\n203.31.253.0/24\n203.32.20.0/24\n203.32.48.0/23\n203.32.56.0/24\n203.32.60.0/24\n203.32.62.0/24\n203.32.68.0/23\n203.32.76.0/24\n203.32.81.0/24\n203.32.84.0/23\n203.32.95.0/24\n203.32.102.0/24\n203.32.105.0/24\n203.32.130.0/24\n203.32.133.0/24\n203.32.140.0/24\n203.32.152.0/24\n203.32.186.0/23\n203.32.192.0/24\n203.32.196.0/24\n203.32.203.0/24\n203.32.204.0/23\n203.32.212.0/24\n203.33.4.0/24\n203.33.7.0/24\n203.33.12.0/23\n203.33.21.0/24\n203.33.26.0/24\n203.33.32.0/24\n203.33.63.0/24\n203.33.64.0/24\n203.33.67.0/24\n203.33.68.0/24\n203.33.73.0/24\n203.33.79.0/24\n203.33.100.0/24\n203.33.122.0/24\n203.33.129.0/24\n203.33.131.0/24\n203.33.145.0/24\n203.33.156.0/24\n203.33.158.0/23\n203.33.174.0/24\n203.33.185.0/24\n203.33.200.0/24\n203.33.202.0/23\n203.33.204.0/24\n203.33.206.0/23\n203.33.214.0/23\n203.33.224.0/23\n203.33.226.0/24\n203.33.233.0/24\n203.33.243.0/24\n203.33.250.0/24\n203.34.4.0/24\n203.34.21.0/24\n203.34.27.0/24\n203.34.39.0/24\n203.34.48.0/23\n203.34.54.0/24\n203.34.56.0/23\n203.34.67.0/24\n203.34.69.0/24\n203.34.76.0/24\n203.34.92.0/24\n203.34.106.0/24\n203.34.113.0/24\n203.34.147.0/24\n203.34.150.0/24\n203.34.152.0/23\n203.34.161.0/24\n203.34.162.0/24\n203.34.187.0/24\n203.34.192.0/21\n203.34.204.0/22\n203.34.232.0/24\n203.34.240.0/24\n203.34.242.0/24\n203.34.245.0/24\n203.34.251.0/24\n203.55.2.0/23\n203.55.4.0/24\n203.55.10.0/24\n203.55.13.0/24\n203.55.22.0/24\n203.55.30.0/24\n203.55.93.0/24\n203.55.101.0/24\n203.55.109.0/24\n203.55.110.0/24\n203.55.116.0/23\n203.55.119.0/24\n203.55.128.0/23\n203.55.146.0/23\n203.55.192.0/24\n203.55.196.0/24\n203.55.218.0/23\n203.55.221.0/24\n203.55.224.0/24\n203.56.1.0/24\n203.56.4.0/24\n203.56.12.0/24\n203.56.24.0/24\n203.56.38.0/24\n203.56.40.0/24\n203.56.46.0/24\n203.56.50.0/23\n203.56.52.0/22\n203.56.68.0/23\n203.56.82.0/23\n203.56.84.0/23\n203.56.95.0/24\n203.56.110.0/24\n203.56.121.0/24\n203.56.161.0/24\n203.56.169.0/24\n203.56.172.0/23\n203.56.175.0/24\n203.56.183.0/24\n203.56.185.0/24\n203.56.187.0/24\n203.56.192.0/24\n203.56.198.0/24\n203.56.201.0/24\n203.56.208.0/23\n203.56.210.0/24\n203.56.214.0/24\n203.56.216.0/24\n203.56.227.0/24\n203.56.228.0/24\n203.56.232.0/24\n203.56.240.0/24\n203.56.252.0/24\n203.56.254.0/24\n203.57.5.0/24\n203.57.6.0/24\n203.57.12.0/23\n203.57.28.0/24\n203.57.39.0/24\n203.57.46.0/24\n203.57.58.0/24\n203.57.61.0/24\n203.57.66.0/24\n203.57.69.0/24\n203.57.70.0/23\n203.57.73.0/24\n203.57.90.0/24\n203.57.101.0/24\n203.57.109.0/24\n203.57.123.0/24\n203.57.157.0/24\n203.57.200.0/24\n203.57.202.0/24\n203.57.206.0/24\n203.57.222.0/24\n203.57.224.0/20\n203.57.246.0/23\n203.57.249.0/24\n203.57.253.0/24\n203.57.254.0/23\n203.62.2.0/24\n203.62.131.0/24\n203.62.139.0/24\n203.62.161.0/24\n203.62.197.0/24\n203.62.228.0/22\n203.62.234.0/24\n203.62.246.0/24\n203.65.240.0/22\n203.76.160.0/22\n203.76.168.0/22\n203.76.208.0/21\n203.76.216.0/22\n203.76.240.0/22\n203.77.180.0/22\n203.78.48.0/20\n203.78.156.0/22\n203.79.0.0/20\n203.80.4.0/23\n203.80.32.0/20\n203.80.57.0/24\n203.80.129.0/24\n203.80.132.0/22\n203.80.140.0/22\n203.80.144.0/20\n203.81.0.0/21\n203.81.16.0/20\n203.81.244.0/22\n203.82.0.0/23\n203.82.16.0/21\n203.82.112.0/20\n203.82.224.0/20\n203.83.0.0/22\n203.83.12.0/22\n203.83.56.0/21\n203.83.224.0/20\n203.86.0.0/18\n203.86.64.0/19\n203.86.250.0/24\n203.86.254.0/23\n203.88.32.0/19\n203.88.100.0/22\n203.88.192.0/19\n203.89.0.0/22\n203.89.100.0/22\n203.89.136.0/22\n203.89.144.0/24\n203.90.0.0/22\n203.90.8.0/21\n203.90.128.0/18\n203.90.192.0/19\n203.91.32.0/19\n203.91.96.0/20\n203.91.120.0/21\n203.92.0.0/22\n203.92.6.0/24\n203.92.160.0/19\n203.93.0.0/16\n203.94.0.0/19\n203.95.0.0/21\n203.95.96.0/19\n203.95.128.0/18\n203.95.200.0/21\n203.95.208.0/22\n203.95.224.0/19\n203.99.8.0/21\n203.99.16.0/22\n203.99.30.0/23\n203.99.80.0/20\n203.100.32.0/20\n203.100.58.0/24\n203.100.60.0/24\n203.100.63.0/24\n203.100.80.0/20\n203.100.96.0/19\n203.100.192.0/20\n203.104.32.0/20\n203.105.96.0/19\n203.105.128.0/19\n203.107.0.0/19\n203.107.32.0/20\n203.107.52.0/22\n203.107.56.0/21\n203.107.69.0/24\n203.107.70.0/23\n203.107.72.0/21\n203.107.80.0/20\n203.107.96.0/19\n203.110.160.0/19\n203.110.208.0/20\n203.110.232.0/23\n203.110.234.0/24\n203.114.80.0/20\n203.114.244.0/22\n203.118.192.0/19\n203.118.241.0/24\n203.118.248.0/22\n203.119.24.0/23\n203.119.32.0/24\n203.119.34.0/23\n203.119.80.0/22\n203.119.85.0/24\n203.119.113.0/24\n203.119.114.0/23\n203.119.116.0/22\n203.119.120.0/21\n203.119.128.0/17\n203.123.58.0/24\n203.128.32.0/19\n203.128.96.0/19\n203.128.128.0/24\n203.128.224.0/21\n203.130.32.0/20\n203.132.32.0/19\n203.134.240.0/22\n203.134.246.0/23\n203.135.96.0/19\n203.135.160.0/20\n203.142.12.0/23\n203.142.219.0/24\n203.142.224.0/19\n203.145.0.0/19\n203.148.0.0/18\n203.148.64.0/20\n203.148.80.0/22\n203.148.86.0/23\n203.149.92.0/22\n203.152.64.0/19\n203.152.128.0/19\n203.153.0.0/22\n203.156.192.0/18\n203.158.16.0/21\n203.160.129.0/24\n203.160.192.0/19\n203.161.0.0/22\n203.161.180.0/24\n203.161.183.0/24\n203.161.192.0/19\n203.166.160.0/19\n203.167.28.0/22\n203.168.0.0/19\n203.170.58.0/23\n203.171.0.0/22\n203.171.208.0/24\n203.171.224.0/20\n203.174.4.0/24\n203.174.6.0/24\n203.174.96.0/20\n203.175.128.0/19\n203.175.192.0/18\n203.176.0.0/18\n203.176.64.0/19\n203.176.168.0/21\n203.184.80.0/20\n203.187.160.0/19\n203.189.0.0/23\n203.189.6.0/23\n203.189.112.0/22\n203.189.192.0/19\n203.189.240.0/22\n203.190.96.0/20\n203.190.249.0/24\n203.191.0.0/23\n203.191.2.0/24\n203.191.5.0/24\n203.191.7.0/24\n203.191.29.0/24\n203.191.31.0/24\n203.191.64.0/18\n203.191.133.0/24\n203.191.144.0/20\n203.192.0.0/19\n203.193.224.0/19\n203.195.64.0/19\n203.195.128.0/17\n203.196.0.0/20\n203.196.28.0/22\n203.201.181.0/24\n203.201.182.0/24\n203.202.236.0/22\n203.205.64.0/19\n203.207.64.0/18\n203.207.128.0/17\n203.208.0.0/20\n203.208.16.0/22\n203.208.32.0/19\n203.209.224.0/19\n203.212.0.0/20\n203.212.80.0/20\n203.217.164.0/22\n203.223.0.0/20\n203.223.16.0/24\n203.223.22.0/24\n204.55.160.0/24\n204.74.96.0/24\n204.114.176.0/23\n206.219.44.0/23\n206.219.50.0/23\n206.219.52.0/23\n207.89.20.0/24\n210.2.0.0/23\n210.2.2.0/24\n210.2.5.0/24\n210.2.6.0/23\n210.2.8.0/21\n210.2.24.0/21\n210.5.0.0/19\n210.5.56.0/24\n210.5.60.0/24\n210.5.128.0/19\n210.7.56.0/21\n210.12.0.0/15\n210.14.64.0/19\n210.14.112.0/20\n210.14.128.0/17\n210.15.0.0/17\n210.15.128.0/18\n210.16.128.0/21\n210.16.136.0/22\n210.16.156.0/22\n210.16.160.0/19\n210.21.0.0/16\n210.22.0.0/16\n210.23.32.0/19\n210.25.0.0/16\n210.26.0.0/15\n210.28.0.0/14\n210.32.0.0/12\n210.51.0.0/16\n210.52.0.0/18\n210.52.64.0/23\n210.52.66.0/24\n210.52.68.0/22\n210.52.72.0/21\n210.52.80.0/20\n210.52.96.0/21\n210.52.104.0/22\n210.52.108.0/24\n210.52.110.0/23\n210.52.112.0/20\n210.52.128.0/17\n210.53.0.0/16\n210.56.192.0/19\n210.72.0.0/14\n210.76.0.0/15\n210.78.0.0/16\n210.79.64.0/18\n210.79.224.0/19\n210.82.0.0/15\n210.87.128.0/18\n210.185.192.0/18\n210.192.96.0/19\n211.64.0.0/13\n211.80.0.0/12\n211.96.0.0/14\n211.100.0.0/17\n211.100.128.0/19\n211.100.160.0/20\n211.100.184.0/21\n211.100.192.0/18\n211.101.0.0/16\n211.102.0.0/15\n211.136.0.0/13\n211.144.0.0/13\n211.152.0.0/17\n211.152.134.0/23\n211.152.138.0/23\n211.152.140.0/22\n211.152.150.0/23\n211.152.157.0/24\n211.152.158.0/23\n211.152.160.0/19\n211.152.192.0/18\n211.153.0.0/16\n211.154.0.0/19\n211.154.32.0/20\n211.154.48.0/21\n211.154.64.0/18\n211.154.128.0/17\n211.155.0.0/18\n211.155.67.0/24\n211.155.68.0/24\n211.155.72.0/21\n211.155.80.0/20\n211.155.97.0/24\n211.155.98.0/23\n211.155.100.0/22\n211.155.104.0/21\n211.155.113.0/24\n211.155.117.0/24\n211.155.118.0/23\n211.155.120.0/21\n211.155.128.0/17\n211.156.0.0/18\n211.156.64.0/19\n211.156.96.0/21\n211.156.104.0/22\n211.156.108.0/23\n211.156.112.0/20\n211.156.128.0/17\n211.157.0.0/16\n211.158.0.0/15\n211.160.0.0/13\n212.64.0.0/17\n212.129.128.0/17\n218.0.0.0/12\n218.16.0.0/13\n218.24.0.0/14\n218.28.0.0/15\n218.30.0.0/19\n218.30.64.0/18\n218.30.128.0/18\n218.30.192.0/19\n218.30.224.0/20\n218.30.240.0/21\n218.30.248.0/22\n218.30.252.0/25\n218.30.252.128/26\n218.30.252.194/31\n218.30.252.196/30\n218.30.252.200/29\n218.30.252.208/28\n218.30.252.224/27\n218.30.253.0/24\n218.30.254.0/23\n218.31.0.0/16\n218.56.0.0/13\n218.64.0.0/11\n218.96.0.0/15\n218.98.0.0/18\n218.98.96.0/21\n218.98.104.0/22\n218.98.108.0/23\n218.98.110.0/24\n218.98.112.0/20\n218.98.128.0/19\n218.98.192.0/18\n218.99.0.0/16\n218.100.96.0/19\n218.100.128.0/17\n218.104.0.0/14\n218.108.0.0/15\n218.185.192.0/19\n218.192.0.0/12\n218.240.0.0/14\n218.244.0.0/15\n218.246.0.0/17\n218.246.129.0/24\n218.246.131.0/24\n218.246.132.0/23\n218.246.134.0/24\n218.246.139.0/24\n218.246.144.0/20\n218.246.160.0/19\n218.246.192.0/18\n218.247.0.0/18\n218.247.96.0/19\n218.247.128.0/17\n218.249.0.0/16\n219.72.0.0/16\n219.82.0.0/16\n219.83.128.0/17\n219.90.68.0/22\n219.90.72.0/21\n219.128.0.0/11\n219.216.0.0/13\n219.224.0.0/13\n219.232.0.0/15\n219.234.0.0/21\n219.234.9.0/24\n219.234.10.0/23\n219.234.12.0/22\n219.234.32.0/19\n219.234.64.0/18\n219.234.128.0/17\n219.235.0.0/16\n219.236.0.0/14\n219.242.0.0/15\n219.244.0.0/14\n220.101.192.0/18\n220.112.0.0/14\n220.152.128.0/17\n220.154.0.0/16\n220.155.0.0/21\n220.155.9.0/24\n220.155.10.0/23\n220.155.12.0/22\n220.155.16.0/21\n220.155.24.0/22\n220.155.28.0/23\n220.155.31.0/24\n220.155.32.0/19\n220.155.64.0/18\n220.155.128.0/17\n220.158.241.0/24\n220.158.243.0/24\n220.160.0.0/11\n220.192.0.0/12\n220.231.0.0/18\n220.231.128.0/17\n220.232.64.0/18\n220.234.0.0/16\n220.242.0.0/24\n220.242.12.0/23\n220.242.14.0/24\n220.242.17.0/24\n220.242.18.0/23\n220.242.20.0/24\n220.242.32.0/20\n220.242.48.0/23\n220.242.53.0/24\n220.242.55.0/24\n220.242.56.0/22\n220.242.60.0/23\n220.242.62.0/24\n220.242.64.0/19\n220.242.96.0/20\n220.242.112.0/21\n220.242.120.0/22\n220.242.124.0/23\n220.242.126.0/24\n220.242.173.0/24\n220.242.197.0/24\n220.242.205.0/24\n220.242.207.0/24\n220.242.215.0/24\n220.242.216.0/21\n220.242.224.0/19\n220.243.0.0/17\n220.243.128.0/18\n220.243.204.0/24\n220.243.214.0/24\n220.243.217.0/24\n220.243.218.0/24\n220.243.238.0/24\n220.247.136.0/21\n220.248.0.0/14\n220.252.0.0/16\n221.0.0.0/13\n221.8.0.0/14\n221.12.0.0/17\n221.12.128.0/18\n221.13.0.0/16\n221.14.0.0/15\n221.122.0.0/15\n221.128.128.0/17\n221.129.0.0/16\n221.130.0.0/15\n221.133.224.0/19\n221.136.0.0/15\n221.172.0.0/14\n221.176.0.0/19\n221.176.32.0/20\n221.176.48.0/21\n221.176.56.0/24\n221.176.58.0/23\n221.176.60.0/22\n221.176.64.0/18\n221.176.128.0/17\n221.177.0.0/16\n221.178.0.0/15\n221.180.0.0/14\n221.192.0.0/14\n221.196.0.0/15\n221.198.0.0/16\n221.199.0.0/17\n221.199.128.0/18\n221.199.192.0/20\n221.199.224.0/19\n221.200.0.0/13\n221.208.0.0/12\n221.224.0.0/12\n222.16.0.0/12\n222.32.0.0/11\n222.64.0.0/11\n222.125.0.0/16\n222.126.128.0/19\n222.126.160.0/21\n222.126.168.0/22\n222.126.172.0/23\n222.126.174.40/29\n222.126.174.76/30\n222.126.174.88/29\n222.126.174.144/28\n222.126.178.0/23\n222.126.180.0/22\n222.126.184.0/21\n222.126.192.0/21\n222.126.200.104/29\n222.126.206.0/23\n222.126.208.0/22\n222.126.212.0/26\n222.126.212.64/27\n222.126.212.96/28\n222.126.212.112/29\n222.126.212.128/25\n222.126.213.0/24\n222.126.214.0/23\n222.126.216.0/21\n222.126.224.0/19\n222.128.0.0/12\n222.160.0.0/14\n222.168.0.0/13\n222.176.0.0/12\n222.192.0.0/11\n222.240.0.0/13\n222.248.0.0/15\n223.0.0.0/12\n223.20.0.0/15\n223.27.184.0/22\n223.29.208.0/22\n223.29.252.0/22\n223.64.0.0/11\n223.96.0.0/12\n223.112.0.0/14\n223.116.0.0/15\n223.120.0.0/13\n223.128.0.0/15\n223.144.0.0/12\n223.160.0.0/14\n223.166.0.0/15\n223.192.0.0/15\n223.198.0.0/15\n223.201.4.0/22\n223.201.8.0/21\n223.201.16.0/20\n223.201.32.0/19\n223.201.64.0/18\n223.201.128.0/17\n223.202.0.0/15\n223.208.0.0/13\n223.220.0.0/15\n223.223.176.0/20\n223.223.192.0/20\n223.240.0.0/13\n223.248.0.0/14\n223.252.128.0/19\n223.252.192.0/18\n223.254.0.0/16\n223.255.0.0/17\n223.255.236.0/22\n223.255.252.0/23\n"
  },
  {
    "path": "acl/server_block_local.acl",
    "content": "# All IPs listed here will be blocked while the ss-server try to outbound.\n# Only IP is allowed, *NOT* domain name.\n#\n\n[outbound_block_list]\n0.0.0.0/8\n10.0.0.0/8\n100.64.0.0/10\n127.0.0.0/8\n169.254.0.0/16\n172.16.0.0/12\n192.0.0.0/24\n192.0.2.0/24\n192.88.99.0/24\n192.168.0.0/16\n198.18.0.0/15\n198.51.100.0/24\n203.0.113.0/24\n224.0.0.0/4\n240.0.0.0/4\n255.255.255.255/32\n::1/128\n::ffff:127.0.0.1/104\nfc00::/7\nfe80::/10\n"
  },
  {
    "path": "cmake/FindCares.cmake",
    "content": "# FindCares.cmake - Find c-ares library\n#\n# Sets:\n#   CARES_FOUND\n#   CARES_INCLUDE_DIRS\n#   CARES_LIBRARIES\n\nfind_path(CARES_INCLUDE_DIR\n    NAMES ares.h\n    HINTS\n        /opt/homebrew/include\n        /usr/local/include\n        /opt/homebrew/opt/c-ares/include\n        /usr/local/opt/c-ares/include\n        /usr/include\n)\n\nfind_library(CARES_LIBRARY\n    NAMES cares\n    HINTS\n        /opt/homebrew/lib\n        /usr/local/lib\n        /opt/homebrew/opt/c-ares/lib\n        /usr/local/opt/c-ares/lib\n        /usr/lib\n)\n\nif(CARES_INCLUDE_DIR AND CARES_LIBRARY)\n    set(CARES_FOUND TRUE)\n    set(CARES_INCLUDE_DIRS ${CARES_INCLUDE_DIR})\n    set(CARES_LIBRARIES ${CARES_LIBRARY})\n\n    # Verify ares_library_init exists\n    include(CheckLibraryExists)\n    check_library_exists(cares ares_library_init \"\" CARES_HAS_INIT)\n    if(NOT CARES_HAS_INIT)\n        message(WARNING \"c-ares found but ares_library_init not detected. Proceeding anyway.\")\n    endif()\n\n    message(STATUS \"Found c-ares: ${CARES_LIBRARY}\")\nelse()\n    set(CARES_FOUND FALSE)\n    message(FATAL_ERROR \"Could not find c-ares library. Install libc-ares-dev or equivalent.\")\nendif()\n"
  },
  {
    "path": "cmake/FindMbedTLS.cmake",
    "content": "# FindMbedTLS.cmake - Find mbedTLS library with feature detection\n#\n# Sets:\n#   MBEDTLS_FOUND\n#   MBEDTLS_INCLUDE_DIRS\n#   MBEDTLS_CRYPTO_LIBRARY\n#   MBEDTLS_TLS_LIBRARY\n\ninclude(CheckCSourceCompiles)\n\n# mbedtls@3 is keg-only on Homebrew; also check versioned opt paths\nfind_path(MBEDTLS_INCLUDE_DIR\n    NAMES mbedtls/cipher.h\n    HINTS\n        /opt/homebrew/opt/mbedtls@3/include\n        /usr/local/opt/mbedtls@3/include\n        /opt/homebrew/opt/mbedtls/include\n        /usr/local/opt/mbedtls/include\n        /opt/homebrew/include\n        /usr/local/include\n        /usr/include\n)\n\nfind_library(MBEDTLS_CRYPTO_LIBRARY\n    NAMES mbedcrypto\n    HINTS\n        /opt/homebrew/opt/mbedtls@3/lib\n        /usr/local/opt/mbedtls@3/lib\n        /opt/homebrew/opt/mbedtls/lib\n        /usr/local/opt/mbedtls/lib\n        /opt/homebrew/lib\n        /usr/local/lib\n        /usr/lib\n)\n\nfind_library(MBEDTLS_TLS_LIBRARY\n    NAMES mbedtls\n    HINTS\n        /opt/homebrew/opt/mbedtls@3/lib\n        /usr/local/opt/mbedtls@3/lib\n        /opt/homebrew/opt/mbedtls/lib\n        /usr/local/opt/mbedtls/lib\n        /opt/homebrew/lib\n        /usr/local/lib\n        /usr/lib\n)\n\nif(MBEDTLS_INCLUDE_DIR AND MBEDTLS_CRYPTO_LIBRARY)\n    set(MBEDTLS_FOUND TRUE)\n    set(MBEDTLS_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIR})\n\n    # Check for required CFB mode support\n    set(CMAKE_REQUIRED_INCLUDES ${MBEDTLS_INCLUDE_DIR})\n    set(CMAKE_REQUIRED_LIBRARIES ${MBEDTLS_CRYPTO_LIBRARY})\n\n    check_c_source_compiles(\"\n        #include <mbedtls/cipher.h>\n        #if !defined(MBEDTLS_CIPHER_MODE_CFB)\n        #error CFB mode not supported\n        #endif\n        int main(void) { return 0; }\n    \" MBEDTLS_HAS_CFB)\n\n    if(NOT MBEDTLS_HAS_CFB)\n        # Try mbedtls 3.x config path\n        check_c_source_compiles(\"\n            #include <mbedtls/build_info.h>\n            #include <mbedtls/cipher.h>\n            #if !defined(MBEDTLS_CIPHER_MODE_CFB)\n            #error CFB mode not supported\n            #endif\n            int main(void) { return 0; }\n        \" MBEDTLS_HAS_CFB_V3)\n\n        if(NOT MBEDTLS_HAS_CFB_V3)\n            message(FATAL_ERROR \"mbedTLS found but MBEDTLS_CIPHER_MODE_CFB is not enabled. \"\n                \"Please enable CFB mode in your mbedTLS configuration.\")\n        endif()\n    endif()\n\n    unset(CMAKE_REQUIRED_INCLUDES)\n    unset(CMAKE_REQUIRED_LIBRARIES)\n\n    message(STATUS \"Found mbedTLS: ${MBEDTLS_CRYPTO_LIBRARY}\")\nelse()\n    set(MBEDTLS_FOUND FALSE)\n    message(FATAL_ERROR \"Could not find mbedTLS library. Install libmbedtls-dev or equivalent.\")\nendif()\n"
  },
  {
    "path": "cmake/FindPCRE2.cmake",
    "content": "# FindPCRE2.cmake - Find PCRE2 library (8-bit)\n#\n# Sets:\n#   PCRE2_FOUND\n#   PCRE2_INCLUDE_DIRS\n#   PCRE2_LIBRARIES\n\ninclude(FindPkgConfig)\n\nif(PKG_CONFIG_FOUND)\n    pkg_check_modules(_PCRE2 QUIET libpcre2-8)\nendif()\n\nif(_PCRE2_FOUND)\n    set(PCRE2_INCLUDE_DIRS ${_PCRE2_INCLUDE_DIRS})\n    set(PCRE2_LIBRARIES ${_PCRE2_LIBRARIES})\n    set(PCRE2_FOUND TRUE)\nelse()\n    # Try pcre2-config\n    find_program(PCRE2_CONFIG pcre2-config)\n    if(PCRE2_CONFIG)\n        execute_process(COMMAND ${PCRE2_CONFIG} --cflags\n            OUTPUT_VARIABLE PCRE2_CFLAGS\n            OUTPUT_STRIP_TRAILING_WHITESPACE)\n        execute_process(COMMAND ${PCRE2_CONFIG} --libs8\n            OUTPUT_VARIABLE PCRE2_LDFLAGS\n            OUTPUT_STRIP_TRAILING_WHITESPACE)\n        string(REGEX REPLACE \"-I\" \"\" PCRE2_INCLUDE_DIRS \"${PCRE2_CFLAGS}\")\n        set(PCRE2_LIBRARIES ${PCRE2_LDFLAGS})\n        set(PCRE2_FOUND TRUE)\n    else()\n        # Manual search\n        find_path(PCRE2_INCLUDE_DIR\n            NAMES pcre2.h\n            HINTS\n                /opt/homebrew/include\n                /usr/local/include\n                /usr/include\n        )\n\n        find_library(PCRE2_LIBRARY\n            NAMES pcre2-8\n            HINTS\n                /opt/homebrew/lib\n                /usr/local/lib\n                /usr/lib\n        )\n\n        if(PCRE2_INCLUDE_DIR AND PCRE2_LIBRARY)\n            set(PCRE2_INCLUDE_DIRS ${PCRE2_INCLUDE_DIR})\n            set(PCRE2_LIBRARIES ${PCRE2_LIBRARY})\n            set(PCRE2_FOUND TRUE)\n        else()\n            set(PCRE2_FOUND FALSE)\n        endif()\n    endif()\nendif()\n\nif(PCRE2_FOUND)\n    message(STATUS \"Found PCRE2: ${PCRE2_LIBRARIES}\")\nelse()\n    message(FATAL_ERROR \"Could not find PCRE2 library. Install libpcre2-dev or equivalent.\")\nendif()\n"
  },
  {
    "path": "cmake/FindSodium.cmake",
    "content": "# FindSodium.cmake - Find libsodium with version check\n#\n# Sets:\n#   SODIUM_FOUND\n#   SODIUM_INCLUDE_DIRS\n#   SODIUM_LIBRARIES\n\nfind_path(SODIUM_INCLUDE_DIR\n    NAMES sodium.h\n    HINTS\n        /opt/homebrew/include\n        /usr/local/include\n        /usr/local/opt/libsodium/include\n        /opt/homebrew/opt/libsodium/include\n        /usr/include\n        $ENV{LIBSODIUM_INCLUDE_DIR}\n        $ENV{LIBSODIUM_DIR}/include\n)\n\nfind_library(SODIUM_LIBRARY\n    NAMES sodium\n    HINTS\n        /opt/homebrew/lib\n        /usr/local/lib\n        /usr/local/opt/libsodium/lib\n        /opt/homebrew/opt/libsodium/lib\n        /usr/lib\n)\n\nif(SODIUM_INCLUDE_DIR AND SODIUM_LIBRARY)\n    set(SODIUM_FOUND TRUE)\n    set(SODIUM_INCLUDE_DIRS ${SODIUM_INCLUDE_DIR})\n    set(SODIUM_LIBRARIES ${SODIUM_LIBRARY})\n\n    # Version check: require SODIUM_LIBRARY_VERSION_MAJOR >= 7 (libsodium >= 1.0.4)\n    include(CheckCSourceCompiles)\n    set(CMAKE_REQUIRED_INCLUDES ${SODIUM_INCLUDE_DIR})\n    set(CMAKE_REQUIRED_LIBRARIES ${SODIUM_LIBRARY})\n    check_c_source_compiles(\"\n        #include <sodium.h>\n        #if SODIUM_LIBRARY_VERSION_MAJOR < 7\n        #error libsodium too old\n        #endif\n        int main(void) { return 0; }\n    \" SODIUM_VERSION_OK)\n    unset(CMAKE_REQUIRED_INCLUDES)\n    unset(CMAKE_REQUIRED_LIBRARIES)\n\n    if(NOT SODIUM_VERSION_OK)\n        message(FATAL_ERROR \"libsodium found but version is too old. Require >= 1.0.4 (SODIUM_LIBRARY_VERSION_MAJOR >= 7)\")\n    endif()\n\n    message(STATUS \"Found libsodium: ${SODIUM_LIBRARY}\")\nelse()\n    set(SODIUM_FOUND FALSE)\n    message(FATAL_ERROR \"Could not find libsodium. Install libsodium-dev or equivalent.\")\nendif()\n"
  },
  {
    "path": "cmake/config.h.cmake",
    "content": "#ifndef _SHADOWSOCKS_CONFIG_H\n#define _SHADOWSOCKS_CONFIG_H\n\n/* Define if building universal (internal helper macro) */\n#cmakedefine AC_APPLE_UNIVERSAL_BUILD\n\n/* errno for incomplete non-blocking connect(2) */\n#cmakedefine CONNECT_IN_PROGRESS @CONNECT_IN_PROGRESS@\n\n/* Define to 1 if you have the <arpa/inet.h> header file. */\n#cmakedefine HAVE_ARPA_INET_H 1\n\n/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you\n   don't. */\n#cmakedefine HAVE_DECL_INET_NTOP 1\n\n/* Define to 1 if you have the <dlfcn.h> header file. */\n#cmakedefine HAVE_DLFCN_H 1\n\n/* Define to 1 if you have the <ev.h> header file. */\n#cmakedefine HAVE_EV_H 1\n\n/* Define to 1 if you have the <fcntl.h> header file. */\n#cmakedefine HAVE_FCNTL_H 1\n\n/* Define to 1 if you have the `fork' function. */\n#cmakedefine HAVE_FORK 1\n\n/* Define to 1 if you have the `getpwnam_r' function. */\n#cmakedefine HAVE_GETPWNAM_R 1\n\n/* Define to 1 if you have the `inet_ntop' function. */\n#cmakedefine HAVE_INET_NTOP 1\n\n/* Define to 1 if you have the <inttypes.h> header file. */\n#cmakedefine HAVE_INTTYPES_H 1\n\n/* Enable IPv6 support in libudns */\n#cmakedefine HAVE_IPv6 1\n\n/* Define to 1 if you have the <langinfo.h> header file. */\n#cmakedefine HAVE_LANGINFO_H 1\n\n/* Compiling with pcre support */\n#cmakedefine HAVE_LIBPCRE 1\n\n/* Define to 1 if you have the `socket' library (-lsocket). */\n#cmakedefine HAVE_LIBSOCKET 1\n\n/* Define to 1 if you have the <limits.h> header file. */\n#cmakedefine HAVE_LIMITS_H 1\n\n/* Define to 1 if you have the <linux/if.h> header file. */\n#cmakedefine HAVE_LINUX_IF_H 1\n\n/* Define to 1 if you have the <linux/tcp.h> header file. */\n#cmakedefine HAVE_LINUX_TCP_H\n\n/* Define to 1 if you have the <netinet/tcp.h> header file. */\n#cmakedefine HAVE_NETINET_TCP_H\n\n/* Define to 1 if you have the <linux/netfilter_ipv4.h> header file. */\n#cmakedefine HAVE_LINUX_NETFILTER_IPV4_H 1\n\n/* Define to 1 if you have the <linux/netfilter_ipv6/ip6_tables.h> header\n   file. */\n#cmakedefine HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H 1\n\n/* Define to 1 if you have the <locale.h> header file. */\n#cmakedefine HAVE_LOCALE_H 1\n\n/* Define to 1 if you have the `malloc' function. */\n#cmakedefine HAVE_MALLOC 1\n\n/* Define to 1 if you have the <memory.h> header file. */\n#cmakedefine HAVE_MEMORY_H 1\n\n/* Define to 1 if you have the `memset' function. */\n#cmakedefine HAVE_MEMSET 1\n\n/* Define to 1 if you have the <netdb.h> header file. */\n#cmakedefine HAVE_NETDB_H 1\n\n/* Define to 1 if you have the <netinet/in.h> header file. */\n#cmakedefine HAVE_NETINET_IN_H 1\n\n/* Define to 1 if you have the <net/if.h> header file. */\n#cmakedefine HAVE_NET_IF_H 1\n\n/* Define to 1 if you have the <pcre2.h> header file. */\n#cmakedefine HAVE_PCRE2_H 1\n\n/* Have PTHREAD_PRIO_INHERIT. */\n#cmakedefine HAVE_PTHREAD_PRIO_INHERIT 1\n\n/* Define to 1 if you have the `select' function. */\n#cmakedefine HAVE_SELECT 1\n\n/* Define to 1 if you have the `setresuid' function. */\n#cmakedefine HAVE_SETRESUID 1\n\n/* Define to 1 if you have the `setreuid' function. */\n#cmakedefine HAVE_SETREUID 1\n\n/* Define to 1 if you have the `setrlimit' function. */\n#cmakedefine HAVE_SETRLIMIT 1\n\n/* Define to 1 if you have the `socket' function. */\n#cmakedefine HAVE_SOCKET 1\n\n/* Define to 1 if you have the <stdint.h> header file. */\n#cmakedefine HAVE_STDINT_H 1\n\n/* Define to 1 if you have the <stdlib.h> header file. */\n#cmakedefine HAVE_STDLIB_H 1\n\n/* Define to 1 if you have the `strerror' function. */\n#cmakedefine HAVE_STRERROR 1\n\n/* Define to 1 if you have the <strings.h> header file. */\n#cmakedefine HAVE_STRINGS_H 1\n\n/* Define to 1 if you have the <string.h> header file. */\n#cmakedefine HAVE_STRING_H 1\n\n/* Define to 1 if you have the <sys/ioctl.h> header file. */\n#cmakedefine HAVE_SYS_IOCTL_H 1\n\n/* Define to 1 if you have the <sys/select.h> header file. */\n#cmakedefine HAVE_SYS_SELECT_H 1\n\n/* Define to 1 if you have the <sys/socket.h> header file. */\n#cmakedefine HAVE_SYS_SOCKET_H 1\n\n/* Define to 1 if you have the <sys/stat.h> header file. */\n#cmakedefine HAVE_SYS_STAT_H 1\n\n/* Define to 1 if you have the <sys/types.h> header file. */\n#cmakedefine HAVE_SYS_TYPES_H 1\n\n/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */\n#cmakedefine HAVE_SYS_WAIT_H 1\n\n/* Define to 1 if you have the <udns.h> header file. */\n#cmakedefine HAVE_UDNS_H 1\n\n/* Define to 1 if you have the <unistd.h> header file. */\n#cmakedefine HAVE_UNISTD_H 1\n\n/* Define to 1 if you have the `vfork' function. */\n#cmakedefine HAVE_VFORK 1\n\n/* Define to 1 if you have the <vfork.h> header file. */\n#cmakedefine HAVE_VFORK_H 1\n\n/* Define to 1 if `fork' works. */\n#cmakedefine HAVE_WORKING_FORK 1\n\n/* Define to 1 if `vfork' works. */\n#cmakedefine HAVE_WORKING_VFORK 1\n\n/* Define to the sub-directory where libtool stores uninstalled libraries. */\n#cmakedefine LT_OBJDIR \"@LT_OBJDIR@\"\n\n/* Define to 1 if assertions should be disabled. */\n#cmakedefine NDEBUG 1\n\n/* Name of package */\n#define PACKAGE \"@PROJECT_NAME@\"\n\n/* Define to the address where bug reports for this package should be sent. */\n#define PACKAGE_BUGREPORT \"@PACKAGE_BUGREPORT@\"\n\n/* Define to the full name of this package. */\n#define PACKAGE_NAME \"@PROJECT_NAME@\"\n\n/* Define to the full name and version of this package. */\n#define PACKAGE_STRING \"@PROJECT_NAME@ @PROJECT_VERSION@\"\n\n/* Define to the one symbol short name of this package. */\n#define PACKAGE_TARNAME \"@PROJECT_NAME@\"\n\n/* Define to the home page for this package. */\n#define PACKAGE_URL \"@PACKAGE_URL@\"\n\n/* Define to the version of this package. */\n#define PACKAGE_VERSION \"@PROJECT_VERSION@\"\n\n/* Define to necessary symbol if this constant uses a non-standard name on\n   your system. */\n#cmakedefine PTHREAD_CREATE_JOINABLE 1\n\n/* Define as the return type of signal handlers (`int' or `void'). */\n#cmakedefine RETSIGTYPE @RETSIGTYPE@\n\n/* Define to the type of arg 1 for `select'. */\n#cmakedefine SELECT_TYPE_ARG1 @SELECT_TYPE_ARG1@\n\n/* Define to the type of args 2, 3 and 4 for `select'. */\n#cmakedefine SELECT_TYPE_ARG234 @SELECT_TYPE_ARG234@\n\n/* Define to the type of arg 5 for `select'. */\n#cmakedefine SELECT_TYPE_ARG5 @SELECT_TYPE_ARG5@\n\n/* Define to 1 if you have the ANSI C header files. */\n#cmakedefine STDC_HEADERS 1\n\n/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */\n#cmakedefine TIME_WITH_SYS_TIME 1\n\n/* If the compiler supports a TLS storage class define it to that here */\n#cmakedefine TLS @TLS@\n\n/* Enable extensions on AIX 3, Interix.  */\n#ifndef _ALL_SOURCE\n#cmakedefine _ALL_SOURCE 1\n#endif\n/* Enable GNU extensions on systems that have them.  */\n#ifndef _GNU_SOURCE\n#cmakedefine _GNU_SOURCE 1\n#endif\n/* Enable threading extensions on Solaris.  */\n#ifndef _POSIX_PTHREAD_SEMANTICS\n#cmakedefine _POSIX_PTHREAD_SEMANTICS 1\n#endif\n/* Enable extensions on HP NonStop.  */\n#ifndef _TANDEM_SOURCE\n#cmakedefine _TANDEM_SOURCE 1\n#endif\n/* Enable general extensions on Solaris.  */\n#ifndef __EXTENSIONS__\n#cmakedefine __EXTENSIONS__ 1\n#endif\n\n\n/* Enable support for QOS netfilter mark preservation */\n#cmakedefine USE_NFCONNTRACK_TOS 1\n\n/* Enable support for nftables firewall */\n#cmakedefine USE_NFTABLES 1\n\n/* Define to 1 if you have the <linux/random.h> header file. */\n#cmakedefine HAVE_LINUX_RANDOM_H 1\n\n/* Define to 1 if you have the `get_current_dir_name' function. */\n#cmakedefine HAVE_GET_CURRENT_DIR_NAME 1\n\n/* Define to 1 if you have the `posix_memalign' function. */\n#cmakedefine HAVE_POSIX_MEMALIGN 1\n\n/* Define if use system shared lib. */\n#cmakedefine USE_SYSTEM_SHARED_LIB 1\n\n/* Version number of package */\n#define VERSION \"@PROJECT_VERSION@\"\n\n/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most\n   significant byte first (like Motorola and SPARC, unlike Intel). */\n#if defined AC_APPLE_UNIVERSAL_BUILD\n# if defined __BIG_ENDIAN__\n#  define WORDS_BIGENDIAN 1\n# endif\n#else\n# ifndef WORDS_BIGENDIAN\n#cmakedefine WORDS_BIGENDIAN 1\n# endif\n#endif\n\n/* Define to 1 if on MINIX. */\n#cmakedefine _MINIX 1\n\n/* Define to 2 if the system does not provide POSIX.1 features except with\n   this defined. */\n#cmakedefine _POSIX_1_SOURCE 1\n\n/* Define to 1 if you need to in order for `stat' and other things to work. */\n#cmakedefine _POSIX_SOURCE 1\n\n/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,\n   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the\n   #define below would cause a syntax error. */\n#cmakedefine _UINT8_T 1\n\n/* Define to empty if `const' does not conform to ANSI C. */\n#cmakedefine const 1\n\n/* Define to `__inline__' or `__inline' if that's what the C compiler\n   calls it, or to nothing if 'inline' is not supported under any name.  */\n#ifndef __cplusplus\n#cmakedefine inline 1\n#endif\n\n/* Define to `int' if <sys/types.h> does not define. */\n#cmakedefine pid_t @pid_t@\n\n/* Define to `unsigned int' if <sys/types.h> does not define. */\n#cmakedefine size_t unsigned int\n\n/* Define to `int' if <sys/types.h> does not define. */\n#cmakedefine ssize_t int\n\n/* Define to the type of an unsigned integer type of width exactly 16 bits if\n   such a type exists and the standard includes do not define it. */\n#cmakedefine uint16_t @uint16_t@\n\n/* Define to the type of an unsigned integer type of width exactly 8 bits if\n   such a type exists and the standard includes do not define it. */\n#cmakedefine uint8_t @uint8_t@\n\n/* Define as `fork' if `vfork' does not work. */\n#cmakedefine vfork\n\n#endif\n"
  },
  {
    "path": "cmake/configure.cmake",
    "content": "\n# -------------------------------------------------------------\n# config.h\n\n# Use cmake to generate config.h\ninclude(CheckIncludeFiles)\ninclude(CheckFunctionExists)\ninclude(CheckSymbolExists)\ninclude(CheckLibraryExists)\ninclude(CheckTypeSize)\ninclude(CheckCSourceCompiles)\ninclude(CheckCCompilerFlag)\n\n# Define if building universal (internal helper macro)\n# AC_APPLE_UNIVERSAL_BUILD\n\n# Set CONNECT_IN_PROGRESS based on platform\nif(MINGW)\n    set(CONNECT_IN_PROGRESS \"WSAEWOULDBLOCK\")\nelse()\n    set(CONNECT_IN_PROGRESS \"EINPROGRESS\")\nendif()\n\nif (CMAKE_SYSTEM_NAME STREQUAL Darwin)\n    set(CMAKE_REQUIRED_INCLUDES \"/usr/local/include\" \"/usr/include\" \"/opt/homebrew/include\")\nendif ()\n\ncheck_include_files(dlfcn.h HAVE_DLFCN_H)\ncheck_include_files(ev.h HAVE_EV_H)\ncheck_include_files(fcntl.h HAVE_FCNTL_H)\ncheck_function_exists(fork HAVE_FORK)\ncheck_function_exists(getpwnam_r HAVE_GETPWNAM_R)\ncheck_function_exists(inet_ntop HAVE_INET_NTOP)\ncheck_include_files(inttypes.h HAVE_INTTYPES_H)\nset(HAVE_IPv6 1)\ncheck_include_files(langinfo.h HAVE_LANGINFO_H)\nset(HAVE_LIBPCRE 1)\ncheck_library_exists(socket socket \"\" HAVE_LIBSOCKET)\ncheck_include_files(limits.h HAVE_LIMITS_H)\ncheck_include_files(linux/if.h HAVE_LINUX_IF_H)\ncheck_include_files(linux/netfilter_ipv4.h HAVE_LINUX_NETFILTER_IPV4_H)\ncheck_include_files(linux/netfilter_ipv6/ip6_tables.h HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H)\ncheck_include_files(locale.h HAVE_LOCALE_H)\n\n\ncheck_function_exists(malloc HAVE_MALLOC)\ncheck_include_files(memory.h HAVE_MEMORY_H)\ncheck_function_exists(memset HAVE_MEMSET)\n\ncheck_include_files(netdb.h HAVE_NETDB_H)\ncheck_include_files(netinet/in.h HAVE_NETINET_IN_H)\nif (CYGWIN)\n    check_include_files(\"sys/types.h;netinet/tcp.h\" HAVE_NETINET_TCP_H)\nelse ()\n    check_include_files(netinet/tcp.h HAVE_NETINET_TCP_H)\nendif ()\ncheck_include_files(linux/tcp.h HAVE_LINUX_TCP_H)\ncheck_include_files(net/if.h HAVE_NET_IF_H)\nset(CMAKE_REQUIRED_DEFINITIONS_SAVE ${CMAKE_REQUIRED_DEFINITIONS})\nset(CMAKE_REQUIRED_DEFINITIONS \"-DPCRE2_CODE_UNIT_WIDTH=8\")\ncheck_include_files(pcre2.h HAVE_PCRE2_H)\nset(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS_SAVE})\ncheck_symbol_exists(PTHREAD_PRIO_INHERIT pthread.h HAVE_PTHREAD_PRIO_INHERIT)\n\ncheck_function_exists(select HAVE_SELECT)\ncheck_function_exists(setresuid HAVE_SETRESUID)\ncheck_function_exists(setreuid HAVE_SETREUID)\ncheck_function_exists(setrlimit HAVE_SETRLIMIT)\ncheck_function_exists(socket HAVE_SOCKET)\n\ncheck_include_files(stdint.h HAVE_STDINT_H)\ncheck_include_files(stdlib.h HAVE_STDLIB_H)\n\ncheck_function_exists(strerror HAVE_STRERROR)\n\ncheck_include_files(strings.h HAVE_STRINGS_H)\ncheck_include_files(string.h HAVE_STRING_H)\ncheck_include_files(sys/ioctl.h HAVE_SYS_IOCTL_H)\ncheck_include_files(sys/select.h HAVE_SYS_SELECT_H)\ncheck_include_files(sys/socket.h HAVE_SYS_SOCKET_H)\ncheck_include_files(sys/stat.h HAVE_SYS_STAT_H)\ncheck_include_files(sys/types.h HAVE_SYS_TYPES_H)\ncheck_include_files(sys/wait.h HAVE_SYS_WAIT_H)\ncheck_include_files(ares.h HAVE_ARES_H)\ncheck_include_files(unistd.h HAVE_UNISTD_H)\ncheck_include_files(arpa/inet.h HAVE_ARPA_INET_H)\ncheck_include_files(linux/random.h HAVE_LINUX_RANDOM_H)\n\ncheck_function_exists(fork HAVE_FORK)\ncheck_function_exists(vfork HAVE_VFORK)\ncheck_include_files(vfork.h HAVE_VFORK_H)\nif (HAVE_VFORK)\n    set(HAVE_WORKING_VFORK 1)\nendif ()\nif (HAVE_FORK)\n    set(HAVE_WORKING_FORK 1)\nendif ()\n\n# Additional function checks\ncheck_function_exists(get_current_dir_name HAVE_GET_CURRENT_DIR_NAME)\ncheck_function_exists(posix_memalign HAVE_POSIX_MEMALIGN)\n\n# Define to the sub-directory where libtool stores uninstalled libraries.\nset(LT_OBJDIR \".libs/\")\nset(NDEBUG 1)\nset(PACKAGE ${PROJECT_NAME})\nset(PACKAGE_BUGREPORT max.c.lv@gmail.com)\nset(PACKAGE_NAME ${PROJECT_NAME})\nset(PACKAGE_VERSION ${PROJECT_VERSION})\nset(PACKAGE_STRING \"${PROJECT_NAME} ${PACKAGE_VERSION}\")\nset(PACKAGE_TARNAME ${PROJECT_NAME})\nset(PACKAGE_URL \"\")\n\n# PTHREAD_CREATE_JOINABLE\n\n# Define as the return type of signal handlers (`int' or `void').\nset(RETSIGTYPE void)\n\n# Define to the type of arg 1 for `select'.\nset(SELECT_TYPE_ARG1 int)\n\n# Define to the type of args 2, 3 and 4 for `select'.\nset(SELECT_TYPE_ARG234 \"(fd_set *)\")\n\n# Define to the type of arg 5 for `select'.\nset(SELECT_TYPE_ARG5 \"(struct timeval *)\")\n\n# Define to 1 if you have the ANSI C header files.\nset(STDC_HEADERS 1)\n\n\ncheck_include_files(\"sys/time.h;time.h\" TIME_WITH_SYS_TIME)\n\n\n# If the compiler supports a TLS storage class define it to that here\ncheck_c_source_compiles(\"\n        __thread int tls;\n        int main(void) { return 0; }\"\n        HAVE_GCC_THREAD_LOCAL_STORAGE)\nif (HAVE_GCC_THREAD_LOCAL_STORAGE)\n    set(TLS __thread)\nendif ()\n\nset(_ALL_SOURCE 1)\nset(_GNU_SOURCE 1)\nset(_POSIX_PTHREAD_SEMANTICS 1)\nset(_TANDEM_SOURCE 1)\nset(__EXTENSIONS__ 1)\n# USE_SYSTEM_SHARED_LIB\nset(VERSION ${PACKAGE_VERSION})\n\nset(CMAKE_EXTRA_INCLUDE_FILES sys/types.h)\ncheck_type_size(pid_t PID_T)\ncheck_type_size(size_t SIZE_T)\ncheck_type_size(ssize_t SSIZE_T)\nset(CMAKE_EXTRA_INCLUDE_FILES)\n\ncheck_type_size(uint16_t UINT16_T)\ncheck_type_size(uint8_t UINT8_T)\n\n## Inverse\nif (NOT HAVE_PID_T)\n    set(pid_t int)\nendif ()\nif (NOT HAVE_SIZE_T)\n    set(size_t \"unsigned int\")\nendif ()\nif (NOT HAVE_SSIZE_T)\n    set(ssize_t int)\nendif ()\n\nif (NOT HAVE_UINT8_T)\n    set(uint8_t \"unsigned char\")\nendif ()\nif (NOT HAVE_UINT16_T)\n    set(uint16_t \"unsigned short\")\nendif ()\n\n\n# Define as `fork' if `vfork' does not work.\nif (NOT HAVE_WORKING_VFORK)\n    set(vfork fork)\nendif ()\n\n# Stack protector detection\noption(DISABLE_SSP \"Disable -fstack-protector\" OFF)\nif(NOT DISABLE_SSP)\n    check_c_compiler_flag(-fstack-protector HAS_STACK_PROTECTOR)\n    if(HAS_STACK_PROTECTOR)\n        set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -fstack-protector\")\n        message(STATUS \"Stack protector enabled\")\n    endif()\nendif()\n\n# MinGW/Cygwin compiler flags\nif(MINGW OR CYGWIN)\n    set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -mno-ms-bitfields\")\nendif()\n"
  },
  {
    "path": "cmake/shadowsocks-libev.pc.cmake",
    "content": "prefix=@CMAKE_INSTALL_PREFIX@\nexec_prefix=${prefix}\nlibdir=${prefix}/@CMAKE_INSTALL_LIBDIR@\nincludedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@\n\nName: @PROJECT_NAME@\nDescription: @PROJECT_DESC@\nURL: @PROJECT_URL@\nVersion: @PROJECT_VERSION@\nRequires:\nCflags: -I${includedir}\nLibs: -L${libdir} -lshadowsocks-libev\n"
  },
  {
    "path": "completions/bash/ss-local",
    "content": "_ss_local()\n{\n    local cur prev opts ciphers\n    opts='-s -p -l -k -m -a -f -t -c -n -i -b -u -U -v -h --reuse-port --fast-open --acl --mtu --mptcp --no-delay --key --plugin --plugin-opts --help'\n    ciphers='rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf'\n    cur=${COMP_WORDS[COMP_CWORD]}\n    prev=\"${COMP_WORDS[COMP_CWORD-1]}\"\n    case \"$prev\" in\n        -f|-c|--acl)\n            _filedir || COMPREPLY=( $(compgen -o plusdirs -f ${cur}) )\n            ;;\n        -s|-b)\n            _known_hosts_real -- \"${cur}\" || OMPREPLY=( $(compgen -A hostname -- ${cur}) )\n            ;;\n        -m)\n            COMPREPLY=( $(compgen -W \"$ciphers\" -- ${cur}) )\n            ;;\n        -a)\n            _allowed_users || COMPREPLY=( $(compgen -u -- ${cur}) )\n            ;;\n        -p|-l|-k|-t|-n|--mtu|--key|--plugin|--plugin-opts)\n            ;;\n        -i)\n            _available_interfaces -a || true\n            ;;\n        *)\n            COMPREPLY+=( $(compgen -W \"${opts}\" -- ${cur}) )\n            ;;\n    esac\n    return 0\n}\n\ncomplete -F _ss_local ss-local\n"
  },
  {
    "path": "completions/bash/ss-manager",
    "content": "_ss_manager()\n{\n    local cur prev opts ciphers\n    opts='-s -p -l -k -m -a -f -t -c -n -i -b -u -U -v -h --reuse-port --manager-address --executable --mtu --mptcp --plugin --plugin-opts --help'\n    ciphers='rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf'\n    cur=${COMP_WORDS[COMP_CWORD]}\n    prev=\"${COMP_WORDS[COMP_CWORD-1]}\"\n    case \"$prev\" in\n        -f|-c|--executable)\n            _filedir || COMPREPLY=( $(compgen -o plusdirs -f ${cur}) )\n            ;;\n        -s|-b)\n            _known_hosts_real -- \"${cur}\" || OMPREPLY=( $(compgen -A hostname -- ${cur}) )\n            ;;\n        -m)\n            COMPREPLY=( $(compgen -W \"$ciphers\" -- ${cur}) )\n            ;;\n        -a)\n            _allowed_users || COMPREPLY=( $(compgen -u -- ${cur}) )\n            ;;\n        -p|-l|-k|-t|-n|--mtu|--plugin|--plugin-opts)\n            ;;\n        -i)\n            _available_interfaces -a || true\n            ;;\n        --manager-address)\n            _known_hosts_real -- \"${cur}\" || OMPREPLY=( $(compgen -A hostname -- ${cur}) )\n            _filedir || COMPREPLY+=( $(compgen -o plusdirs -f ${cur}) )\n            ;;\n        *)\n            COMPREPLY+=( $(compgen -W \"${opts}\" -- ${cur}) )\n            ;;\n    esac\n    return 0\n}\n\ncomplete -F _ss_manager ss-manager\n"
  },
  {
    "path": "completions/bash/ss-redir",
    "content": "_ss_redir()\n{\n    local cur prev opts ciphers\n    opts='-s -p -l -k -m -a -f -t -c -n -b -u -U -T -v -h --reuse-port --mtu --mptcp --key --plugin --plugin-opts --help'\n    ciphers='rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf'\n    cur=${COMP_WORDS[COMP_CWORD]}\n    prev=\"${COMP_WORDS[COMP_CWORD-1]}\"\n    case \"$prev\" in\n        -f|-c)\n            _filedir || COMPREPLY=( $(compgen -o plusdirs -f ${cur}) )\n            ;;\n        -s|-b)\n            _known_hosts_real -- \"${cur}\" || OMPREPLY=( $(compgen -A hostname -- ${cur}) )\n            ;;\n        -m)\n            COMPREPLY=( $(compgen -W \"$ciphers\" -- ${cur}) )\n            ;;\n        -a)\n            _allowed_users || COMPREPLY=( $(compgen -u -- ${cur}) )\n            ;;\n        -p|-l|-k|-t|-n|--mtu|--key|--plugin|--plugin-opts)\n            ;;\n        *)\n            COMPREPLY+=( $(compgen -W \"${opts}\" -- ${cur}) )\n            ;;\n    esac\n    return 0\n}\n\ncomplete -F _ss_redir ss-redir\n"
  },
  {
    "path": "completions/bash/ss-server",
    "content": "_ss_server()\n{\n    local cur prev opts ciphers\n    opts='-s -p -l -k -m -a -f -t -c -n -i -b -u -U -6 -d -v -h --reuse-port --fast-open --acl --manager-address --mtu --mptcp --no-delay --key --plugin --plugin-opts --help'\n    ciphers='rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf'\n    COMPREPLY=()\n    cur=${COMP_WORDS[COMP_CWORD]}\n    prev=\"${COMP_WORDS[COMP_CWORD-1]}\"\n    case \"$prev\" in\n        -f|-c|--acl)\n            _filedir || COMPREPLY=( $(compgen -o plusdirs -f ${cur}) )\n            ;;\n        -s|-b)\n            _known_hosts_real -- \"${cur}\" || OMPREPLY=( $(compgen -A hostname -- ${cur}) )\n            ;;\n        -m)\n            COMPREPLY=( $(compgen -W \"$ciphers\" -- ${cur}) )\n            ;;\n        -a)\n            _allowed_users || COMPREPLY=( $(compgen -u -- ${cur}) )\n            ;;\n        -p|-l|-k|-t|-n|-d|--mtu|--key|--plugin|--plugin-opts)\n            ;;\n        --manager-address)\n            _known_hosts_real -- \"${cur}\" || OMPREPLY=( $(compgen -A hostname -- ${cur}) )\n            _filedir || COMPREPLY+=( $(compgen -o plusdirs -f ${cur}) )\n            ;;\n        -i)\n            _available_interfaces -a || true\n            ;;\n        *)\n            COMPREPLY=( $(compgen -W \"${opts}\" -- ${cur}) )\n            ;;\n    esac\n}\n\ncomplete -F _ss_server ss-server\n"
  },
  {
    "path": "completions/bash/ss-tunnel",
    "content": "_ss_tunnel()\n{\n    local cur prev opts ciphers\n    opts='-s -p -l -k -m -a -f -t -c -n -i -b -u -U -L -v -h --reuse-port --mtu --mptcp --key --plugin --plugin-opts --help'\n    ciphers='rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf'\n    cur=${COMP_WORDS[COMP_CWORD]}\n    prev=\"${COMP_WORDS[COMP_CWORD-1]}\"\n    compopt +o nospace\n    case \"$prev\" in\n        -f|-c)\n            _filedir || COMPREPLY=( $(compgen -o plusdirs -f ${cur}) )\n            ;;\n        -s|-b)\n            _known_hosts_real -- \"${cur}\" || OMPREPLY=( $(compgen -A hostname -- ${cur}) )\n            ;;\n        -L)\n            compopt -o nospace\n            _known_hosts_real -c -- \"${cur}\" || OMPREPLY=( $(compgen -A hostname -S : -- ${cur}) )\n            ;;\n        -m)\n            COMPREPLY=( $(compgen -W \"$ciphers\" -- ${cur}) )\n            ;;\n        -a)\n            _allowed_users || COMPREPLY=( $(compgen -u -- ${cur}) )\n            ;;\n        -p|-l|-k|-t|-n|--mtu|--key|--plugin|--plugin-opts)\n            ;;\n        -i)\n            _available_interfaces -a || true\n            ;;\n        *)\n            COMPREPLY+=( $(compgen -W \"${opts}\" -- ${cur}) )\n            ;;\n    esac\n    return 0\n}\n\ncomplete -F _ss_tunnel ss-tunnel\n"
  },
  {
    "path": "completions/zsh/_ss-local",
    "content": "#compdef ss-local\n\nlocal ciphers\nciphers='(rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)'\n\n_arguments \"-h::\" \\\n           \"-s:server host:_hosts\" \\\n           \"-p:server port:\" \\\n           \"-l:local port:\" \\\n           \"-k:password:\" \\\n           \"-m:encrypt method:$ciphers\" \\\n           \"-a:run as user:_users\" \\\n           \"-f:pid file:_files\" \\\n           \"-t:timeout:\" \\\n           \"-c:configure file:_files\" \\\n           \"-n:max number of open files:\" \\\n           \"-i:bind interface:_net_interfaces\" \\\n           \"-b:local address:(127.0.0.1 \\:\\:1 0.0.0.0 \\:\\:)\" \\\n           \"-u:enable udp:\" \\\n           \"-U:udp only:\" \\\n           \"-v:verbose mode:\" \\\n           \"--reuse-port::\" \\\n           \"--fast-open::\" \\\n           \"--acl:acl file:_files\" \\\n           \"--mtu::\" \\\n           \"--mptcp::\" \\\n           \"--no-delay::\" \\\n           \"--key:key in base64:\" \\\n           \"--plugin:plugin name:\" \\\n           \"--plugin-opts:plugin options:\" \\\n           \"--help::\"\n\n"
  },
  {
    "path": "completions/zsh/_ss-manager",
    "content": "#compdef ss-manager\n\nlocal ciphers\nciphers='(rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)'\n\n_arguments \"-h::\" \\\n           \"-s:server host:_hosts\" \\\n           \"-p:server port:\" \\\n           \"-l:local port:\" \\\n           \"-k:password:\" \\\n           \"-m:encrypt method:$ciphers\" \\\n           \"-a:run as user:_users\" \\\n           \"-f:pid file:_files\" \\\n           \"-t:timeout:\" \\\n           \"-c:configure file:_files\" \\\n           \"-n:max number of open files:\" \\\n           \"-i:bind interface:_net_interfaces\" \\\n           \"-b:local address:(127.0.0.1 \\:\\:1 0.0.0.0 \\:\\:)\" \\\n           \"-u:enable udp:\" \\\n           \"-U:udp only:\" \\\n           \"-v:verbose mode:\" \\\n           \"--executable:path to ss-server:_files\" \\\n           \"--manager-address:manager address:\" \\\n           \"--reuse-port::\" \\\n           \"--acl:acl file:_files\" \\\n           \"--mtu::\" \\\n           \"--key:key in base64:\" \\\n           \"--plugin:plugin name:\" \\\n           \"--plugin-opts:plugin options:\" \\\n           \"--help::\"\n\n"
  },
  {
    "path": "completions/zsh/_ss-redir",
    "content": "#compdef ss-redir\n\nlocal ciphers\nciphers='(rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)'\n\n_arguments \"-h::\" \\\n           \"-s:server host:_hosts\" \\\n           \"-p:server port:\" \\\n           \"-l:local port:\" \\\n           \"-k:password:\" \\\n           \"-m:encrypt method:$ciphers\" \\\n           \"-a:run as user:_users\" \\\n           \"-f:pid file:_files\" \\\n           \"-t:timeout:\" \\\n           \"-c:configure file:_files\" \\\n           \"-n:nofile:\" \\\n           \"-b:local address:(127.0.0.1 \\:\\:1 0.0.0.0 \\:\\:)\" \\\n           \"-u:enable udp:\" \\\n           \"-U:udp only:\" \\\n           \"-v:verbose mode:\" \\\n           \"-T:tcp tproxy mode:\" \\\n           \"--reuse-port::\" \\\n           \"--fast-open::\" \\\n           \"--acl:acl file:_files\" \\\n           \"--mtu::\" \\\n           \"--mptcp::\" \\\n           \"--no-delay::\" \\\n           \"--key:key in base64:\" \\\n           \"--plugin:plugin name:\" \\\n           \"--plugin-opts:plugin options:\" \\\n           \"--help::\"\n\n"
  },
  {
    "path": "completions/zsh/_ss-server",
    "content": "#compdef ss-server\n\nlocal ciphers\nciphers='(rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)'\n\n_arguments \"-h::\" \\\n           \"-s:server host:_hosts\" \\\n           \"-p:server port:\" \\\n           \"-l:local port:\" \\\n           \"-k:password:\" \\\n           \"-m:encrypt method:$ciphers\" \\\n           \"-a:run as user:_users\" \\\n           \"-f:pid file:_files\" \\\n           \"-t:timeout:\" \\\n           \"-c:configure file:_files\" \\\n           \"-n:max number of open files:\" \\\n           \"-i:bind interface:_net_interfaces\" \\\n           \"-b:local address:(127.0.0.1 \\:\\:1 0.0.0.0 \\:\\:)\" \\\n           \"-u:enable udp:\" \\\n           \"-U:udp only:\" \\\n           \"-v:verbose mode:\" \\\n           \"-6:ipv6 first:\" \\\n           \"-d:nameserver for internal dns:\" \\\n           \"--manager-address:manager address:\" \\\n           \"--reuse-port::\" \\\n           \"--fast-open::\" \\\n           \"--acl:acl file:_files\" \\\n           \"--mtu::\" \\\n           \"--mptcp::\" \\\n           \"--no-delay::\" \\\n           \"--key:key in base64:\" \\\n           \"--plugin:plugin name:\" \\\n           \"--plugin-opts:plugin options:\" \\\n           \"--help::\"\n\n"
  },
  {
    "path": "completions/zsh/_ss-tunnel",
    "content": "#compdef ss-tunnel\n\nlocal ciphers\nciphers='(rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)'\n\n_arguments \"-h::\" \\\n           \"-s:server host:_hosts\" \\\n           \"-p:server port:\" \\\n           \"-l:local port:\" \\\n           \"-k:password:\" \\\n           \"-m:encrypt method:$ciphers\" \\\n           \"-a:run as user:_users\" \\\n           \"-f:pid file:_files\" \\\n           \"-t:timeout:\" \\\n           \"-c:configure file:_files\" \\\n           \"-n:nofile:\" \\\n           \"-i:bind interface:_net_interfaces\" \\\n           \"-b:local address:(127.0.0.1 \\:\\:1 0.0.0.0 \\:\\:)\" \\\n           \"-u:enable udp:\" \\\n           \"-U:udp only:\" \\\n           \"-v:verbose mode:\" \\\n           \"-L:destination server address and port:\" \\\n           \"--reuse-port::\" \\\n           \"--acl:acl file:_files\" \\\n           \"--mtu::\" \\\n           \"--key:key in base64:\" \\\n           \"--plugin:plugin name:\" \\\n           \"--plugin-opts:plugin options:\" \\\n           \"--help::\"\n\n"
  },
  {
    "path": "debian/.gitignore",
    "content": "*.substvars\ndebhelper-build-stamp\nlibshadowsocks-libev*/\nlibshadowsocks-libev-dev/\ntmp/\n"
  },
  {
    "path": "debian/README.Debian",
    "content": "shadowsocks-libev for Debian\n----------------------------\n\nThe Debian package has added systemd support. A default server service which\nreads the default configuration in /etc/default/shadowsocks-libev is installed\nand enabled by default, plus some other service templates placed in\n/lib/systemd/system, which can be used by users later.\n\nThe systemd service templates accept one parameter to determine the\nconfiguration json file that is used by this instance. For example,\nif the user starts a service called \"shadowsocks-libev-local@foobar.service\",\nThis service instance will start the \"ss-local\" client and read\n/etc/shadowsocks-libev/foobar.json as its configuration file.\n\n -- Boyuan Yang <byang@debian.org>  Thu, 08 Sep 2016 19:01:20 +0800\n"
  },
  {
    "path": "debian/changelog",
    "content": "shadowsocks-libev (3.3.6-1) unstable; urgency=medium\n\n  * Reduce memory copies in crypto encrypt/decrypt paths.\n  * Fix unbounded buffer growth in aead_decrypt chunk reassembly.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 09 Feb 2026 08:00:00 +0800\n\nshadowsocks-libev (3.3.5-1) unstable; urgency=medium\n\n  * Remove the SNI proxy function.\n  * Minor bug fixes. (#2581, #2582, #2590, #2595, #2599,\n    #2600, #2620, #2687, #2692)\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 15 Sep 2020 10:24:43 +0800\n\nshadowsocks-libev (3.3.4-1) unstable; urgency=medium\n\n  * Minor bug fixes. (#2539, #2565, #2566, #2577)\n  * Security bug fixes. (CVE-2019-5163, CVE-2019-5164)\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 10 Jan 2020 09:28:25 +0800\n\nshadowsocks-libev (3.3.3-1) unstable; urgency=medium\n\n  * Refine the handling of suspicious connections.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 31 Oct 2019 15:06:04 +0800\n\nshadowsocks-libev (3.3.2-1) unstable; urgency=medium\n\n  * Refine the handling of fragment request.\n  * Minor bug fixes. (#2463, #2481, #2508)\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 12 Oct 2019 08:42:24 +0800\n\nshadowsocks-libev (3.3.1-1) unstable; urgency=high\n\n  * Fix a high CPU bug introduced in 3.3.0. (#2449)\n  * Fix MinGW build. (#2438)\n  * Minor bug fixes. (#2402, #2412, #2427, #2443)\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 09 Aug 2019 15:02:34 +0800\n\nshadowsocks-libev (3.3.0-1) unstable; urgency=medium\n\n  * Enlarge the socket buffer size to 16KB.\n  * Fix the empty list bug in ss-manager.\n  * Fix the IPv6 address parser.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 08 Jun 2019 07:53:20 +0800\n\nshadowsocks-libev (3.2.5-1) unstable; urgency=medium\n\n  * Fix a bug of port parser.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 09 Mar 2019 18:54:36 +0800\n\nshadowsocks-libev (3.2.4-1) unstable; urgency=medium\n\n  * Fix a crash with MinGW.\n  * Refine SIP003 plugin interface.\n  * Remove connection timeout from all clients.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 26 Feb 2019 09:40:18 +0800\n\nshadowsocks-libev (3.2.3-1) unstable; urgency=medium\n\n  * Fix the alignment issue again.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 28 Nov 2018 00:27:40 -0800\n\nshadowsocks-libev (3.2.2-1) unstable; urgency=medium\n\n  * Fix a bug on 32-bit arch.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 26 Nov 2018 20:07:21 -0800\n\nshadowsocks-libev (3.2.1-1) unstable; urgency=medium\n\n  * Add TCP fast open support to ss-tunnel by @PantherJohn.\n  * Fix several security issues.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 07 Nov 2018 22:31:59 -0800\n\nshadowsocks-libev (3.2.0-1) unstable; urgency=medium\n\n  * Add MinGW support by @linusyang.\n  * Refine c-ares integration by @xnoreq.\n  * Fix building issues with GCC8 by @FlyingheartCN.\n  * Minor bug fixes.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 28 May 2018 19:46:21 -0700\n\nshadowsocks-libev (3.1.3-1) unstable; urgency=medium\n\n  * Fix a bug in UDP relay.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 15 Jan 2018 17:19:31 -0800\n\nshadowsocks-libev (3.1.2-1) unstable; urgency=medium\n\n  * Fix a bug in DNS resolver.\n  * Add new TFO API support.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 28 Dec 2017 21:01:56 -0800\n\nshadowsocks-libev (3.1.1-1) unstable; urgency=high\n\n  * Fix a security issue in ss-manager. (CVE-2017-15924)\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 20 Nov 2017 12:13:04 +0800\n\nshadowsocks-libev (3.1.0-1) unstable; urgency=low\n\n  * Replace libudns with libc-ares.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 14 Sep 2017 19:27:51 -0700\n\nshadowsocks-libev (3.0.8-1) unstable; urgency=medium\n\n  * Refine the ping-pong bloom filter.\n  * Minor bug fixes by @vfreex, @vlolteanu and @jackyyf.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 27 Jul 2017 11:01:37 +0800\n\nshadowsocks-libev (3.0.7-1) unstable; urgency=medium\n\n  * Refine manager mode by @mengxd.\n  * Fix a potential memory leak by @vlolteanu.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 27 Jun 2017 14:08:27 +0800\n\nshadowsocks-libev (3.0.6-1) unstable; urgency=medium\n\n  * Fix a bug with AEAD ciphers.\n  * Refine ACL support by @blackgear.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 26 Apr 2017 13:48:11 +0800\n\nshadowsocks-libev (3.0.5-1) unstable; urgency=medium\n\n  * Fix a bug of TCP Fast Open in ss-redir.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 21 Mar 2017 13:49:18 +0800\n\nshadowsocks-libev (3.0.4-1) unstable; urgency=medium\n\n  * Add CMake files by @wenerme.\n  * Support TCP Fast Open in ss-redir by @lqs.\n  * Support TOS/DESCP in ss-redir by @sduponch.\n  * Refine MPTCP by @sduponch.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 16 Mar 2017 14:07:57 +0800\n\nshadowsocks-libev (3.0.3-1) unstable; urgency=medium\n\n  * Replace nonce cache with a ping-pong bloom filter.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 24 Feb 2017 12:08:31 +0800\n\nshadowsocks-libev (3.0.2-1) unstable; urgency=high\n\n  * Add session key for AEAD. (SIP007)\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 13 Feb 2017 09:07:17 +0800\n\nshadowsocks-libev (3.0.1-1) unstable; urgency=medium\n\n  * Fix a crashe when using stream ciphers.\n  * Fix a protocol bug in AEAD ciphers. (SIP004)\n  * Allow setting keys directly. (SIP006)\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 07 Feb 2017 13:18:02 +0800\n\nshadowsocks-libev (3.0.0-1) unstable; urgency=medium\n\n  * Drop dependencies of OpenSSL and PolarSSL.\n  * Deprecate OTA (One-Time-Auth).\n  * Add new ciphers for SIP004: aes-128-gcm, aes-192-gcm, aes-256-gcm,\n    chacha20-poly1305 and chacha20-ietf-poly1305.\n  * Refine SIP003 to support standalone mode of obfsproxy.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 01 Feb 2017 19:10:14 +0800\n\nshadowsocks-libev (2.6.3-1) unstable; urgency=medium\n\n  * Refine the project structure.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 24 Jan 2017 19:10:45 +0800\n\nshadowsocks-libev (2.6.2-1) unstable; urgency=medium\n\n  * Refine SIP003 plugin support.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 16 Jan 2017 10:16:12 +0800\n\nshadowsocks-libev (2.6.1-1) unstable; urgency=medium\n\n  * Deprecate HTTP/TLS obfuscating.\n  * Add SIP003 plugin support.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 08 Jan 2017 15:14:19 +0800\n\nshadowsocks-libev (2.6.0-1) unstable; urgency=medium\n\n  * Add HTTP/TLS obfuscating.\n  * Add support of aunch_activate_socket on macOS.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 27 Dec 2016 16:37:23 +0800\n\nshadowsocks-libev (2.5.6-1) unstable; urgency=medium\n\n  * Add outbound ACL for server.\n  * Refine log format.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 01 Nov 2016 09:51:52 +0800\n\nshadowsocks-libev (2.5.5-1) unstable; urgency=medium\n\n  * Refine attack detection.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 11 Oct 2016 15:45:09 +0800\n\nshadowsocks-libev (2.5.4-1) unstable; urgency=medium\n\n  * Fix a bug of auto blocking mechanism.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 09 Oct 2016 19:36:37 +0800\n\nshadowsocks-libev (2.5.3-1) unstable; urgency=medium\n\n  * Fix TCP Fast Open on macOS.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 21 Sep 2016 19:31:57 +0800\n\nshadowsocks-libev (2.5.2-1) unstable; urgency=medium\n\n  * Fix a bug of UDP relay mode of ss-local.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 12 Sep 2016 12:54:33 +0800\n\nshadowsocks-libev (2.5.1-1) unstable; urgency=medium\n\n  * Refine ACL feature with hostname support.\n  * Add HTTP/SNI parser for ss-local/ss-redir.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 10 Sep 2016 17:06:49 +0800\n\nshadowsocks-libev (2.5.0-1) unstable; urgency=medium\n\n  * Fix several bugs of the command line interface.\n  * Add aes-128/192/256-ctr ciphers.\n  * Add option MTU for UDP relay.\n  * Add MultiPath TCP support.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 29 Aug 2016 13:07:51 +0800\n\nshadowsocks-libev (2.4.8-1) unstable; urgency=low\n\n  * Update manual pages with asciidoc.\n  * Fix issues of bind_address option.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 20 Jul 2016 09:25:50 +0800\n\nshadowsocks-libev (2.4.7-1) unstable; urgency=low\n\n  * Add ss-nat, a helper script to set up NAT rules for ss-redir.\n  * Fix several issues for debian package.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 1 Jun 2016 18:21:45 +0800\n\nshadowsocks-libev (2.4.6-1) unstable; urgency=low\n\n  * Update manual pages.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 21 Apr 2016 17:33:34 +0800\n\nshadowsocks-libev (2.4.5-1) unstable; urgency=low\n\n  * Fix build issues on OpenWRT.\n  * Reduce the latency of redir mode.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 01 Feb 2016 13:22:50 +0800\n\nshadowsocks-libev (2.4.4-1) unstable; urgency=low\n\n  * Fix a potential memory leak.\n  * Fix some compiler related issues.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 13 Jan 2016 11:50:12 +0800\n\nshadowsocks-libev (2.4.3-1) unstable; urgency=high\n\n  * Refine the buffer allocation.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 19 Dec 2015 12:30:21 +0900\n\nshadowsocks-libev (2.4.1-1) unstable; urgency=high\n\n  * Fix a security bug.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 29 Oct 2015 15:42:47 +0900\n\nshadowsocks-libev (2.4.0-1) unstable; urgency=low\n\n  * Update the one-time authentication\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 24 Sep 2015 14:11:05 +0900\n\nshadowsocks-libev (2.3.3-1) unstable; urgency=low\n\n  * Refine the onetime authentication of header.\n  * Enforce CRC16 on the payload.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 18 Sep 2015 10:38:21 +0900\n\nshadowsocks-libev (2.3.2-1) unstable; urgency=low\n\n  * Fix minor issues of build scripts.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 13 Sep 2015 15:22:28 +0900\n\nshadowsocks-libev (2.3.1-1) unstable; urgency=low\n\n  * Fix an issue of connection cache of UDP relay.\n  * Add support of onetime authentication for header verification.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 04 Sep 2015 07:54:02 +0900\n\nshadowsocks-libev (2.3.0-1) unstable; urgency=low\n\n  * Add manager mode to support multi-user and traffic stat.\n  * Fix a build issue on OS X El Capitan.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 30 Jul 2015 17:30:43 +0900\n\nshadowsocks-libev (2.2.3-1) unstable; urgency=high\n\n  * Fix the multiple UDP source port issue.\n  * Allow working in UDP only mode.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 11 Jul 2015 08:31:02 +0900\n\nshadowsocks-libev (2.2.2-1) unstable; urgency=low\n\n  * Fix the timer of UDP relay.\n  * Check name_len in the header.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 15 Jun 2015 10:26:40 +0900\n\nshadowsocks-libev (2.2.1-1) unstable; urgency=low\n\n  * Fix an issue of UDP relay.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 10 May 2015 21:23:44 +0900\n\nshadowsocks-libev (2.2.0-1) unstable; urgency=low\n\n  * Add TPROXY support in redir mode.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 04 May 2015 02:44:17 -0300\n\nshadowsocks-libev (2.1.4-1) unstable; urgency=low\n\n  * Fix a bug of server mode ACL.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 08 Feb 2015 20:24:43 +0900\n\nshadowsocks-libev (2.1.3-1) unstable; urgency=low\n\n  * Add ACL support to remote server.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 08 Feb 2015 10:59:44 +0900\n\nshadowsocks-libev (2.1.2-1) unstable; urgency=low\n\n  * Refine multiple port binding.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 31 Jan 2015 18:56:25 +0900\n\nshadowsocks-libev (2.1.1-1) unstable; urgency=low\n\n  * Fix a memory leak.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 21 Jan 2015 21:40:58 +0900\n\nshadowsocks-libev (2.1.0-1) unstable; urgency=low\n\n  * Fix a bug of tunnel mode.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 19 Jan 2015 09:59:52 +0900\n\nshadowsocks-libev (2.0.8-1) unstable; urgency=low\n\n  * Fix a bug of IPv6.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 16 Jan 2015 10:58:12 +0900\n\nshadowsocks-libev (2.0.7-1) unstable; urgency=low\n\n  * Fix some performance issue.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 13 Jan 2015 13:17:58 +0900\n\nshadowsocks-libev (2.0.6-1) unstable; urgency=high\n\n  * Fix a critical issue in redir mode.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 12 Jan 2015 21:51:19 +0900\n\nshadowsocks-libev (2.0.5-1) unstable; urgency=low\n\n  * Refine local, tunnel, and redir modes.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 12 Jan 2015 12:39:05 +0800\n\nshadowsocks-libev (2.0.4-1) unstable; urgency=low\n\n  * Fix building issues with MinGW32.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 11 Jan 2015 13:33:31 +0900\n\nshadowsocks-libev (2.0.3-1) unstable; urgency=high\n\n  * Fix some issues.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 10 Jan 2015 16:27:54 +0800\n\nshadowsocks-libev (2.0.2-1) unstable; urgency=low\n\n  * Fix issues with MinGW.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 10 Jan 2015 15:17:10 +0800\n\nshadowsocks-libev (2.0.1-1) unstable; urgency=low\n\n  * Implement a real asynchronous DNS resolver.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 10 Jan 2015 10:04:28 +0800\n\nshadowsocks-libev (1.6.4-1) unstable; urgency=low\n\n  * Update documents.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 07 Jan 2015 21:48:58 +0900\n\nshadowsocks-libev (1.6.3-1) unstable; urgency=low\n\n  * Refine ss-redir.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 04 Jan 2015 19:23:52 +0900\n\nshadowsocks-libev (1.6.2-1) unstable; urgency=low\n\n  * Fix some build issues.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 30 Dec 2014 10:30:28 +0800\n\nshadowsocks-libev (1.6.1-1) unstable; urgency=high\n\n  * Add salsa20 and chacha20 support.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 13 Dec 2014 15:11:34 +0800\n\nshadowsocks-libev (1.6.0-1) unstable; urgency=low\n\n  * Solve conflicts with other shadowsocks portings.\n\n -- Max Lv <max.c.lv@gmail.com>  Mon, 17 Nov 2014 14:10:21 +0800\n\nshadowsocks-libev (1.5.3-2) unstable; urgency=low\n\n  * rename as shadowsocks-libev.\n\n -- Symeon Huang <hzwhuang@gmail.com>  Sat, 15 Nov 2014 14:55:28 +0000\n\nshadowsocks (1.5.3-1) unstable; urgency=low\n\n  * Fix log on Win32.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 14 Nov 2014 09:10:06 +0800\n\nshadowsocks (1.5.2-1) unstable; urgency=low\n\n  * Handle SIGTERM and SIGKILL nicely.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 12 Nov 2014 13:11:29 +0800\n\nshadowsocks (1.5.1-1) unstable; urgency=low\n\n  * Fix a bug of tcp fast open.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 08 Nov 2014 19:45:37 +0900\n\nshadowsocks (1.5.0-1) unstable; urgency=low\n\n  * Support to build static or shared library.\n  * Supprot IPv6 NAT in redirect mode.\n  * Refine the cache size of UDPRelay.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 07 Nov 2014 09:33:19 +0800\n\nshadowsocks (1.4.8-1) unstable; urgency=low\n\n  * Fix a bug of tcp fast open.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 08 Oct 2014 18:02:02 +0800\n\nshadowsocks (1.4.7-1) unstable; urgency=low\n\n  * Add a new encryptor rc4-md5.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 09 Sep 2014 07:50:10 +0800\n\nshadowsocks (1.4.6-1) unstable; urgency=low\n\n  * Add ACL support.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 03 May 2014 04:37:10 -0400\n\nshadowsocks (1.4.5-1) unstable; urgency=high\n\n  * Fix the compatibility issue of udprelay.\n  * Enhance asyncns to reduce the latency.\n  * Add TCP_FASTOPEN support.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 20 Apr 2014 08:12:45 +0800\n\nshadowsocks (1.4.4-1) unstable; urgency=low\n\n  * Add CommonCrypto support for darwin.\n  * Fix some config related issues.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 26 Mar 2014 13:29:03 +0800\n\nshadowsocks (1.4.3-1) unstable; urgency=low\n\n  * Add tunnel mode with local port forwarding feature.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 21 Feb 2014 11:52:13 +0900\n\nshadowsocks (1.4.2-1) unstable; urgency=high\n\n  * Fix the UDP relay issues.\n  * Add syslog support.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 05 Jan 2014 10:05:29 +0900\n\nshadowsocks (1.4.1-1) unstable; urgency=low\n\n  * Add multi-port support.\n  * Add PolarSSL support by @linusyang.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 12 Nov 2013 03:57:21 +0000\n\nshadowsocks (1.4.0-1) unstable; urgency=low\n\n  * Add standard socks5 udp support.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 08 Sep 2013 02:20:40 +0000\n\nshadowsocks (1.3.3-1) unstable; urgency=high\n\n  * Provide more info in verbose mode.\n\n -- Max Lv <max.c.lv@gmail.com>  Fri, 21 Jun 2013 09:59:20 +0800\n\nshadowsocks (1.3.2-1) unstable; urgency=high\n\n  * Fix some ciphers by @linusyang.\n\n -- Max Lv <max.c.lv@gmail.com>  Sun, 09 Jun 2013 09:52:31 +0000\n\nshadowsocks (1.3.1-1) unstable; urgency=low\n\n  * Support more cihpers: camellia, idea, rc2 and seed.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 04 Jun 2013 00:56:17 +0000\n\nshadowsocks (1.3-1) unstable; urgency=low\n\n  * Able to bind connections to specific interface.\n  * Support more ciphers: aes-128-cfb, aes-192-cfb, aes-256-cfb, bf-cfb, cast5-cfb, des-cfb.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 16 May 2013 10:51:15 +0800\n\nshadowsocks (1.2-2) unstable; urgency=low\n\n  * Close timeouted TCP connections.\n\n -- Max Lv <max.c.lv@gmail.com>  Tue, 07 May 2013 14:10:33 +0800\n\nshadowsocks (1.2-1) unstable; urgency=low\n\n  * Fix a high load issue.\n\n -- Max Lv <max.c.lv@gmail.com>  Thu, 18 Apr 2013 10:52:34 +0800\n\nshadowsocks (1.1-1) unstable; urgency=low\n\n  * Fix a IPV6 resolve issue.\n\n -- Max Lv <max.c.lv@gmail.com>  Wed, 10 Apr 2013 12:11:36 +0800\n\nshadowsocks (1.0-2) unstable; urgency=low\n\n  * Initial release.\n\n -- Max Lv <max.c.lv@gmail.com>  Sat, 06 Apr 2013 16:59:15 +0800\n"
  },
  {
    "path": "debian/compat",
    "content": "10\n"
  },
  {
    "path": "debian/config.json",
    "content": "{\n    \"server\":[\"::1\", \"127.0.0.1\"],\n    \"mode\":\"tcp_and_udp\",\n    \"server_port\":8388,\n    \"local_port\":1080,\n    \"password\":\"barfoo!\",\n    \"timeout\":86400,\n    \"method\":\"chacha20-ietf-poly1305\"\n}\n"
  },
  {
    "path": "debian/control",
    "content": "Source: shadowsocks-libev\nSection: net\nPriority: optional\nMaintainer: Debian Bridges Team <team+bridges@tracker.debian.org>\nUploaders:\n Max Lv <max.c.lv@gmail.com>,\n Boyuan Yang <byang@debian.org>,\n Roger Shimizu <rosh@debian.org>\nBuild-Depends:\n asciidoc-base | asciidoc,\n debhelper (>= 10),\n libc-ares-dev,\n libev-dev,\n libmbedtls-dev,\n libpcre2-dev,\n libsodium-dev (>= 1.0.12),\n pkg-config,\n xmlto\nStandards-Version: 4.1.1\nRules-Requires-Root: no\nHomepage: https://www.shadowsocks.org\nVcs-Git: https://github.com/shadowsocks/shadowsocks-libev.git\nVcs-Browser: https://github.com/shadowsocks/shadowsocks-libev\n\nPackage: shadowsocks-libev\nReplaces: shadowsocks (<< 1.5.3-2)\nBreaks: shadowsocks (<< 1.5.3-2)\nArchitecture: any\nPre-Depends: ${misc:Pre-Depends}\nDepends:\n libcap2-bin [linux-any],\n lsb-base (>= 3.0-6),\n ${misc:Depends},\n ${shlibs:Depends}\nSuggests:\n haveged,\n kcptun,\n simple-obfs\nDescription: lightweight and secure socks5 proxy\n Shadowsocks-libev is a lightweight and secure socks5 proxy for\n embedded devices and low end boxes.\n .\n Shadowsocks-libev was inspired by Shadowsocks (in Python). It's rewritten\n in pure C and only depends on libev, mbedTLS and a few other tiny\n libraries.\n\nPackage: libshadowsocks-libev-dev\nArchitecture: any\nMulti-Arch: same\nSection: libdevel\nBreaks: shadowsocks-libev (<< 2.4.0)\nDepends:\n libshadowsocks-libev2 (= ${binary:Version}),\n ${misc:Depends}\nDescription: lightweight and secure socks5 proxy (development files)\n Shadowsocks-libev is a lightweight and secure socks5 proxy for\n embedded devices and low end boxes.\n .\n Shadowsocks-libev was inspired by Shadowsocks (in Python). It's rewritten\n in pure C and only depends on libev, mbedTLS and a few other tiny\n libraries.\n .\n This package provides C header files for the libraries.\n\nPackage: libshadowsocks-libev2\nArchitecture: any\nMulti-Arch: same\nSection: libs\nReplaces: libshadowsocks-libev1\nBreaks:\n libshadowsocks-libev1,\n shadowsocks-libev (<< 2.4.0)\nPre-Depends: ${misc:Pre-Depends}\nDepends:\n ${misc:Depends},\n ${shlibs:Depends}\nDescription: lightweight and secure socks5 proxy (shared library)\n Shadowsocks-libev is a lightweight and secure socks5 proxy for\n embedded devices and low end boxes.\n .\n Shadowsocks-libev was inspired by Shadowsocks (in Python). It's rewritten\n in pure C and only depends on libev, mbedTLS and a few other tiny\n libraries.\n .\n This package provides shared libraries.\n"
  },
  {
    "path": "debian/copyright",
    "content": "Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: shadowsocks-libev\nUpstream-Contact: Max Lv <max.c.lv@gmail.com>\nSource: https://github.com/shadowsocks/shadowsocks-libev\n\nFiles: *\nCopyright: 2013-2015, Clow Windy <clowwindy42@gmail.com>\n           2013-2018, Max Lv <max.c.lv@gmail.com>\n           2014, Linus Yang <linusyang@gmail.com>\nLicense: GPL-3+\n\nFiles: debian/*\nCopyright: 2013-2015, Max Lv <max.c.lv@gmail.com>\n           2015-2018, Boyuan Yang <073plan@gmail.com>\n           2016-2019, Roger Shimizu <rosh@debian.org>\nLicense: GPL-3+\n\nFiles: doc/*\nCopyright: 2012-2018, Max Lv <max.c.lv@gmail.com>\nLicense: GFDL-1.1+\n\nFiles: m4/ax_pthread.m4\nCopyright: 2008 Steven G. Johnson <stevenj@alum.mit.edu>\n           2011 Daniel Richard G. <skunk@iSKUNK.ORG>\nLicense: GPL-3+ with Autoconf exception\n\nFiles: m4/ax_tls.m4\nCopyright: 2008 Alan Woodland <ajw05@aber.ac.uk>\n           2010 Diego Elio Petteno` <flameeyes@gmail.com>\nLicense: GPL-3+ with Autoconf exception\n\nFiles: m4/pcre.m4\nCopyright: 2015 Syrone Wong <wong.syrone@gmail.com>\nLicense: Apache-2.0\n\nFiles: m4/stack-protector.m4\nCopyright: 2007 Google Inc.\nLicense: Apache-2.0\n\nFiles: scripts/build_deb.sh\nCopyright: 2018 Roger Shimizu <rosh@debian.org>\nLicense: GPL-3+\n\nFiles: src/base64.c src/base64.h\nCopyright: 2006 Ryan Martell <rdm4@martellventures.com>\nLicense: LGPL-2.1+\n\nFiles: src/json.c src/json.h\nCopyright: 2012-2014, James McLaughlin et al.\nLicense: BSD-2-clause\n\nFiles: src/resolv.c src/resolv.h\nCopyright: 2011-2014, Dustin Lundquist <dustin@null-ptr.net>\nLicense: BSD-2-clause\n\nFiles: src/rule.c src/rule.h\nCopyright: 2011-2012, Dustin Lundquist <dustin@null-ptr.net>\n           2011, Manuel Kasper <mk@neon1.net>\nLicense: BSD-2-clause\n\nFiles: src/ss-nat\nCopyright: 2015, OpenWrt-dist\n           2015, Jian Chang <aa65535@live.com>\nLicense: GPL-3+\n\nFiles: src/uthash.h\nCopyright: 2003-2016, Troy D. Hanson\nLicense: BSD-1-clause\n\nFiles: tests/test.py\nCopyright: 2015, Clow Windy <clowwindy42@gmail.com>\nLicense: Apache-2.0\n\nLicense: Apache-2.0\n Licensed to the Apache Software Foundation (ASF) under one or more\n contributor license agreements.  See the NOTICE file distributed with\n this work for additional information regarding copyright ownership.\n The ASF licenses this file to You under the Apache License, Version 2.0\n (the \"License\"); you may not use this file except in compliance with\n the License.  You may obtain a copy of the License at\n .\n         http://www.apache.org/licenses/LICENSE-2.0\n .\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n .\n On Debian systems, the complete text of the Apache version 2.0 license\n can be found in \"/usr/share/common-licenses/Apache-2.0\".\n\nLicense: BSD-1-clause\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n .\n * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n .\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER\n OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nLicense: BSD-2-clause\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions\n are met:\n .\n 1. Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n .\n 2. Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n .\n THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n SUCH DAMAGE.\n\nLicense: GFDL-1.1+\n Permission is granted to copy, distribute and/or modify this document\n under the terms of the GNU Free Documentation License, Version 1.1 or\n any later version published by the Free Software Foundation;\n with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.\n .\n A copy of the license is included in the section entitled\n \"GNU Free Documentation License\".\n\nLicense: GPL-3+\n This package is free software; you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation; either version 3 of the License, or\n (at your option) any later version.\n .\n This package is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU General Public License for more details.\n .\n You should have received a copy of the GNU General Public License\n along with this program. If not, see <http://www.gnu.org/licenses/>\n .\n On Debian systems, the complete text of the GNU General\n Public License version 3 can be found in \"/usr/share/common-licenses/GPL-3\".\n\nLicense: GPL-3+ with Autoconf exception\n This program is free software: you can redistribute it and/or modify it\n under the terms of the GNU General Public License as published by the\n Free Software Foundation, either version 3 of the License, or (at your\n option) any later version.\n .\n This program is distributed in the hope that it will be useful, but\n WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n Public License for more details.\n .\n You should have received a copy of the GNU General Public License along\n with this program. If not, see <http://www.gnu.org/licenses/>.\n .\n As a special exception, the respective Autoconf Macro's copyright owner\n gives unlimited permission to copy, distribute and modify the configure\n scripts that are the output of Autoconf when processing the Macro. You\n need not follow the terms of the GNU General Public License when using\n or distributing such scripts, even though portions of the text of the\n Macro appear in them. The GNU General Public License (GPL) does govern\n all other use of the material that constitutes the Autoconf Macro.\n .\n This special exception to the GPL applies to versions of the Autoconf\n Macro released by the Autoconf Archive. When you make and distribute a\n modified version of the Autoconf Macro, you may extend this special\n exception to the GPL to apply to your modified version as well.\n\nLicense: LGPL-2.1+\n This file is part of FFmpeg.\n .\n FFmpeg is free software; you can redistribute it and/or\n modify it under the terms of the GNU Lesser General Public\n License as published by the Free Software Foundation; either\n version 2.1 of the License, or (at your option) any later version.\n .\n FFmpeg is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n Lesser General Public License for more details.\n .\n You should have received a copy of the GNU Lesser General Public\n License along with FFmpeg; if not, write to the Free Software\n Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n"
  },
  {
    "path": "debian/copyright.original",
    "content": "This work was packaged for Debian by:\n\n    Max Lv <max.c.lv@gmail.com> on Sat, 06 Apr 2013 16:59:15 +0800\n\nIt was downloaded from:\n\n    https://github.com/madeye/shadowsocks-libev\n\nUpstream Author(s):\n\n    clowwindy <clowwindy42@gmail.com>\n\nCopyright:\n\n    Copyright (C) 2013 Max Lv\n\nLicense:\n\n    GPLv3\n\nThe Debian packaging is:\n\n    Copyright (C) 2013 Max Lv <max.c.lv@gmail.com>\n"
  },
  {
    "path": "debian/libshadowsocks-libev-dev.install",
    "content": "usr/include/\nusr/lib/*/libshadowsocks-libev.so\nusr/lib/*/pkgconfig/\n"
  },
  {
    "path": "debian/libshadowsocks-libev2.install",
    "content": "usr/lib/*/libshadowsocks-libev.so.*\n"
  },
  {
    "path": "debian/rules",
    "content": "#!/usr/bin/make -f\n# See debhelper(7) (uncomment to enable)\n# output every command that modifies files on the build system.\n#export DH_VERBOSE = 1\n\n# Security Hardening\nexport DEB_BUILD_MAINT_OPTIONS = hardening=+all\n\noverride_dh_auto_install:\n\tfind src/ -name '*.la' -delete\n\tdh_auto_install\n\noverride_dh_auto_configure:\n\tdh_auto_configure -- -DWITH_STATIC=OFF\n\noverride_dh_installchangelogs:\n\tdh_installchangelogs -XChanges\n\n%:\n\tdh $@\n"
  },
  {
    "path": "debian/shadowsocks-libev-local@.service",
    "content": "#  This file is part of shadowsocks-libev.\n#\n#  Shadowsocks-libev is free software; you can redistribute it and/or modify\n#  it under the terms of the GNU General Public License as published by\n#  the Free Software Foundation; either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  This is a template unit file. Users may copy and rename the file into\n#  config directories to make new service instances. See systemd.unit(5)\n#  for details.\n\n[Unit]\nDescription=Shadowsocks-Libev Custom Client Service for %I\nDocumentation=man:ss-local(1)\nAfter=network-online.target\n\n[Service]\nType=simple\nCapabilityBoundingSet=CAP_NET_BIND_SERVICE\nAmbientCapabilities=CAP_NET_BIND_SERVICE\nDynamicUser=true\nExecStart=/usr/bin/ss-local -c /etc/shadowsocks-libev/%i.json\n\n[Install]\nWantedBy=multi-user.target\n"
  },
  {
    "path": "debian/shadowsocks-libev-redir@.service",
    "content": "#  This file is part of shadowsocks-libev.\n#\n#  Shadowsocks-libev is free software; you can redistribute it and/or modify\n#  it under the terms of the GNU General Public License as published by\n#  the Free Software Foundation; either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  This is a template unit file. Users may copy and rename the file into\n#  config directories to make new service instances. See systemd.unit(5)\n#  for details.\n\n[Unit]\nDescription=Shadowsocks-Libev Custom Client Service Redir Mode for %I\nDocumentation=man:ss-redir(1)\nAfter=network-online.target\n\n[Service]\nType=simple\nCapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE\nAmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE\nDynamicUser=true\nExecStart=/usr/bin/ss-redir -c /etc/shadowsocks-libev/%i.json\n\n[Install]\nWantedBy=multi-user.target\n"
  },
  {
    "path": "debian/shadowsocks-libev-server@.service",
    "content": "#  This file is part of shadowsocks-libev.\n#\n#  Shadowsocks-libev is free software; you can redistribute it and/or modify\n#  it under the terms of the GNU General Public License as published by\n#  the Free Software Foundation; either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  This is a template unit file. Users may copy and rename the file into\n#  config directories to make new service instances. See systemd.unit(5)\n#  for details.\n\n[Unit]\nDescription=Shadowsocks-Libev Custom Server Service for %I\nDocumentation=man:ss-server(1)\nAfter=network-online.target\n\n[Service]\nType=simple\nCapabilityBoundingSet=CAP_NET_BIND_SERVICE\nAmbientCapabilities=CAP_NET_BIND_SERVICE\nDynamicUser=true\nExecStart=/usr/bin/ss-server -c /etc/shadowsocks-libev/%i.json\n\n[Install]\nWantedBy=multi-user.target\n"
  },
  {
    "path": "debian/shadowsocks-libev-tunnel@.service",
    "content": "#  This file is part of shadowsocks-libev.\n#\n#  Shadowsocks-libev is free software; you can redistribute it and/or modify\n#  it under the terms of the GNU General Public License as published by\n#  the Free Software Foundation; either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  This is a template unit file. Users may copy and rename the file into\n#  config directories to make new service instances. See systemd.unit(5)\n#  for details.\n\n[Unit]\nDescription=Shadowsocks-Libev Custom Client Service Tunnel Mode for %I\nDocumentation=man:ss-tunnel(1)\nAfter=network-online.target\n\n[Service]\nType=simple\nCapabilityBoundingSet=CAP_NET_BIND_SERVICE\nAmbientCapabilities=CAP_NET_BIND_SERVICE\nDynamicUser=true\nExecStart=/usr/bin/ss-tunnel -c /etc/shadowsocks-libev/%i.json\n\n[Install]\nWantedBy=multi-user.target\n"
  },
  {
    "path": "debian/shadowsocks-libev.NEWS",
    "content": "shadowsocks-libev (3.2.0+ds-5) unstable; urgency=medium\n\n  There is a mode setting to choose whether to enable both TCP and\n  UDP, or only one of them. This setting was set to \"tcp_and_udp\" in\n  /etc/default/shadowsocks-libev, /etc/init.d/shadowsocks-libev\n  (for init system only), and maybe also in config.json added by user,\n  which is quite confusing.\n\n  So we moved this setting to config.json. Since we won't update\n  config.json on package upgrade, please add the following to your\n  /etc/shadowsocks-libev/config.json.\n\n     \"mode\":\"tcp_and_udp\",\n\n  Otherwise you setting will be TCP only.\n  For more about TCP/UDP mode, please refer the ticket upstream:\n\n   - https://github.com/shadowsocks/shadowsocks-libev/issues/1870\n\n -- Roger Shimizu <rosh@debian.org>  Sun, 07 Oct 2018 00:48:07 +0900\n"
  },
  {
    "path": "debian/shadowsocks-libev.default",
    "content": "# Defaults for shadowsocks initscript\n# sourced by /etc/init.d/shadowsocks-libev\n# installed at /etc/default/shadowsocks-libev by the maintainer scripts\n\n#\n# This is a POSIX shell fragment\n#\n# Note: `START', `GROUP' and `MAXFD' options are not recognized by systemd.\n# Please change those settings in the corresponding systemd unit file.\n\n# Enable during startup?\nSTART=yes\n\n# Configuration file\nCONFFILE=\"/etc/shadowsocks-libev/config.json\"\n\n# Extra command line arguments\nDAEMON_ARGS=\n\n# User and group to run the server as\nUSER=nobody\nGROUP=nogroup\n\n# Number of maximum file descriptors\nMAXFD=32768\n"
  },
  {
    "path": "debian/shadowsocks-libev.doc-base",
    "content": "Document: shadowsocks-libev\nTitle: shadowsocks-libev documentation\nAuthor: Max Lv <max.c.lv@gmail.com>\nAbstract: This is the documentation of shadowsocks-libev\nSection: Network/Communication\n\nFormat: HTML\nIndex: /usr/share/doc/shadowsocks-libev/shadowsocks-libev.html\nFiles: /usr/share/doc/shadowsocks-libev/*.html\n"
  },
  {
    "path": "debian/shadowsocks-libev.docs",
    "content": "AUTHORS\nREADME.md\ndebian/copyright.original\nscripts\ndoc/*.html\n"
  },
  {
    "path": "debian/shadowsocks-libev.init",
    "content": "#!/bin/sh\n### BEGIN INIT INFO\n# Provides:          shadowsocks-libev\n# Required-Start:    $network $local_fs $remote_fs\n# Required-Stop:     $remote_fs\n# Default-Start:     2 3 4 5\n# Default-Stop:      0 1 6\n# Short-Description: lightweight secured socks5 proxy\n# Description:       Shadowsocks-libev is a lightweight secured\n#                    socks5 proxy for embedded devices and low end boxes.\n### END INIT INFO\n\n# Author: Max Lv <max.c.lv@gmail.com>\n\n# PATH should only include /usr/ if it runs after the mountnfs.sh script\nPATH=/sbin:/usr/sbin:/bin:/usr/bin\nDESC=shadowsocks-libev       # Introduce a short description here\nNAME=shadowsocks-libev       # Introduce the short server's name here\nDAEMON=/usr/bin/ss-server    # Introduce the server's location here\nDAEMON_ARGS=\"\"               # Arguments to run the daemon with\nPIDFILE=/var/run/$NAME/$NAME.pid\nSCRIPTNAME=/etc/init.d/$NAME\n\n# Exit if the package is not installed\n[ -x $DAEMON ] || exit 0\n\n# Read configuration variable file if it is present\n[ -r /etc/default/$NAME ] && . /etc/default/$NAME\n\n[ \"$START\" = \"yes\" ] || exit 0\n\n: ${USER:=\"nobody\"}\n: ${GROUP:=\"nogroup\"}\n\n# Load the VERBOSE setting and other rcS variables\n. /lib/init/vars.sh\n\n# Define LSB log_* functions.\n# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.\n. /lib/lsb/init-functions\n\n#\n# Function that starts the daemon/service\n#\ndo_start()\n{\n    # Modify the file descriptor limit\n    ulimit -n ${MAXFD}\n\n    # Take care of pidfile permissions\n    mkdir /var/run/$NAME 2>/dev/null || true\n    chown \"$USER:$GROUP\" /var/run/$NAME\n\n    # Return\n    #   0 if daemon has been started\n    #   1 if daemon was already running\n    #   2 if daemon could not be started\n    start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $USER:$GROUP --exec $DAEMON --test > /dev/null \\\n        || return 1\n    start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $USER:$GROUP --exec $DAEMON -- \\\n        -c \"$CONFFILE\" -f $PIDFILE $DAEMON_ARGS \\\n        || return 2\n}\n\n#\n# Function that stops the daemon/service\n#\ndo_stop()\n{\n    # Return\n    #   0 if daemon has been stopped\n    #   1 if daemon was already stopped\n    #   2 if daemon could not be stopped\n    #   other if a failure occurred\n    start-stop-daemon --stop --quiet --retry=TERM/5 --pidfile $PIDFILE --exec $DAEMON\n    RETVAL=\"$?\"\n    [ \"$RETVAL\" = 2 ] && return 2\n    # Wait for children to finish too if this is a daemon that forks\n    # and if the daemon is only ever run from this initscript.\n    # If the above conditions are not satisfied then add some other code\n    # that waits for the process to drop all resources that could be\n    # needed by services started subsequently.  A last resort is to\n    # sleep for some time.\n    start-stop-daemon --stop --quiet --oknodo --retry=KILL/5 --exec $DAEMON\n    [ \"$?\" = 2 ] && return 2\n    # Many daemons don't delete their pidfiles when they exit.\n    rm -f $PIDFILE\n    return \"$RETVAL\"\n}\n\n\ncase \"$1\" in\n    start)\n        [ \"$VERBOSE\" != no ] && log_daemon_msg \"Starting $DESC \" \"$NAME\"\n        do_start\n        case \"$?\" in\n            0|1) [ \"$VERBOSE\" != no ] && log_end_msg 0 ;;\n        2) [ \"$VERBOSE\" != no ] && log_end_msg 1 ;;\n    esac\n    ;;\nstop)\n    [ \"$VERBOSE\" != no ] && log_daemon_msg \"Stopping $DESC\" \"$NAME\"\n    do_stop\n    case \"$?\" in\n        0|1) [ \"$VERBOSE\" != no ] && log_end_msg 0 ;;\n    2) [ \"$VERBOSE\" != no ] && log_end_msg 1 ;;\nesac\n;;\n  status)\n      status_of_proc \"$DAEMON\" \"$NAME\" && exit 0 || exit $?\n      ;;\n  restart|force-reload)\n      log_daemon_msg \"Restarting $DESC\" \"$NAME\"\n      do_stop\n      case \"$?\" in\n          0|1)\n              do_start\n              case \"$?\" in\n                  0) log_end_msg 0 ;;\n              1) log_end_msg 1 ;; # Old process is still running\n          *) log_end_msg 1 ;; # Failed to start\n      esac\n      ;;\n  *)\n      # Failed to stop\n      log_end_msg 1\n      ;;\n    esac\n    ;;\n*)\n    echo \"Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}\" >&2\n    exit 3\n    ;;\nesac\n\n:\n"
  },
  {
    "path": "debian/shadowsocks-libev.install",
    "content": "completions/bash/* usr/share/bash-completion/completions/\ncompletions/zsh/* usr/share/zsh/vendor-completions/\ndebian/config.json usr/share/shadowsocks-libev\ndebian/shadowsocks-libev-*.service lib/systemd/system\nusr/bin/\nusr/share/man/\nusr/share/doc/shadowsocks-libev/\n"
  },
  {
    "path": "debian/shadowsocks-libev.lintian-overrides",
    "content": "# False positive: systemd service templates cannot fallback to sysvinit script\npackage-supports-alternative-init-but-no-init.d-script lib/systemd/system/shadowsocks-libev-local@.service\npackage-supports-alternative-init-but-no-init.d-script lib/systemd/system/shadowsocks-libev-redir@.service\npackage-supports-alternative-init-but-no-init.d-script lib/systemd/system/shadowsocks-libev-server@.service\npackage-supports-alternative-init-but-no-init.d-script lib/systemd/system/shadowsocks-libev-tunnel@.service\n"
  },
  {
    "path": "debian/shadowsocks-libev.postinst",
    "content": "#!/bin/sh\n\nset -e\n\n# POSIX-compliant maint function recommend by devref\n# to check for the existence of a command\n# https://www.debian.org/doc/manuals/developers-reference/ch06.html#bpp-debian-maint-scripts\npathfind() {\n\tOLDIFS=\"$IFS\"\n\tIFS=:\n\tfor p in $PATH; do\n\t\tif [ -x \"$p/$*\" ]; then\n\t\tIFS=\"$OLDIFS\"\n\t\treturn 0\n\t\tfi\n\tdone\n\tIFS=\"$OLDIFS\"\n\treturn 1\n}\n\ncase \"$1\" in\n\tconfigure|reconfigure)\n\t\tif pathfind setcap; then\n\t\t\tif ! setcap \\\n\t\t\t\tcap_net_bind_service+ep /usr/bin/ss-local \\\n\t\t\t\tcap_net_bind_service,cap_net_admin+ep /usr/bin/ss-redir \\\n\t\t\t\tcap_net_bind_service+ep /usr/bin/ss-server \\\n\t\t\t\tcap_net_bind_service+ep /usr/bin/ss-tunnel; then\n\t\t\t\techo \"Failed to set capabilities; ss-* will only be runnable by root.\"\n\t\t\tfi\n\t\telse\n\t\t\techo \"setcap not installed; ss-* will only be runnable by root.\"\n\t\tfi\n\t\tif [ ! -f /etc/shadowsocks-libev/config.json ]; then\n\t\t\tset +e\n\t\t\tpasswd=$(perl -e 'print map{(\"a\"..\"z\",\"A\"..\"Z\",0..9)[int(rand(62))]}(1..12)')\n\t\t\tset -e\n\t\t\tmkdir -p /etc/shadowsocks-libev\n\t\t\tsed \"s/barfoo!/$passwd/\" /usr/share/shadowsocks-libev/config.json \\\n\t\t\t\t> /etc/shadowsocks-libev/config.json\n\t\tfi\n\t\t;;\n\tabort-upgrade|abort-remove|abort-deconfigure)\n\t\texit 0\n\t\t;;\n\t*)\n\t\techo \"postinst called with unknown argument \\`$1'\" >&2\n\t\texit 0\n\t\t;;\nesac\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "debian/shadowsocks-libev.postrm",
    "content": "#!/bin/sh\n\nset -e\n\ncase \"$1\" in\n\tpurge)\n\t\trm -f /etc/shadowsocks-libev/config.json\n\t\tif test ! -e /etc/shadowsocks-libev ; then\n\t\t\t# If the config directory does not exist, do nothing\n\t\t\t:\n\t\telse\n\t\t\tif test -d /etc/shadowsocks-libev ; then\n\t\t\t\t# If it is an empty directory, remove it\n\t\t\t\trmdir /etc/shadowsocks-libev || true\n\t\t\tfi\n\t\tfi\n\t\t;;\n\tremove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)\n\t\texit 0\n\t\t;;\n\t*)\n\t\techo \"postrm called with unknown argument \\`$1'\" >&2\n\t\texit 0\n\t\t;;\nesac\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "debian/shadowsocks-libev.service",
    "content": "#  This file is part of shadowsocks-libev.\n#\n#  Shadowsocks-libev is free software; you can redistribute it and/or modify\n#  it under the terms of the GNU General Public License as published by\n#  the Free Software Foundation; either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  This file is default for Debian packaging. See also\n#  /etc/default/shadowsocks-libev for environment variables.\n\n[Unit]\nDescription=Shadowsocks-libev Default Server Service\nDocumentation=man:shadowsocks-libev(8)\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nCapabilityBoundingSet=CAP_NET_BIND_SERVICE\nAmbientCapabilities=CAP_NET_BIND_SERVICE\nDynamicUser=true\nEnvironmentFile=/etc/default/shadowsocks-libev\nLimitNOFILE=32768\nExecStart=/usr/bin/ss-server -c $CONFFILE $DAEMON_ARGS\n\n[Install]\nWantedBy=multi-user.target\n"
  },
  {
    "path": "debian/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "debian/tests/control",
    "content": "Test-Command: bash tests/test.sh\nDepends: @, python3, curl, dnsutils\nRestrictions: allow-stderr\n"
  },
  {
    "path": "debian/upstream/metadata",
    "content": "Name: shadowsocks-libev\nHomepage: https://shadowsocks.org\nRepository: https://github.com/shadowsocks/shadowsocks-libev.git\nRepository-Browse: https://github.com/shadowsocks/shadowsocks-libev\nBug-Database: https://github.com/shadowsocks/shadowsocks-libev/issues\nContact: Max Lv <max.c.lv@gmail.com>\n"
  },
  {
    "path": "debian/watch",
    "content": "version=4\n\nopts=\"repack,compression=xz, \\\n   dversionmangle=s/\\+ds\\d*$//,repacksuffix=+ds, \\\n   filenamemangle=s%(?:.*?)?v?(\\d[\\d.]*)\\.tar\\.gz%shadowsocks-libev_$1.orig.tar.gz%\" \\\n   https://github.com/shadowsocks/shadowsocks-libev/tags \\\n   (?:.*?/)?v?(\\d[\\d.]*)\\.tar\\.gz debian uupdate\n"
  },
  {
    "path": "doc/CMakeLists.txt",
    "content": "find_program(XMLTO_EXECUTABLE NAMES xmlto)\nfind_program(ASCIIDOC_EXECUTABLE NAMES asciidoc asciidoc.py)\n\n# Opt-in doc build option\nif (NOT XMLTO_EXECUTABLE OR NOT ASCIIDOC_EXECUTABLE)\n    option(WITH_DOC_MAN \"Build manpage doc\" OFF)\nelse ()\n    option(WITH_DOC_MAN \"Build manpage doc\" ON)\nendif ()\n\nif (NOT ASCIIDOC_EXECUTABLE)\n    option(WITH_DOC_HTML \"Build html doc\" OFF)\nelse ()\n    option(WITH_DOC_HTML \"Build html doc\" ON)\nendif ()\n\n# NOTE For brew user, we have to setup this env var. see `brew info asciidoc'\nset(XMLTO_ENV)\nset(XMLTO_CATALOG_DIR_MACOS /usr/local/etc/xml/catalog)\nif (EXISTS ${XMLTO_CATALOG_DIR_MACOS})\n    set(XMLTO_ENV XML_CATALOG_FILES=${XMLTO_CATALOG_DIR_MACOS})\n    message(STATUS \"Detect xmlto catalog dir ${XMLTO_CATALOG_DIR_MACOS}\")\nendif ()\n\nset(CMAKE_MANPAGE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/man)\nset(CMAKE_HTML_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/html)\n\nset(DOC_DIR ${PROJECT_SOURCE_DIR}/doc)\nset(XMLTO_OPTS -m ${DOC_DIR}/manpage-normal.xsl -m ${DOC_DIR}/manpage-bold-literal.xsl man)\nset(ASCIIDOC_XML_OPTS -b docbook -d manpage -f ${DOC_DIR}/asciidoc.conf -aversion=${PROJECT_VERSION})\nset(ASCIIDOC_HTML_OPTS -b html4 -d article -f ${DOC_DIR}/asciidoc.conf -aversion=${PROJECT_VERSION})\n\n\nset(MAN_NAMES ss-local.1 ss-manager.1 ss-nat.1 ss-redir.1 ss-server.1 ss-tunnel.1 shadowsocks-libev.8)\nset(MAN_FILES)\nset(HTML_FILES)\n\nforeach (manfile IN LISTS MAN_NAMES)\n    string(REGEX REPLACE \\\\.. .xml xmlfile ${manfile})\n    string(REGEX REPLACE \\\\.. .asciidoc docfile ${manfile})\n    string(REGEX REPLACE \\\\.. .html htmlfile ${manfile})\n\n    set(manfile ${CMAKE_MANPAGE_OUTPUT_DIRECTORY}/${manfile})\n    set(htmlfile ${CMAKE_HTML_OUTPUT_DIRECTORY}/${htmlfile})\n    set(docfile ${DOC_DIR}/${docfile})\n\n    add_custom_command(OUTPUT ${manfile}\n            COMMAND ${ASCIIDOC_EXECUTABLE} ${ASCIIDOC_XML_OPTS} -o ${xmlfile} ${docfile}\n            COMMAND ${CMAKE_COMMAND} -E env ${XMLTO_ENV} ${XMLTO_EXECUTABLE} ${XMLTO_OPTS} ${xmlfile}\n            # After we built the manpage, the xmlfile is nolongger needed\n            COMMAND ${CMAKE_COMMAND} -E remove ${xmlfile}\n            DEPENDS ${docfile}\n            WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/man\n            COMMENT \"Building manpage ${manfile}\"\n            VERBATIM)\n    list(APPEND MAN_FILES ${manfile})\n\n    add_custom_command(OUTPUT ${htmlfile}\n            COMMAND ${ASCIIDOC_EXECUTABLE} ${ASCIIDOC_HTML_OPTS} -o ${htmlfile} ${docfile}\n            DEPENDS ${docfile}\n            WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/html\n            COMMENT \"Building htmlfile ${htmlfile}\"\n            VERBATIM)\n    list(APPEND HTML_FILES ${htmlfile})\nendforeach ()\n\nadd_custom_target(doc-man ALL DEPENDS ${MAN_FILES})\nadd_custom_target(doc-html ALL DEPENDS ${HTML_FILES})\n\n\nif (NOT WITH_DOC_MAN)\n    set_target_properties(doc-man PROPERTIES EXCLUDE_FROM_ALL TRUE)\nelse ()\n    install(DIRECTORY ${PROJECT_BINARY_DIR}/man/\n            DESTINATION share/man/man1\n            FILES_MATCHING PATTERN \"*.1\"\n            )\n    install(DIRECTORY ${PROJECT_BINARY_DIR}/man/\n            DESTINATION share/man/man8\n            FILES_MATCHING PATTERN \"*.8\"\n            )\nendif ()\nif (NOT WITH_DOC_HTML)\n    set_target_properties(doc-html PROPERTIES EXCLUDE_FROM_ALL TRUE)\nelse ()\n    install(DIRECTORY ${PROJECT_BINARY_DIR}/html/\n            DESTINATION share/doc/${PROJECT_NAME})\nendif ()\n\n# This is required for custom command\nfile(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/man)\nfile(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/html)\n"
  },
  {
    "path": "doc/asciidoc.conf",
    "content": "[tags]\nbracket-emphasis={1?[{1}]}<emphasis>&lt;|&gt;</emphasis>\n\n[quotes]\n&lt;|&gt;=#bracket-emphasis\n\n[attributes]\nasterisk=&#42;\nplus=&#43;\ncaret=&#94;\nstartsb=&#91;\nendsb=&#93;\nbackslash=&#92;\ntilde=&#126;\napostrophe=&#39;\nbacktick=&#96;\nlitdd=&#45;&#45;\n\nifdef::doctype-manpage[]\nifdef::backend-docbook[]\n[header]\ntemplate::[header-declarations]\n<refentry>\n<refmeta>\n<refentrytitle>{mantitle}</refentrytitle>\n<manvolnum>{manvolnum}</manvolnum>\n<refmiscinfo class=\"source\">Shadowsocks-libev</refmiscinfo>\n<refmiscinfo class=\"version\">{version}</refmiscinfo>\n<refmiscinfo class=\"manual\">Shadowsocks-libev Manual</refmiscinfo>\n</refmeta>\n<refnamediv>\n  <refname>{manname}</refname>\n  <refpurpose>{manpurpose}</refpurpose>\n</refnamediv>\nendif::backend-docbook[]\nendif::doctype-manpage[]\n"
  },
  {
    "path": "doc/manpage-base.xsl",
    "content": "<!-- manpage-base.xsl:\n     special formatting for manpages rendered from asciidoc+docbook -->\n<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n\t\tversion=\"1.0\">\n\n<!-- these params silence some output from xmlto -->\n<xsl:param name=\"man.output.quietly\" select=\"1\"/>\n<xsl:param name=\"refentry.meta.get.quietly\" select=\"1\"/>\n\n<!-- convert asciidoc callouts to man page format;\n     git.docbook.backslash and git.docbook.dot params\n     must be supplied by another XSL file or other means -->\n<xsl:template match=\"co\">\n\t<xsl:value-of select=\"concat(\n\t\t\t      $git.docbook.backslash,'fB(',\n\t\t\t      substring-after(@id,'-'),')',\n\t\t\t      $git.docbook.backslash,'fR')\"/>\n</xsl:template>\n<xsl:template match=\"calloutlist\">\n\t<xsl:value-of select=\"$git.docbook.dot\"/>\n\t<xsl:text>sp&#10;</xsl:text>\n\t<xsl:apply-templates/>\n\t<xsl:text>&#10;</xsl:text>\n</xsl:template>\n<xsl:template match=\"callout\">\n\t<xsl:value-of select=\"concat(\n\t\t\t      $git.docbook.backslash,'fB',\n\t\t\t      substring-after(@arearefs,'-'),\n\t\t\t      '. ',$git.docbook.backslash,'fR')\"/>\n\t<xsl:apply-templates/>\n\t<xsl:value-of select=\"$git.docbook.dot\"/>\n\t<xsl:text>br&#10;</xsl:text>\n</xsl:template>\n\n</xsl:stylesheet>\n"
  },
  {
    "path": "doc/manpage-bold-literal.xsl",
    "content": "<!-- manpage-bold-literal.xsl:\n     special formatting for manpages rendered from asciidoc+docbook -->\n<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n\t\tversion=\"1.0\">\n\n<!-- render literal text as bold (instead of plain or monospace);\n     this makes literal text easier to distinguish in manpages\n     viewed on a tty -->\n<xsl:template match=\"literal\">\n\t<xsl:value-of select=\"$git.docbook.backslash\"/>\n\t<xsl:text>fB</xsl:text>\n\t<xsl:apply-templates/>\n\t<xsl:value-of select=\"$git.docbook.backslash\"/>\n\t<xsl:text>fR</xsl:text>\n</xsl:template>\n\n</xsl:stylesheet>\n"
  },
  {
    "path": "doc/manpage-normal.xsl",
    "content": "<!-- manpage-normal.xsl:\n     special settings for manpages rendered from asciidoc+docbook\n     handles anything we want to keep away from docbook-xsl 1.72.0 -->\n<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n\t\tversion=\"1.0\">\n\n<xsl:import href=\"manpage-base.xsl\"/>\n\n<!-- these are the normal values for the roff control characters -->\n<xsl:param name=\"git.docbook.backslash\">\\</xsl:param>\n<xsl:param name=\"git.docbook.dot\"\t>.</xsl:param>\n\n</xsl:stylesheet>\n"
  },
  {
    "path": "doc/shadowsocks-libev.asciidoc",
    "content": "shadowsocks-libev(8)\n====================\n\nNAME\n----\nshadowsocks-libev - a lightweight and secure socks5 proxy\n\nSYNOPSIS\n--------\n*ss-local*|*ss-redir*|*ss-server*|*ss-tunnel*|*ss-manager*\n [-s <server_host>] [-p <server_port>] [-l <local_port>] [-k <password>]\n [-m <encrypt_method>] [-f <pid_file>] [-t <timeout>] [-c <config_file>]\n\nDESCRIPTION\n-----------\n*Shadowsocks-libev* is a lightweight and secure socks5 proxy.\nIt is a port of the original shadowsocks created by clowwindy.\n*Shadowsocks-libev* is written in pure C and takes advantage of *libev*\nto achieve both high performance and low resource consumption.\n\n*Shadowsocks-libev* consists of five components. One is `ss-server`(1)\nthat runs on a remote server to provide secured tunnel service.\n`ss-local`(1) and `ss-redir`(1) are clients on your local machines to proxy\ntraffic(TCP/UDP or both).\n`ss-tunnel`(1) is a tool for local port forwarding.\n\nWhile `ss-local`(1) works as a standard socks5 proxy, `ss-redir`(1) works\nas a transparent proxy and requires netfilter's NAT module. For more\ninformation, check out the 'EXAMPLE' section.\n\n`ss-manager`(1) is a controller for multi-user management and traffic\nstatistics, using UNIX domain socket to talk with `ss-server`(1).\nAlso, it provides a UNIX domain socket or IP based API for other software.\nAbout the details of this API, please refer to the 'PROTOCOL' section.\n\nOPTIONS\n-------\n\n-s <server_host>::\nSet the server's hostname or IP.\n\n-l <local_port>::\nSet the local port number.\n+\nNot available in server nor manager mode.\n\n-k <password>::\n--password <password>::\nSet the password. The server and the client should use the same password.\n\n--key <key_in_base64>::\nSet the key directly. The key should be encoded with URL-safe Base64.\n+\nNot available in manager mode.\n\n-m <encrypt_method>::\nSet the cipher.\n+\n*Shadowsocks-libev* accepts 19 different ciphers:\n+\naes-128-gcm, aes-192-gcm, aes-256-gcm,\nrc4-md5, aes-128-cfb, aes-192-cfb, aes-256-cfb,\naes-128-ctr, aes-192-ctr, aes-256-ctr, bf-cfb,\ncamellia-128-cfb, camellia-192-cfb, camellia-256-cfb,\nchacha20-ietf-poly1305, xchacha20-ietf-poly1305,\nsalsa20, chacha20 and chacha20-ietf.\n+\nThe default cipher is 'chacha20-ietf-poly1305'.\n+\nIf built with PolarSSL or custom OpenSSL libraries, some of\nthese ciphers may not work.\n\n-a <user_name>::\nRun as a specific user.\n\n-f <pid_file>::\nStart shadowsocks as a daemon with specific pid file.\n\n-t <timeout>::\nSet the socket timeout in seconds. The default value is 60.\n\n-c <config_file>::\nUse a configuration file.\n\n-n <number>::\nSpecify max number of open files.\n+\nNot available in manager mode.\n+\nOnly available on Linux.\n\n-i <interface>::\nSend traffic through specific network interface.\n+\nFor example, there are three interfaces in your device, which is\nlo (127.0.0.1), eth0 (192.168.0.1) and eth1 (192.168.0.2).\nMeanwhile, you configure *shadowsocks-libev* to listen on 0.0.0.0:8388\nand bind to eth1. That results the traffic go out through eth1,\nbut not lo nor eth0. This option is useful to control traffic in\nmulti-interface environment.\n+\nNot available in redir mode.\n\n-b <local_address>::\nSpecify the local address to bind.\n+\nFor servers: Specify the local address to use while this server is making\noutbound connections to remote servers on behalf of the clients.\n+\nFor clients: Specify the local address to use while this client is making\noutbound connections to the server.\n+\nNot available in manager mode.\n\n-u::\nEnable UDP relay.\n+\nTPROXY is required in redir mode. You may need root permission.\n\n-U::\nEnable UDP relay and disable TCP relay.\n+\nNot available in local mode.\n\n-T::\nUse tproxy instead of redirect (for tcp).\n+\nOnly available in redir mode.\n\n-L <addr:port>::\nSpecify destination server address and port for local port forwarding.\n+\nOnly available in tunnel mode.\n\n-d <addr>::\nSetup name servers for internal DNS resolver (libc-ares).\nThe default server is fetched from /etc/resolv.conf.\n+\nOnly available in server and manager mode.\n\n--fast-open::\nEnable TCP fast open.\n+\nNot available in redir nor tunnel mode, with Linux kernel > 3.7.0.\n\n--reuse-port::\nEnable port reuse.\n+\nOnly available with Linux kernel > 3.9.0.\n\n--no-delay::\nEnable TCP_NODELAY.\n\n--tcp-incoming-sndbuf <size>::\nSet TCP send buffer size for incoming connections.\n+\nNot available in manager mode.\n\n--tcp-incoming-rcvbuf <size>::\nSet TCP receive buffer size for incoming connections.\n+\nNot available in manager mode.\n\n--tcp-outgoing-sndbuf <size>::\nSet TCP send buffer size for outgoing connections.\n+\nNot available in manager mode.\n\n--tcp-outgoing-rcvbuf <size>::\nSet TCP receive buffer size for outgoing connections.\n+\nNot available in manager mode.\n\n--acl <acl_config>::\nEnable ACL (Access Control List) and specify config file.\n+\nNot available in redir nor tunnel mode.\n\n--manager-address <path_to_unix_domain>::\nSpecify UNIX domain socket address.\n+\nOnly available in server and manager mode.\n\n--executable <path_to_server_executable>::\nSpecify the executable path of `ss-server`.\n+\nOnly available in manager mode.\n\n-D <path>::\n--workdir <path>::\nSpecify the working directory of ss-manager.\n+\nOnly available in manager mode.\n\n--nftables-sets <family:table:set>::\nSpecify nftables sets for reporting malicious IPs.\n+\nOnly available in server mode, when built with nftables support.\n\n-v::\nEnable verbose mode.\n\n-h|--help::\nPrint help message.\n\nCONFIG FILE\n-----------\nThe config file is written in JSON and easy to edit.\n\nThe config file equivalent of command line options is listed as example below.\n[frame=\"topbot\",options=\"header\"]\n|==========================================================================\n| Command line                        | JSON\n| -s some.server.net                  | \"server\": \"some.server.net\"\n| -s some.server.net -p 1234 (client) | \"server\": \"some.server.net:1234\"\n| -p 1234                             | \"server_port\": \"1234\"\n| -b 0.0.0.0                          | \"local_address\": \"0.0.0.0\"\n| -b 10.0.0.2                         | \"local_ipv4_address\": \"10.0.0.2\"\n| -b 2620:129:35::33                  | \"local_ipv6_address\": \"2620:129:35::33\"\n| -l 4321                             | \"local_port\": \"4321\"\n| -k \"PasSworD\"                       | \"password\": \"PasSworD\"\n| -m \"aes-256-cfb\"                    | \"method\": \"aes-256-cfb\"\n| -t 60                               | \"timeout\": 60\n| -a nobody                           | \"user\": \"nobody\"\n| --acl \"/path/to/acl\"                | \"acl\": \"/path/to/acl\"\n| --fast-open                         | \"fast_open\": true\n| --reuse-port                        | \"reuse_port\": true\n| --no-delay                          | \"no_delay\": true\n| --plugin \"obfs-server\"              | \"plugin\": \"obfs-server\"\n| --plugin-opts \"obfs=http\"           | \"plugin_opts\": \"obfs=http\"\n| -6                                  | \"ipv6_first\": true\n| -n \"/etc/nofile\"                    | \"nofile\": \"/etc/nofile\"\n| -d \"8.8.8.8\"                        | \"nameserver\": \"8.8.8.8\"\n| -L \"somedns.net:53\"                 | \"tunnel_address\": \"somedns.net:53\"\n| -u                                  | \"mode\": \"tcp_and_udp\"\n| -U                                  | \"mode\": \"udp_only\"\n| no \"-u\" nor \"-U\" options (default)  | \"mode\": \"tcp_only\"\n| -T                                  | \"tcp_tproxy\": true\n| (only in ss-manager's config)       | \"port_password\": {\"1234\":\"PasSworD\"}\n|============================================================================\n\nEXAMPLE\n-------\n`ss-redir` requires netfilter's NAT function. Here is an example:\n\n....\n# Create new chain\niptables -t nat -N SHADOWSOCKS\niptables -t mangle -N SHADOWSOCKS\n\n# Ignore your shadowsocks server's addresses\n# It's very IMPORTANT, just be careful.\niptables -t nat -A SHADOWSOCKS -d 123.123.123.123 -j RETURN\n\n# Ignore LANs and any other addresses you'd like to bypass the proxy\n# See Wikipedia and RFC5735 for full list of reserved networks.\n# See ashi009/bestroutetb for a highly optimized CHN route list.\niptables -t nat -A SHADOWSOCKS -d 0.0.0.0/8 -j RETURN\niptables -t nat -A SHADOWSOCKS -d 10.0.0.0/8 -j RETURN\niptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN\niptables -t nat -A SHADOWSOCKS -d 169.254.0.0/16 -j RETURN\niptables -t nat -A SHADOWSOCKS -d 172.16.0.0/12 -j RETURN\niptables -t nat -A SHADOWSOCKS -d 192.168.0.0/16 -j RETURN\niptables -t nat -A SHADOWSOCKS -d 224.0.0.0/4 -j RETURN\niptables -t nat -A SHADOWSOCKS -d 240.0.0.0/4 -j RETURN\n\n# Anything else should be redirected to shadowsocks's local port\niptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports 12345\n\n# Add any UDP rules\nip rule add fwmark 0x01/0x01 table 100\nip route add local 0.0.0.0/0 dev lo table 100\niptables -t mangle -A SHADOWSOCKS -p udp --dport 53 -j TPROXY --on-port 12345 --tproxy-mark 0x01/0x01\n\n# Apply the rules\niptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS\niptables -t mangle -A PREROUTING -j SHADOWSOCKS\n\n# Start the shadowsocks-redir\nss-redir -u -c /etc/config/shadowsocks.json -f /var/run/shadowsocks.pid\n....\n\nPROTOCOL\n--------\n`ss-manager`(1) provides several APIs through UDP protocol::\n\nSend UDP commands in the following format to the manager-address provided to ss-manager(1): ::::\n command: [JSON data]\n\nTo add a port: ::::\n add: {\"server_port\": 8001, \"password\":\"7cd308cc059\"}\n\nTo remove a port: ::::\n remove: {\"server_port\": 8001}\n\nTo receive a pong: ::::\n ping\n\nThen `ss-manager`(1) will send back the traffic statistics: ::::\n stat: {\"8001\":11370}\n\nSEE ALSO\n--------\n`ss-local`(1),\n`ss-server`(1),\n`ss-tunnel`(1),\n`ss-redir`(1),\n`ss-manager`(1),\n`iptables`(8),\n/etc/shadowsocks-libev/config.json\n"
  },
  {
    "path": "doc/ss-local.asciidoc",
    "content": "ss-local(1)\n===========\n\nNAME\n----\nss-local - shadowsocks client as socks5 proxy, libev port\n\nSYNOPSIS\n--------\n*ss-local*\n [-uv6] [-h|--help]\n [-s <server_host>] [-p <server_port>] [-l <local_port>]\n [-k <password>] [-m <encrypt_method>] [-f <pid_file>]\n [-t <timeout>] [-c <config_file>] [-i <interface>]\n [-a <user_name>] [-b <local_address>] [-n <nofile>]\n [--fast-open] [--reuse-port] [--acl <acl_config>]\n [--mtu <MTU>] [--no-delay]\n [--plugin <plugin_name>] [--plugin-opts <plugin_options>]\n [--password <password>] [--key <key_in_base64>]\n\nDESCRIPTION\n-----------\n*Shadowsocks-libev* is a lightweight and secure socks5 proxy.\nIt is a port of the original shadowsocks created by clowwindy.\n*Shadowsocks-libev* is written in pure C and takes advantage of libev to\nachieve both high performance and low resource consumption.\n\n*Shadowsocks-libev* consists of five components. `ss-local`(1) works as a standard\nsocks5 proxy on local machines to proxy TCP traffic.\nFor more information, check out `shadowsocks-libev`(8).\n\nOPTIONS\n-------\n\n-s <server_host>::\nSet the server's hostname or IP.\n\n-p <server_port>::\nSet the server's port number.\n\n-l <local_port>::\nSet the local port number.\n\n-k <password>::\n--password <password>::\nSet the password. The server and the client should use the same password.\n\n--key <key_in_base64>::\nSet the key directly. The key should be encoded with URL-safe Base64.\n\n-m <encrypt_method>::\nSet the cipher.\n+\n*Shadowsocks-libev* accepts 19 different ciphers:\n+\naes-128-gcm, aes-192-gcm, aes-256-gcm,\nrc4-md5, aes-128-cfb, aes-192-cfb, aes-256-cfb,\naes-128-ctr, aes-192-ctr, aes-256-ctr, bf-cfb,\ncamellia-128-cfb, camellia-192-cfb, camellia-256-cfb,\nchacha20-ietf-poly1305, xchacha20-ietf-poly1305,\nsalsa20, chacha20 and chacha20-ietf.\n+\nThe default cipher is 'chacha20-ietf-poly1305'.\n+\nIf built with PolarSSL or custom OpenSSL libraries, some of\nthese ciphers may not work.\n\n-a <user_name>::\nRun as a specific user.\n\n-f <pid_file>::\nStart shadowsocks as a daemon with specific pid file.\n\n-t <timeout>::\nSet the socket timeout in seconds. The default value is 60.\n\n-c <config_file>::\nUse a configuration file.\n+\nRefer to `shadowsocks-libev`(8) 'CONFIG FILE' section for more details.\n\n-n <number>::\nSpecify max number of open files.\n+\nOnly available on Linux.\n\n-i <interface>::\nSend traffic through specific network interface.\n+\nFor example, there are three interfaces in your device,\nwhich is lo (127.0.0.1), eth0 (192.168.0.1) and eth1 (192.168.0.2).\nMeanwhile, you configure `ss-local` to listen on 0.0.0.0:8388 and bind to eth1.\nThat results the traffic go out through eth1, but not lo nor eth0.\nThis option is useful to control traffic in multi-interface environment.\n\n-b <local_address>::\nSpecify the local address to use while this client is making outbound \nconnections to the server.\n\n-u::\nEnable UDP relay.\n\n-U::\nEnable UDP relay and disable TCP relay.\n\n-6::\nResolve hostname to IPv6 address first.\n\n--fast-open::\nEnable TCP fast open.\n+\nOnly available with Linux kernel > 3.7.0.\n\n--reuse-port::\nEnable port reuse.\n+\nOnly available with Linux kernel > 3.9.0.\n\n--acl <acl_config>::\nEnable ACL (Access Control List) and specify config file.\n\n--mtu <MTU>::\nSpecify the MTU of your network interface.\n\n--mptcp::\nEnable Multipath TCP.\n+\nOnly available with MPTCP enabled Linux kernel.\n\n--no-delay::\nEnable TCP_NODELAY.\n\n--tcp-incoming-sndbuf <size>::\nSet TCP send buffer size for incoming connections.\n\n--tcp-incoming-rcvbuf <size>::\nSet TCP receive buffer size for incoming connections.\n\n--tcp-outgoing-sndbuf <size>::\nSet TCP send buffer size for outgoing connections.\n\n--tcp-outgoing-rcvbuf <size>::\nSet TCP receive buffer size for outgoing connections.\n\n--plugin <plugin_name>::\nEnable SIP003 plugin. (Experimental)\n\n--plugin-opts <plugin_options>::\nSet SIP003 plugin options. (Experimental)\n\n-v::\nEnable verbose mode.\n\n-h|--help::\nPrint help message.\n\nEXAMPLE\n-------\n`ss-local`(1) can be started from command line and run in foreground.\nHere is an example:\n....\n# Start ss-local with given parameters\nss-local -s example.com -p 12345 -l 1080 -k foobar -m aes-256-cfb\n....\n\nSEE ALSO\n--------\n`ss-server`(1),\n`ss-tunnel`(1),\n`ss-redir`(1),\n`ss-manager`(1),\n`shadowsocks-libev`(8),\n`iptables`(8),\n/etc/shadowsocks-libev/config.json\n\n"
  },
  {
    "path": "doc/ss-manager.asciidoc",
    "content": "ss-manager(1)\n=============\n\nNAME\n----\nss-manager - ss-server controller for multi-user management and traffic statistics\n\nSYNOPSIS\n--------\n*ss-manager*\n [-AuUv] [-h|--help]\n [-s <server_host>] [-p <server_port>] [-l <local_port>]\n [-k <password>] [-m <encrypt_method>] [-f <pid_file>]\n [-t <timeout>] [-c <config_file>] [-i <interface>]\n [-b <local_addr>] [-a <user_name>] [-D <path>]\n [--manager-address <path_to_unix_domain>]\n [--executable <path_to_server_executable>]\n [--fast-open] [--reuse-port]\n [--plugin <plugin_name>] [--plugin-opts <plugin_options>]\n\nDESCRIPTION\n-----------\n*Shadowsocks-libev* is a lightweight and secure socks5 proxy.\nIt is a port of the original shadowsocks created by clowwindy.\n*Shadowsocks-libev* is written in pure C and takes advantage of libev to\nachieve both high performance and low resource consumption.\n\n*Shadowsocks-libev* consists of five components.\n`ss-manager`(1) is a controller for multi-user management and\ntraffic statistics, using UNIX domain socket to talk with `ss-server`(1).\nAlso, it provides a UNIX domain socket or IP based API for other software.\nAbout the details of this API, please refer to the following 'PROTOCOL'\nsection.\n\nOPTIONS\n-------\n-s <server_host>::\nSet the server's hostname or IP.\n\n-k <password>::\nSet the password. The server and the client should use the same password.\n\n-m <encrypt_method>::\nSet the cipher.\n+\n*Shadowsocks-libev* accepts 19 different ciphers:\n+\naes-128-gcm, aes-192-gcm, aes-256-gcm,\nrc4-md5, aes-128-cfb, aes-192-cfb, aes-256-cfb,\naes-128-ctr, aes-192-ctr, aes-256-ctr, bf-cfb,\ncamellia-128-cfb, camellia-192-cfb, camellia-256-cfb,\nchacha20-ietf-poly1305, xchacha20-ietf-poly1305,\nsalsa20, chacha20 and chacha20-ietf.\n+\nThe default cipher is 'chacha20-ietf-poly1305'.\n+\nIf built with PolarSSL or custom OpenSSL libraries, some of\nthese ciphers may not work.\n\n-a <user_name>::\nRun as a specific user.\n\n-f <pid_file>::\nStart shadowsocks as a daemon with specific pid file.\n\n-t <timeout>::\nSet the socket timeout in seconds. The default value is 60.\n\n-c <config_file>::\nUse a configuration file.\n+\nYou may use \"port_password\" field inside this configuration file to bring up\nmultiple ss-server instances together.\n\n-i <interface>::\nSend traffic through specific network interface.\n+\nFor example, there are three interfaces in your device,\nwhich is lo (127.0.0.1), eth0 (192.168.0.1) and eth1 (192.168.0.2).\nMeanwhile, you configure `ss-local` to listen on 0.0.0.0:8388 and bind to eth1.\nThat results the traffic go out through eth1, but not lo nor eth0.\nThis option is useful to control traffic in multi-interface environment.\n\n-u::\n Enable UDP relay.\n\n-U::\nEnable UDP relay and disable TCP relay.\n\n-A::\nEnable onetime authentication.\n\n-d <addr>::\nSetup name servers for internal DNS resolver (libc-ares).\nThe default server is fetched from `/etc/resolv.conf`.\n\n--fast-open::\nEnable TCP fast open.\n+\nOnly available with Linux kernel > 3.7.0.\n\n--reuse-port::\nEnable port reuse.\n+\nOnly available with Linux kernel > 3.9.0.\n\n--acl <acl_config>::\nEnable ACL (Access Control List) and specify config file.\n\n--manager-address <path_to_unix_domain>::\nSpecify UNIX domain socket address for the communication between ss-manager(1) and ss-server(1).\n+\nOnly available in server and manager mode.\n\n--executable <path_to_server_executable>::\nSpecify the executable path of ss-server.\n+\nOnly available in manager mode.\n\n-D <path>::\n--workdir <path>::\nSpecify the working directory of ss-manager.\n+\nOnly available in manager mode.\n\n--plugin <plugin_name>::\nEnable SIP003 plugin. (Experimental)\n\n--plugin-opts <plugin_options>::\nSet SIP003 plugin options. (Experimental)\n\n-v::\nEnable verbose mode.\n\n-h|--help::\nPrint help message.\n\nPROTOCOL\n--------\n`ss-manager`(1) provides several APIs through UDP protocol:\n\nSend UDP commands in the following format to the manager-address provided to ss-manager(1): ::::\n command: [JSON data]\n\nTo add a port: ::::\n add: {\"server_port\": 8001, \"password\":\"7cd308cc059\"}\n\nTo remove a port: ::::\n remove: {\"server_port\": 8001}\n\nTo receive the traffic statistics: ::::\n ping\n\nThe format of the traffic statistics: ::::\n stat: {\"8001\":11370}\n\nThere is no way to reset the traffic statistics, unless you remove the port and add it again\n\nEXAMPLE\n-------\nTo use `ss-manager`(1), First start it and specify necessary information.\n\nThen communicate with `ss-manager`(1) through UNIX Domain Socket using UDP\nprotocol:\n\n....\n# Start the manager. Arguments for ss-server will be passed to generated\n# ss-server process(es) respectively.\nss-manager --manager-address /tmp/manager.sock --executable $(which ss-server) -s example.com -m aes-256-cfb -c /path/to/config.json\n\n# Connect to the socket. Using netcat-openbsd as an example.\n# You should use scripts or other programs for further management.\nnc -Uu /tmp/manager.sock\n....\n\nAfter that, you may communicate with `ss-manager`(1) as described above in the\n'PROTOCOL' section.\n\nSEE ALSO\n--------\n`ss-local`(1),\n`ss-server`(1),\n`ss-tunnel`(1),\n`ss-redir`(1),\n`shadowsocks-libev`(8),\n`iptables`(8),\n/etc/shadowsocks-libev/config.json\n"
  },
  {
    "path": "doc/ss-nat.asciidoc",
    "content": "ss-nat(1)\n=========\n\nNAME\n----\nss-nat - helper script to setup NAT rules for transparent proxy\n\nSYNOPSIS\n--------\n*ss-nat*\n [-ouUfh]\n [-s <server_ip>] [-S <server_ip>] [-l <local_port>]\n [-L <local_port>] [-i <ip_list_file>] [-a <lan_ips>]\n [-b <wan_ips>] [-w <wan_ips>] [-e <extra_options>]\n\nDESCRIPTION\n-----------\n*Shadowsocks-libev* is a lightweight and secure socks5 proxy.\nIt is a port of the original shadowsocks created by clowwindy.\n*Shadowsocks-libev* is written in pure C and takes advantage of libev to\nachieve both high performance and low resource consumption.\n\n`ss-nat`(1) sets up NAT rules for `ss-redir`(1) to provide traffic redirection.\nIt requires netfilter's NAT module and `iptables`(8).\nFor more information, check out `shadowsocks-libev`(8) and the following\n'EXAMPLE' section.\n\nOPTIONS\n-------\n-s <server_ip>::\nIP address of shadowsocks remote server\n\n-l <local_port>::\nPort number of shadowsocks local server\n\n-S <server_ip>::\nIP address of shadowsocks remote UDP server\n\n-L <local_port>::\nPort number of shadowsocks local UDP server\n\n-i <ip_list_file>::\na file whose content is bypassed ip list\n\n-a <lan_ips>::\nLAN IP of access control, need a prefix to define access control mode\n\n-b <wan_ips>::\nWAN IP of will be bypassed\n\n-w <wan_ips>::\nWAN IP of will be forwarded\n\n-e <extra_options>::\nExtra options for iptables\n\n-o::\nApply the rules to the OUTPUT chain\n\n-u::\nEnable udprelay mode, TPROXY is required\n\n-U::\nEnable udprelay mode, using different IP and ports for TCP and UDP\n\n-f::\nFlush the rules\n\n-h::\nShow this help message and exit\n\nEXAMPLE\n-------\n`ss-nat` requires `iptables`(8). Here is an example:\n\n....\n# Enable NAT rules for shadowsocks,\n# with both TCP and UDP redirection enabled,\n# and applied for both PREROUTING and OUTPUT chains\nroot@Wrt:~# ss-nat -s 192.168.1.100 -l 1080 -u -o\n\n# Disable and flush all NAT rules for shadowsocks\nroot@Wrt:~# ss-nat -f\n....\n\nSEE ALSO\n--------\n`ss-local`(1),\n`ss-server`(1),\n`ss-tunnel`(1),\n`ss-manager`(1),\n`shadowsocks-libev`(8),\n`iptables`(8),\n/etc/shadowsocks-libev/config.json\n\n"
  },
  {
    "path": "doc/ss-redir.asciidoc",
    "content": "ss-redir(1)\n===========\n\nNAME\n----\nss-redir - shadowsocks client as transparent proxy, libev port\n\nSYNOPSIS\n--------\n*ss-redir*\n [-uUv6] [-h|--help]\n [-s <server_host>] [-p <server_port>] [-l <local_port>]\n [-k <password>] [-m <encrypt_method>] [-f <pid_file>]\n [-t <timeout>] [-c <config_file>] [-b <local_address>]\n [-a <user_name>] [-n <nofile>] [--mtu <MTU>] [--no-delay]\n [--plugin <plugin_name>] [--plugin-opts <plugin_options>]\n [--password <password>] [--key <key_in_base64>]\n\nDESCRIPTION\n-----------\n*Shadowsocks-libev* is a lightweight and secure socks5 proxy.\nIt is a port of the original shadowsocks created by clowwindy.\n*Shadowsocks-libev* is written in pure C and takes advantage of libev to\nachieve both high performance and low resource consumption.\n\n*Shadowsocks-libev* consists of five components.\n`ss-redir`(1) works as a transparent proxy on local machines to proxy TCP\ntraffic and requires netfilter's NAT module.\nFor more information, check out `shadowsocks-libev`(8) and the following\n'EXAMPLE' section.\n\nOPTIONS\n-------\n-s <server_host>::\nSet the server's hostname or IP.\n\n-p <server_port>::\nSet the server's port number.\n\n-l <local_port>::\nSet the local port number.\n\n-k <password>::\n--password <password>::\nSet the password. The server and the client should use the same password.\n\n--key <key_in_base64>::\nSet the key directly. The key should be encoded with URL-safe Base64.\n\n-m <encrypt_method>::\nSet the cipher.\n+\n*Shadowsocks-libev* accepts 19 different ciphers:\n+\naes-128-gcm, aes-192-gcm, aes-256-gcm,\nrc4-md5, aes-128-cfb, aes-192-cfb, aes-256-cfb,\naes-128-ctr, aes-192-ctr, aes-256-ctr, bf-cfb,\ncamellia-128-cfb, camellia-192-cfb, camellia-256-cfb,\nchacha20-ietf-poly1305, xchacha20-ietf-poly1305,\nsalsa20, chacha20 and chacha20-ietf.\n+\nThe default cipher is 'chacha20-ietf-poly1305'.\n+\nIf built with PolarSSL or custom OpenSSL libraries, some of\nthese ciphers may not work.\n\n-a <user_name>::\nRun as a specific user.\n\n-f <pid_file>::\nStart shadowsocks as a daemon with specific pid file.\n\n-t <timeout>::\nSet the socket timeout in seconds. The default value is 60.\n\n-c <config_file>::\nUse a configuration file.\n+\nRefer to `shadowsocks-libev`(8) 'CONFIG FILE' section for more details.\n\n-n <number>::\nSpecify max number of open files.\n+\nOnly available on Linux.\n\n-b <local_address>::\nSpecify the local address to use while this client is making outbound \nconnections to the server.\n\n-u::\nEnable UDP relay.\n+\nTPROXY is required in redir mode. You may need root permission.\n\n-U::\nEnable UDP relay and disable TCP relay.\n\n-T::\nUse tproxy instead of redirect. (for tcp)\n\n-6::\nResolve hostname to IPv6 address first.\n\n--mtu <MTU>::\nSpecify the MTU of your network interface.\n\n--mptcp::\nEnable Multipath TCP.\n+\nOnly available with MPTCP enabled Linux kernel.\n\n--reuse-port::\nEnable port reuse.\n+\nOnly available with Linux kernel > 3.9.0.\n\n--no-delay::\nEnable TCP_NODELAY.\n\n--tcp-incoming-sndbuf <size>::\nSet TCP send buffer size for incoming connections.\n\n--tcp-incoming-rcvbuf <size>::\nSet TCP receive buffer size for incoming connections.\n\n--tcp-outgoing-sndbuf <size>::\nSet TCP send buffer size for outgoing connections.\n\n--tcp-outgoing-rcvbuf <size>::\nSet TCP receive buffer size for outgoing connections.\n\n--plugin <plugin_name>::\nEnable SIP003 plugin. (Experimental)\n\n--plugin-opts <plugin_options>::\nSet SIP003 plugin options. (Experimental)\n\n-v::\nEnable verbose mode.\n\n-h|--help::\nPrint help message.\n\nEXAMPLE\n-------\nss-redir requires netfilter's NAT function. Here is an example:\n\n....\n# Create new chain\niptables -t nat -N SHADOWSOCKS\niptables -t mangle -N SHADOWSOCKS\n\n# Ignore your shadowsocks server's addresses\n# It's very IMPORTANT, just be careful.\niptables -t nat -A SHADOWSOCKS -d 123.123.123.123 -j RETURN\n\n# Ignore LANs and any other addresses you'd like to bypass the proxy\n# See Wikipedia and RFC5735 for full list of reserved networks.\n# See ashi009/bestroutetb for a highly optimized CHN route list.\niptables -t nat -A SHADOWSOCKS -d 0.0.0.0/8 -j RETURN\niptables -t nat -A SHADOWSOCKS -d 10.0.0.0/8 -j RETURN\niptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN\niptables -t nat -A SHADOWSOCKS -d 169.254.0.0/16 -j RETURN\niptables -t nat -A SHADOWSOCKS -d 172.16.0.0/12 -j RETURN\niptables -t nat -A SHADOWSOCKS -d 192.168.0.0/16 -j RETURN\niptables -t nat -A SHADOWSOCKS -d 224.0.0.0/4 -j RETURN\niptables -t nat -A SHADOWSOCKS -d 240.0.0.0/4 -j RETURN\n\n# Anything else should be redirected to shadowsocks's local port\niptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports 12345\n\n# Add any UDP rules\nip route add local default dev lo table 100\nip rule add fwmark 1 lookup 100\niptables -t mangle -A SHADOWSOCKS -p udp --dport 53 -j TPROXY --on-port 12345 --tproxy-mark 0x01/0x01\n\n# Apply the rules\niptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS\niptables -t mangle -A PREROUTING -j SHADOWSOCKS\n\n# Start the shadowsocks-redir\nss-redir -u -c /etc/config/shadowsocks.json -f /var/run/shadowsocks.pid\n....\n\nSEE ALSO\n--------\n`ss-local`(1),\n`ss-server`(1),\n`ss-tunnel`(1),\n`ss-manager`(1),\n`shadowsocks-libev`(8),\n`iptables`(8),\n/etc/shadowsocks-libev/config.json\n"
  },
  {
    "path": "doc/ss-server.asciidoc",
    "content": "ss-server(1)\n============\n\nNAME\n----\nss-server - shadowsocks server, libev port\n\nSYNOPSIS\n--------\n*ss-server*\n [-uUv] [-h|--help]\n [-s <server_host>] [-p <server_port>] [-l <local_port>]\n [-k <password>] [-m <encrypt_method>] [-f <pid_file>]\n [-t <timeout>] [-c <config_file>] [-i <interface>]\n [-a <user_name>] [-d <addr>] [-n <nofile>]\n [-b <local_address>] [--fast-open] [--reuse-port]\n [--mptcp] [--acl <acl_config>] [--mtu <MTU>] [--no-delay]\n [--manager-address <path_to_unix_domain>]\n [--plugin <plugin_name>] [--plugin-opts <plugin_options>]\n [--password <password>] [--key <key_in_base64>]\n\nDESCRIPTION\n-----------\n*Shadowsocks-libev* is a lightweight and secure socks5 proxy.\nIt is a port of the original shadowsocks created by clowwindy.\n*Shadowsocks-libev* is written in pure C and takes advantage of libev to\nachieve both high performance and low resource consumption.\n\n*Shadowsocks-libev* consists of five components.\n`ss-server`(1) runs on a remote server to provide secured tunnel service.\nFor more information, check out `shadowsocks-libev`(8).\n\nOPTIONS\n-------\n-s <server_host>::\nSet the server's hostname or IP.\n\n-p <server_port>::\nSet the server's port number.\n\n-k <password>::\n--password <password>::\nSet the password. The server and the client should use the same password.\n\n--key <key_in_base64>::\nSet the key directly. The key should be encoded with URL-safe Base64.\n\n-m <encrypt_method>::\nSet the cipher.\n+\n*Shadowsocks-libev* accepts 19 different ciphers:\n+\naes-128-gcm, aes-192-gcm, aes-256-gcm,\nrc4-md5, aes-128-cfb, aes-192-cfb, aes-256-cfb,\naes-128-ctr, aes-192-ctr, aes-256-ctr, bf-cfb,\ncamellia-128-cfb, camellia-192-cfb, camellia-256-cfb,\nchacha20-ietf-poly1305, xchacha20-ietf-poly1305,\nsalsa20, chacha20 and chacha20-ietf.\n+\nIf built with PolarSSL or custom OpenSSL libraries, some of\nthese ciphers may not work.\n\n-a <user_name>::\nRun as a specific user.\n\n-f <pid_file>::\nStart shadowsocks as a daemon with specific pid file.\n\n-t <timeout>::\nSet the socket timeout in seconds. The default value is 60.\n\n-c <config_file>::\nUse a configuration file.\n+\nRefer to `shadowsocks-libev`(8) 'CONFIG FILE' section for more details.\n\n-n <number>::\nSpecify max number of open files.\n+\nOnly available on Linux.\n\n-i <interface>::\nSend traffic through specific network interface.\n+\nFor example, there are three interfaces in your device,\nwhich is lo (127.0.0.1), eth0 (192.168.0.1) and eth1 (192.168.0.2).\nMeanwhile, you configure `ss-server` to listen on 0.0.0.0:8388 and bind to eth1.\nThat results the traffic go out through eth1, but not lo nor eth0.\nThis option is useful to control traffic in multi-interface environment.\n\n-b <local_address>::\nSpecify the local address to use while this server is making outbound \nconnections to remote servers on behalf of the clients.\n\n-u::\nEnable UDP relay.\n\n-U::\nEnable UDP relay and disable TCP relay.\n\n-6::\nResolve hostname to IPv6 address first.\n\n-d <addr>::\nSetup name servers for internal DNS resolver (libc-ares).\nThe default server is fetched from '/etc/resolv.conf'.\n\n--fast-open::\nEnable TCP fast open.\n+\nOnly available with Linux kernel > 3.7.0.\n\n--reuse-port::\nEnable port reuse.\n+\nOnly available with Linux kernel > 3.9.0.\n\n--no-delay::\nEnable TCP_NODELAY.\n\n--tcp-incoming-sndbuf <size>::\nSet TCP send buffer size for incoming connections.\n\n--tcp-incoming-rcvbuf <size>::\nSet TCP receive buffer size for incoming connections.\n\n--tcp-outgoing-sndbuf <size>::\nSet TCP send buffer size for outgoing connections.\n\n--tcp-outgoing-rcvbuf <size>::\nSet TCP receive buffer size for outgoing connections.\n\n--acl <acl_config>::\nEnable ACL (Access Control List) and specify config file.\n\n--manager-address <path_to_unix_domain>::\nSpecify UNIX domain socket address for the communication between ss-manager(1) and ss-server(1).\n+\nOnly available in server and manager mode.\n\n--mtu <MTU>::\nSpecify the MTU of your network interface.\n\n--mptcp::\nEnable Multipath TCP.\n+\nOnly available with MPTCP enabled Linux kernel.\n\n--plugin <plugin_name>::\nEnable SIP003 plugin. (Experimental)\n\n--plugin-opts <plugin_options>::\nSet SIP003 plugin options. (Experimental)\n\n-v::\nEnable verbose mode.\n\n-h|--help::\nPrint help message.\n\nEXAMPLE\n-------\nIt is recommended to use a config file when starting `ss-server`(1).\n\nThe config file is written in JSON and is easy to edit.\nCheck out the 'SEE ALSO' section for the default path of config file.\n\n....\n# Start the ss-server\nss-server -c /etc/shadowsocks-libev/config.json\n....\n\nINCOMPATIBILITY\n---------------\nThe config file of `shadowsocks-libev`(8) is slightly different from original\nshadowsocks.\n\nIn order to listen to both IPv4/IPv6 address, use the following grammar in\nyour config json file:\n....\n{\n\"server\":[\"::0\",\"0.0.0.0\"],\n...\n}\n....\n\n`ss-server`(1) also does not understand \"port_password\" field in config file.\nIf you want to start up multiple server instances with a single config file,\nplease try ss-manager tool. See `ss-manager`(8) for details.\n\nSEE ALSO\n--------\n`ss-local`(1),\n`ss-tunnel`(1),\n`ss-redir`(1),\n`ss-manager`(1),\n`shadowsocks-libev`(8),\n`iptables`(8),\n/etc/shadowsocks-libev/config.json\n"
  },
  {
    "path": "doc/ss-tunnel.asciidoc",
    "content": "ss-tunnel(1)\n============\n\nNAME\n----\nss-tunnel - shadowsocks tools for local port forwarding, libev port\n\nSYNOPSIS\n--------\n*ss-tunnel*\n [-uUv6] [-h|--help]\n [-s <server_host>] [-p <server_port>] [-l <local_port>]\n [-k <password>] [-m <encrypt_method>] [-f <pid_file>]\n [-t <timeout>] [-c <config_file>] [-i <interface>]\n [-b <local_address>] [-a <user_name>] [-n <nofile>]\n [-L addr:port] [--mtu <MTU>] [--mptcp] [--reuse-port] [--no-delay]\n [--plugin <plugin_name>] [--plugin-opts <plugin_options>]\n [--key <key_in_base64>]\n\nDESCRIPTION\n-----------\n*Shadowsocks-libev* is a lightweight and secure socks5 proxy.\nIt is a port of the original shadowsocks created by clowwindy.\n*Shadowsocks-libev* is written in pure C and takes advantage of libev to\nachieve both high performance and low resource consumption.\n\n*Shadowsocks-libev* consists of five components.\n`ss-tunnel`(1) is a tool for local port forwarding.\nSee 'OPTIONS' section for special option needed by `ss-tunnel`(1).\nFor more information, check out `shadowsocks-libev`(8).\n\nOPTIONS\n-------\n-s <server_host>::\nSet the server's hostname or IP.\n\n-p <server_port>::\nSet the server's port number.\n\n-l <local_port>::\nSet the local port number.\n\n-k <password>::\n--password <password>::\nSet the password. The server and the client should use the same password.\n\n--key <key_in_base64>::\nSet the key directly. The key should be encoded with URL-safe Base64.\n\n-m <encrypt_method>::\nSet the cipher.\n+\n*Shadowsocks-libev* accepts 19 different ciphers:\n+\naes-128-gcm, aes-192-gcm, aes-256-gcm,\nrc4-md5, aes-128-cfb, aes-192-cfb, aes-256-cfb,\naes-128-ctr, aes-192-ctr, aes-256-ctr, bf-cfb,\ncamellia-128-cfb, camellia-192-cfb, camellia-256-cfb,\nchacha20-ietf-poly1305, xchacha20-ietf-poly1305,\nsalsa20, chacha20 and chacha20-ietf.\n+\nThe default cipher is 'chacha20-ietf-poly1305'.\n+\nIf built with PolarSSL or custom OpenSSL libraries, some of\nthese ciphers may not work.\n\n-a <user_name>::\nRun as a specific user.\n\n-f <pid_file>::\nStart shadowsocks as a daemon with specific pid file.\n\n-t <timeout>::\nSet the socket timeout in seconds. The default value is 60.\n\n-c <config_file>::\nUse a configuration file.\n+\nRefer to `shadowsocks-libev`(8) 'CONFIG FILE' section for more details.\n\n-n <number>::\nSpecify max number of open files.\n+\nOnly available on Linux.\n\n-i <interface>::\nSend traffic through specific network interface.\n+\nFor example, there are three interfaces in your device,\nwhich is lo (127.0.0.1), eth0 (192.168.0.1) and eth1 (192.168.0.2).\nMeanwhile, you configure `ss-tunnel` to listen on 0.0.0.0:8388 and bind to eth1.\nThat results the traffic go out through eth1, but not lo nor eth0.\nThis option is useful to control traffic in multi-interface environment.\n\n-b <local_address>::\nSpecify the local address to use while this client is making outbound \nconnections to the server.\n\n-u::\nEnable UDP relay.\n\n-U::\nEnable UDP relay and disable TCP relay.\n\n-6::\nResolve hostname to IPv6 address first.\n\n-L <addr:port>::\nSpecify destination server address and port for local port forwarding.\n+\nOnly used and available in tunnel mode.\n\n--mtu <MTU>::\nSpecify the MTU of your network interface.\n\n--mptcp::\nEnable Multipath TCP.\n+\nOnly available with MPTCP enabled Linux kernel.\n\n--reuse-port::\nEnable port reuse.\n+\nOnly available with Linux kernel > 3.9.0.\n\n--no-delay::\nEnable TCP_NODELAY.\n\n--tcp-incoming-sndbuf <size>::\nSet TCP send buffer size for incoming connections.\n\n--tcp-incoming-rcvbuf <size>::\nSet TCP receive buffer size for incoming connections.\n\n--tcp-outgoing-sndbuf <size>::\nSet TCP send buffer size for outgoing connections.\n\n--tcp-outgoing-rcvbuf <size>::\nSet TCP receive buffer size for outgoing connections.\n\n--plugin <plugin_name>::\nEnable SIP003 plugin. (Experimental)\n\n--plugin-opts <plugin_options>::\nSet SIP003 plugin options. (Experimental)\n\n-v::\nEnable verbose mode.\n\n-h|--help::\nPrint help message.\n\nEXAMPLE\n-------\n`ss-tunnel`(1) can be used to forward DNS queries to a remote DNS server\nthrough the shadowsocks tunnel. Here is an example:\n\n....\n# Forward local UDP port 5353 to 8.8.8.8:53 through the ss-server\nss-tunnel -s example.com -p 12345 -l 5353 -k foobar -m aes-256-cfb -L 8.8.8.8:53 -u\n\n# Then configure your system to use 127.0.0.1:5353 as the DNS server\ndig @127.0.0.1 -p 5353 www.google.com\n....\n\nSEE ALSO\n--------\n`ss-local`(1),\n`ss-server`(1),\n`ss-redir`(1),\n`ss-manager`(1),\n`shadowsocks-libev`(8),\n`iptables`(8),\n/etc/shadowsocks-libev/config.json\n"
  },
  {
    "path": "docker/alpine/Dockerfile",
    "content": "FROM alpine:3.16\nLABEL maintainer=\"kev <noreply@datageek.info>, Sah <contact@leesah.name>, vndroid <waveworkshop@outlook.com>\"\n\nENV SERVER_ADDR=0.0.0.0\nENV SERVER_PORT=8388\nENV PASSWORD=\nENV METHOD=aes-256-gcm\nENV TIMEOUT=300\nENV DNS_ADDRS=\"8.8.8.8,8.8.4.4\"\nENV TZ=UTC\nENV ARGS=\n\nCOPY . /tmp/repo\nRUN set -x \\\n # Build environment setup\n && apk add --no-cache --virtual .build-deps \\\n      build-base \\\n      cmake \\\n      c-ares-dev \\\n      libcap \\\n      libev-dev \\\n      libsodium-dev \\\n      linux-headers \\\n      mbedtls-dev \\\n      pcre2-dev \\\n # Build & install\n && cd /tmp/repo \\\n && mkdir -p build && cd build \\\n && cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local -DBUILD_TESTING=OFF -DWITH_STATIC=OFF -DCMAKE_BUILD_TYPE=Release \\\n && make -j$(getconf _NPROCESSORS_ONLN) \\\n && make install \\\n && cd /usr/local/bin \\\n && ls /usr/local/bin/ss-* | xargs -n1 setcap cap_net_bind_service+ep \\\n && strip $(ls /usr/local/bin | grep -Ev 'ss-nat') \\\n && apk del .build-deps \\\n # Runtime dependencies setup\n && apk add --no-cache \\\n      ca-certificates \\\n      rng-tools \\\n      tzdata \\\n      $(scanelf --needed --nobanner /usr/local/bin/ss-* \\\n      | awk '{ gsub(/,/, \"\\nso:\", $2); print \"so:\" $2 }' \\\n      | sort -u) \\\n && rm -rf /tmp/repo\n\nCOPY ./docker/alpine/entrypoint.sh /usr/local/bin/docker-entrypoint.sh\nENTRYPOINT [\"docker-entrypoint.sh\"]\n\nEXPOSE 8388\n\nSTOPSIGNAL SIGINT\n\nCMD [\"ss-server\"]\n"
  },
  {
    "path": "docker/alpine/README.md",
    "content": "# Shadowsocks-libev Docker Image\n\n[shadowsocks-libev][1] is a lightweight secured socks5 proxy for embedded\ndevices and low end boxes.  It is a port of [shadowsocks][2] created by\n@clowwindy maintained by @madeye and @linusyang.\n\nDocker images are built for quick deployment in various computing cloud providers. For more information on docker and containerization technologies, refer to [official document][9].\n\n## Prepare the host\n\nMany cloud providers offer docker-ready environments, for instance the [CoreOS Droplet in DigitalOcean][10] or the [Container-Optimized OS in Google Cloud][11].\n\nIf you need to install docker yourself, follow the [official installation guide][12].\n\n## Pull the image\n\n```bash\n$ docker pull shadowsocks/shadowsocks-libev\n```\nThis pulls the latest release of shadowsocks-libev.\n\nYou can also choose to pull a previous release or to try the bleeding edge build:\n```bash\n$ docker pull shadowsocks/shadowsocks-libev:<tag>\n$ docker pull shadowsocks/shadowsocks-libev:edge\n```\n> A list of supported tags can be found at [Docker Hub][13].\n\n## Start a container\n\n```bash\n$ docker run -p 8388:8388 -p 8388:8388/udp -d --restart always shadowsocks/shadowsocks-libev:latest\n```\nThis starts a container of the latest release with all the default settings, which is equivalent to\n```bash\n$ ss-server -s 0.0.0.0 -p 8388 -k \"$(hostname)\" -m aes-256-gcm -t 300 -d \"8.8.8.8,8.8.4.4\" -u\n```\n> **Note**: It's the hostname in the container that is used as the password, not that of the host.\n\n### With custom port\n\nIn most cases you'll want to change a thing or two, for instance the port which the server listens on. This is done by changing the `-p` arguments.\n\nHere's an example to start a container that listens on `28388` (both TCP and UDP):\n```bash\n$ docker run -p 28388:8388 -p 28388:8388/udp -d --restart always shadowsocks/shadowsocks-libev\n```\n\n### With custom password\n\nAnother thing you may want to change is the password. To change that, you can pass your own password as an environment variable when starting the container.\n\nHere's an example to start a container with `9MLSpPmNt` as the password:\n```bash\n$ docker run -e PASSWORD=9MLSpPmNt -p 8388:8388 -p 8388:8388/udp -d --restart always shadowsocks/shadowsocks-libev\n```\n> :warning: Click [here][6] to generate a strong password to protect your server.\n\n### With password as a mounted file or a Docker secret (swarm only)\n\nInstead of hardcoding a password to the docker-compose file or `docker run` command, you can mount in a file that contains the password. To do so, pass the path that you mounted to the container as the `PASSWORD_FILE` environment variable.\n\nIf you are running Docker Swarm, you can also utilize Docker secrets. To do so, pass the name of the secret as the `PASSWORD_SECRET` environment variable. If you specify both `PASSWORD_FILE` and `PASSWORD_SECRET`, the latter will take effect.\n\nThis is a sample `docker-compose.yml` file that uses the external Docker secret named `shadowsocks` as the password.\n\n```yaml\nshadowsocks:\n  image: shadowsocks/shadowsocks-libev\n  ports:\n    - \"8388:8388\"\n  environment:\n    - METHOD=aes-256-gcm\n    - PASSWORD_SECRET=shadowsocks\n  secrets:\n    - shadowsocks\n```\n\nThis is a sample `docker service create` command that uses the external Docker secret named `shadowsocks` as the password.\n\n```bash\ndocker service create -e PASSWORD_SECRET=shadowsocks -p 8388:8388 -p 8388:8388/udp --secret shadowsocks shadowsocks/shadowsocks-libev\n```\n\n### With other customizations\nBesides `PASSWORD`, the image also defines the following environment variables that you can customize:\n* `SERVER_ADDR`: the IP/domain to bind to, defaults to `0.0.0.0`\n* `SERVER_ADDR_IPV6`: the IPv6 address to bind to, defaults to `::0`\n* `METHOD`: encryption method to use, defaults to `aes-256-gcm`\n* `TIMEOUT`: defaults to `300`\n* `DNS_ADDRS`: DNS servers to redirect NS lookup requests to, defaults to `8.8.8.8,8.8.4.4`\n* `TZ`: Timezone, defaults to `UTC`\n\nAdditional arguments supported by `ss-server` can be passed with the environment variable `ARGS`, for instance to start in verbose mode:\n```bash\n$ docker run -e ARGS=-v -p 8388:8388 -p 8388:8388/udp -d --restart always shadowsocks/shadowsocks-libev:latest\n```\n\n## Use docker-compose to manage (optional)\n\nIt is very handy to use [docker-compose][7] to manage docker containers.\nYou can download the binary at <https://github.com/docker/compose/releases>.\n\nThis is a sample `docker-compose.yml` file.\n\n```yaml\nshadowsocks:\n  image: shadowsocks/shadowsocks-libev\n  ports:\n    - \"8388:8388\"\n  environment:\n    - METHOD=aes-256-gcm\n    - PASSWORD=9MLSpPmNt\n  restart: always\n```\n\nIt is highly recommended that you setup a directory tree to make things easy to manage.\n\n```bash\n$ mkdir -p ~/fig/shadowsocks/\n$ cd ~/fig/shadowsocks/\n$ curl -sSLO https://github.com/shadowsocks/shadowsocks-libev/raw/master/docker/alpine/docker-compose.yml\n$ docker-compose up -d\n$ docker-compose ps\n```\n\n## Finish\n\nAt last, download shadowsocks client [here][8].\nDon't forget to share internet with your friends.\n\n```yaml\n{\n    \"server\": \"your-vps-ip\",\n    \"server_port\": 8388,\n    \"local_address\": \"0.0.0.0\",\n    \"local_port\": 1080,\n    \"password\": \"9MLSpPmNt\",\n    \"timeout\": 600,\n    \"method\": \"aes-256-gcm\"\n}\n```\n\n[1]: https://github.com/shadowsocks/shadowsocks-libev\n[2]: https://shadowsocks.org/en/index.html\n[6]: https://duckduckgo.com/?q=password+12&t=ffsb&ia=answer\n[7]: https://github.com/docker/compose\n[8]: https://shadowsocks.org/en/download/clients.html\n[9]: https://docs.docker.com/\n[10]: https://www.digitalocean.com/products/linux-distribution/coreos/\n[11]: https://cloud.google.com/container-optimized-os/\n[12]: https://docs.docker.com/install/\n[13]: https://hub.docker.com/r/shadowsocks/shadowsocks-libev/tags/\n"
  },
  {
    "path": "docker/alpine/docker-compose.yml",
    "content": "shadowsocks:\n  image: shadowsocks/shadowsocks-libev\n  ports:\n    - \"8388:8388/tcp\"\n    - \"8388:8388/udp\"\n  environment:\n    - METHOD=aes-256-gcm\n    - PASSWORD=9MLSpPmNt\n  restart: always\n"
  },
  {
    "path": "docker/alpine/entrypoint.sh",
    "content": "#!/bin/sh\n# vim:sw=4:ts=4:et\n\nset -e\n\nif [ \"$1\" = \"ss-server\" ]; then\n    COREVER=$(uname -r | grep -Eo '[0-9].[0-9]+' | sed -n '1,1p')\n    CMV=$(echo $COREVER | awk -F '.' '{print $1}')\n    CSV=$(echo $COREVER | awk -F '.' '{print $2}')\n\n    if [[ -f \"$PASSWORD_FILE\" ]]; then\n        PASSWORD=$(cat \"$PASSWORD_FILE\")\n    fi\n    \n    if [[ -f \"/var/run/secrets/$PASSWORD_SECRET\" ]]; then\n        PASSWORD=$(cat \"/var/run/secrets/$PASSWORD_SECRET\")\n    fi\n    \n    if [[ ! -z \"$DNS_ADDRS\" ]]; then\n        DNS=\"-d $DNS_ADDRS\"\n    fi\n\n    if [ $(echo \"$CMV >= 3\" | bc) ]; then\n        if [ $(echo \"$CSV > 7\" | bc) ]; then\n        TFO='--fast-open'\n        fi\n    fi \n    RT_ARGS=\"-s $SERVER_ADDR -p $SERVER_PORT -k ${PASSWORD:-$(hostname)} -m $METHOD -a nobody -t $TIMEOUT -u $DNS $TFO $ARGS\"\nfi\n\nexec $@ $RT_ARGS"
  },
  {
    "path": "docker/mingw/Dockerfile",
    "content": "#\n# Dockerfile for building MinGW port\n#\n# This file is part of the shadowsocks-libev.\n#\n# shadowsocks-libev is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n#\n# shadowsocks-libev is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with shadowsocks-libev; see the file COPYING. If not, see\n# <http://www.gnu.org/licenses/>.\n#\n\nFROM debian:stretch\n\nARG REPO=shadowsocks\nARG REV=master\n\nADD docker/mingw/apt.sh /\n\nRUN \\\n  /bin/bash -c \"source /apt.sh && dk_prepare\" && \\\n  apt-get clean && \\\n  rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /build\n\nADD docker/mingw/prepare.sh /\n\nRUN /bin/bash -c \"source /prepare.sh && dk_download\"\n\nADD docker/mingw/deps.sh /\nRUN /bin/bash -c \"source /deps.sh && dk_deps\"\n\nADD docker/mingw/build.sh /\n\nARG REBUILD=0\n\nADD . /build/src/proj\n\nRUN /bin/bash -c \"source /build.sh && dk_build\"\n\nRUN /bin/bash -c \"source /build.sh && dk_package\"\n"
  },
  {
    "path": "docker/mingw/Makefile",
    "content": "#\n# Makefile for building MinGW port\n#\n# This file is part of the shadowsocks-libev.\n#\n# shadowsocks-libev is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n#\n# shadowsocks-libev is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with shadowsocks-libev; see the file COPYING. If not, see\n# <http://www.gnu.org/licenses/>.\n#\n\nREPO=shadowsocks\nREV=master\nIMAGE=ss-build-mingw\nDIST=ss-libev-win-dist.tar.gz\n\nall: build\n\nbuild:\n\tcd ../../ && docker build -t $(IMAGE) \\\n\t  -f docker/mingw/Dockerfile \\\n\t  --build-arg REV=$(REV) --build-arg REPO=$(REPO) \\\n\t  --build-arg REBUILD=\"$$(date +%Y-%m-%d-%H-%M-%S)\" \\\n\t  .\n\tdocker run --rm --entrypoint cat $(IMAGE) /bin.tgz > $(DIST)\n\nclean:\n\trm -f $(DIST)\n\tdocker rmi $(IMAGE) || true\n\n.PHONY: all clean build\n"
  },
  {
    "path": "docker/mingw/apt.sh",
    "content": "#!/bin/bash\n#\n# Functions for building MinGW port in Docker\n#\n# This file is part of the shadowsocks-libev.\n#\n# shadowsocks-libev is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n#\n# shadowsocks-libev is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with shadowsocks-libev; see the file COPYING. If not, see\n# <http://www.gnu.org/licenses/>.\n#\n\n# Exit on error\nset -e\n\n# Build steps\n\ndk_prepare() {\n    apt-get update -y\n    apt-get install --no-install-recommends -y \\\n      mingw-w64 aria2 git make automake autoconf libtool ca-certificates\n}\n"
  },
  {
    "path": "docker/mingw/build.sh",
    "content": "#!/bin/bash\n#\n# Functions for building MinGW port in Docker\n#\n# This file is part of the shadowsocks-libev.\n#\n# shadowsocks-libev is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n#\n# shadowsocks-libev is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with shadowsocks-libev; see the file COPYING. If not, see\n# <http://www.gnu.org/licenses/>.\n#\n\n# Exit on error\nset -e\n\n. /prepare.sh\n\nbuild_proj() {\n    arch=$1\n    host=$arch-w64-mingw32\n    prefix=${DIST}/$arch\n    dep=${PREFIX}/$arch\n    cpu=\"$(nproc --all)\"\n\n    cd \"$SRC\"\n    cd proj\n\n    ./autogen.sh\n    ./configure --host=${host} --prefix=${prefix} \\\n      --disable-documentation \\\n      --with-ev=\"$dep\" \\\n      --with-mbedtls=\"$dep\" \\\n      --with-sodium=\"$dep\" \\\n      --with-pcre=\"$dep\" \\\n      --with-cares=\"$dep\" \\\n      CFLAGS=\"-DCARES_STATICLIB -DPCRE_STATIC\"\n\n    make clean\n    make -j$cpu LDFLAGS=\"-all-static -L${dep}/lib\"\n    make install\n}\n\ndk_build() {\n    for arch in i686 x86_64; do\n        build_proj $arch\n    done\n}\n\ndk_package() {\n    rm -rf \"$BASE/pack\"\n    mkdir -p \"$BASE/pack\"\n    cd \"$BASE/pack\"\n    mkdir -p ss-libev-${PROJ_REV}\n    cd ss-libev-${PROJ_REV}\n    for bin in local server tunnel; do\n        cp ${DIST}/i686/bin/ss-${bin}.exe ss-${bin}-x86.exe\n        cp ${DIST}/x86_64/bin/ss-${bin}.exe ss-${bin}-x64.exe\n    done\n    cd ..\n    tar zcf /bin.tgz ss-libev-${PROJ_REV}\n}\n"
  },
  {
    "path": "docker/mingw/deps.sh",
    "content": "#!/bin/bash\n#\n# Functions for building MinGW port in Docker\n#\n# This file is part of the shadowsocks-libev.\n#\n# shadowsocks-libev is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n#\n# shadowsocks-libev is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with shadowsocks-libev; see the file COPYING. If not, see\n# <http://www.gnu.org/licenses/>.\n#\n\n# Exit on error\nset -e\n\n. /prepare.sh\n\nbuild_deps() {\n    arch=$1\n    host=$arch-w64-mingw32\n    prefix=${PREFIX}/$arch\n    args=\"--host=${host} --prefix=${prefix} --disable-shared --enable-static\"\n    cpu=\"$(nproc --all)\"\n\n    # libev\n    cd \"$SRC/$LIBEV_SRC\"\n    ./configure $args\n    make clean\n    make -j$cpu install\n\n    # mbedtls\n    cd \"$SRC/$MBEDTLS_SRC\"\n    make clean\n    make -j$cpu lib WINDOWS=1 CC=\"${host}-gcc\" AR=\"${host}-ar\"\n    ## \"make install\" command from mbedtls\n    DESTDIR=\"${prefix}\"\n    mkdir -p \"${DESTDIR}\"/include/mbedtls\n    cp -r include/mbedtls \"${DESTDIR}\"/include\n    mkdir -p \"${DESTDIR}\"/lib\n    cp -RP library/libmbedtls.*    \"${DESTDIR}\"/lib\n    cp -RP library/libmbedx509.*   \"${DESTDIR}\"/lib\n    cp -RP library/libmbedcrypto.* \"${DESTDIR}\"/lib\n    unset DESTDIR\n\n    # sodium\n    cd \"$SRC/$SODIUM_SRC\"\n    ./autogen.sh\n    ./configure $args\n    make clean\n    make -j$cpu install\n\n    # pcre\n    cd \"$SRC/$PCRE_SRC\"\n    ./configure $args --disable-cpp \\\n      --enable-unicode-properties\n    make clean\n    make -j$cpu install\n\n    # c-ares\n    cd \"$SRC/$CARES_SRC\"\n    ./configure $args\n    make clean\n    make -j$cpu install\n}\n\ndk_deps() {\n    for arch in i686 x86_64; do\n        build_deps $arch\n    done\n}\n"
  },
  {
    "path": "docker/mingw/make.bat",
    "content": "@echo off\r\npushd %~dp0\r\nset \"REPO=shadowsocks\"\r\nset \"REV=master\"\r\nset \"PLUGIN=true\"\r\nset \"IMAGE=ss-build-mingw\"\r\nset \"DIST=ss-libev-win-dist.tar.gz\"\r\ndocker build --force-rm -t %IMAGE% ^\r\n      --build-arg REV=%REV% --build-arg REPO=%REPO% ^\r\n      --build-arg REBUILD=%RANDOM% ^\r\n      --build-arg PLUGIN=%PLUGIN% .\r\ndocker run --rm --entrypoint cat %IMAGE% /bin.tgz > %DIST%\r\npause\r\n"
  },
  {
    "path": "docker/mingw/prepare.sh",
    "content": "#!/bin/bash\n#\n# Functions for building MinGW port in Docker\n#\n# This file is part of the shadowsocks-libev.\n#\n# shadowsocks-libev is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n#\n# shadowsocks-libev is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with shadowsocks-libev; see the file COPYING. If not, see\n# <http://www.gnu.org/licenses/>.\n#\n\n# Exit on error\nset -e\n\n# Build options\nBASE=\"/build\"\nPREFIX=\"$BASE/stage\"\nSRC=\"$BASE/src\"\nDIST=\"$BASE/dist\"\n\n# Project URL\nPROJ_SITE=$REPO   # Change REPO in Makefile\nPROJ_REV=$REV     # Change REV in Makefile\nPROJ_URL=https://github.com/${PROJ_SITE}/shadowsocks-libev.git\n\n# Libraries from project\n\n## libev for MinGW\nLIBEV_VER=mingw\nLIBEV_SRC=libev-${LIBEV_VER}\nLIBEV_URL=https://github.com/${PROJ_SITE}/libev/archive/${LIBEV_VER}.tar.gz\n\n# Public libraries\n\n## mbedTLS\nMBEDTLS_VER=2.16.5\nMBEDTLS_SRC=mbedtls-${MBEDTLS_VER}\nMBEDTLS_URL=https://tls.mbed.org/download/mbedtls-${MBEDTLS_VER}-apache.tgz\n\n## Sodium\nSODIUM_VER=1.0.18\nSODIUM_SRC=libsodium-stable\nSODIUM_URL=https://download.libsodium.org/libsodium/releases/libsodium-${SODIUM_VER}-stable.tar.gz\n\n## PCRE\nPCRE_VER=8.44\nPCRE_SRC=pcre-${PCRE_VER}\nPCRE_URL=https://ftp.pcre.org/pub/pcre/${PCRE_SRC}.tar.gz\n\n## c-ares\nCARES_VER=1.16.0\nCARES_SRC=c-ares-${CARES_VER}\nCARES_URL=https://c-ares.haxx.se/download/${CARES_SRC}.tar.gz\n\n# Build steps\n\ndk_download() {\n    mkdir -p \"${SRC}\"\n    cd \"${SRC}\"\n    DOWN=\"aria2c --file-allocation=trunc -s10 -x10 -j10 -c\"\n    for pkg in LIBEV SODIUM MBEDTLS PCRE CARES; do\n        src=${pkg}_SRC\n        url=${pkg}_URL\n        out=\"${!src}\".tar.gz\n        $DOWN ${!url} -o \"${out}\"\n        echo \"Unpacking ${out}...\"\n        tar zxf ${out}\n    done\n}\n"
  },
  {
    "path": "rpm/SOURCES/etc/init.d/shadowsocks-libev",
    "content": "#!/bin/bash\n#\n# Script to run Shadowsocks in daemon mode at boot time.\n# ScriptAuthor: icyboy\n# Revision 1.0 - 14th Sep 2013\n#====================================================================\n# Run level information:\n# chkconfig: 2345 99 99\n# Description: lightweight secured socks5 proxy\n# processname: ss-server\n# Author: Max Lv <max.c.lv@gmail.com>;\n# Run \"/sbin/chkconfig --add shadowsocks\" to add the Run levels.\n#====================================================================\n\n#====================================================================\n# Paths and variables and system checks.\n\n# Source function library\n. /etc/rc.d/init.d/functions\n\n# Check that networking is up.\n#\n[ ${NETWORKING} =\"yes\" ] || exit 0\n\n# Daemon\nNAME=shadowsocks-server\nDAEMON=/usr/bin/ss-server\n\n# Path to the configuration file.\n#\nCONF=/etc/shadowsocks-libev/config.json\n\n#USER=\"nobody\"\n#GROUP=\"nobody\"\n\n# Take care of pidfile permissions\nmkdir /var/run/$NAME 2>/dev/null || true\n#chown \"$USER:$GROUP\" /var/run/$NAME\n\n# Check the configuration file exists.\n#\nif [ ! -f $CONF ] ; then\necho \"The configuration file cannot be found!\"\nexit 0\nfi\n\n# Path to the lock file.\n#\nLOCK_FILE=/var/lock/subsys/shadowsocks\n\n# Path to the pid file.\n#\nPID=/var/run/$NAME/pid\n\n\n#====================================================================\n\n#====================================================================\n# Run controls:\n\nRETVAL=0\n\n# Start shadowsocks as daemon.\n#\nstart() {\nif [ -f $LOCK_FILE ]; then\necho \"$NAME is already running!\"\nexit 0\nelse\necho -n $\"Starting ${NAME}: \"\n#daemon --check $DAEMON --user $USER \"$DAEMON -f $PID -c $CONF > /dev/null\"\ndaemon $DAEMON -c $CONF -f $PID\nfi\n\nRETVAL=$?\n[ $RETVAL -eq 0 ] && success\necho\n[ $RETVAL -eq 0 ] && touch $LOCK_FILE\nreturn $RETVAL\n}\n\n\n# Stop shadowsocks.\n#\nstop() {\necho -n $\"Shutting down ${NAME}: \"\nkillproc -p ${PID}\nRETVAL=$?\n[ $RETVAL -eq 0 ]\nrm -f $LOCK_FILE\nrm -f ${PID}\necho\nreturn $RETVAL\n}\n\n# See how we were called.\ncase \"$1\" in\nstart)\nstart\n;;\nstop)\nstop\n;;\nrestart)\nstop\nstart\n;;\ncondrestart)\nif [ -f $LOCK_FILE ]; then\nstop\nstart\nRETVAL=$?\nfi\n;;\nstatus)\nstatus $DAEMON\nRETVAL=$?\n;;\n*)\necho $\"Usage: $0 {start|stop|restart|condrestart|status}\"\nRETVAL=1\nesac\n\nexit $RETVAL\n"
  },
  {
    "path": "rpm/SOURCES/systemd/shadowsocks-libev-local.service",
    "content": "#  This file is part of shadowsocks-libev.\n#\n#  Shadowsocks-libev is free software; you can redistribute it and/or modify\n#  it under the terms of the GNU General Public License as published by\n#  the Free Software Foundation; either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  This file is default for RPM packaging. See also\n#  /etc/sysconfig/shadowsocks-libev for environment variables.\n\n[Unit]\nDescription=Shadowsocks-libev Default Local Service\nDocumentation=man:shadowsocks-libev(8)\nAfter=network-online.target\n\n[Service]\nType=simple\nEnvironmentFile=/etc/sysconfig/shadowsocks-libev\nUser=nobody\nGroup=nobody\nLimitNOFILE=32768\nExecStart=/usr/bin/ss-local -c \"$CONFFILE\" $DAEMON_ARGS\nCapabilityBoundingSet=CAP_NET_BIND_SERVICE\n\n[Install]\nWantedBy=multi-user.target\n\n"
  },
  {
    "path": "rpm/SOURCES/systemd/shadowsocks-libev-local@.service",
    "content": "#  This file is part of shadowsocks-libev.\n#\n#  Shadowsocks-libev is free software; you can redistribute it and/or modify\n#  it under the terms of the GNU General Public License as published by\n#  the Free Software Foundation; either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  This is a template unit file. Users may copy and rename the file into\n#  config directories to make new service instances. See systemd.unit(5)\n#  for details.\n\n[Unit]\nDescription=Shadowsocks-Libev Custom Client Service for %I\nDocumentation=man:ss-local(1)\nAfter=network-online.target\n\n[Service]\nType=simple\nCapabilityBoundingSet=CAP_NET_BIND_SERVICE\nExecStart=/usr/bin/ss-local -c /etc/shadowsocks-libev/%i.json\nUser=nobody\nGroup=nobody\nLimitNOFILE=32768\n\n[Install]\nWantedBy=multi-user.target\n\n"
  },
  {
    "path": "rpm/SOURCES/systemd/shadowsocks-libev-redir@.service",
    "content": "#  This file is part of shadowsocks-libev.\n#\n#  Shadowsocks-libev is free software; you can redistribute it and/or modify\n#  it under the terms of the GNU General Public License as published by\n#  the Free Software Foundation; either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  This is a template unit file. Users may copy and rename the file into\n#  config directories to make new service instances. See systemd.unit(5)\n#  for details.\n\n[Unit]\nDescription=Shadowsocks-Libev Custom Client Service Redir Mode for %I\nDocumentation=man:ss-redir(1)\nAfter=network-online.target\n\n[Service]\nType=simple\nCapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE\nExecStart=/usr/bin/ss-redir -c /etc/shadowsocks-libev/%i.json\nUser=nobody\nGroup=nobody\nLimitNOFILE=32768\n\n[Install]\nWantedBy=multi-user.target\n\n"
  },
  {
    "path": "rpm/SOURCES/systemd/shadowsocks-libev-server@.service",
    "content": "#  This file is part of shadowsocks-libev.\n#\n#  Shadowsocks-libev is free software; you can redistribute it and/or modify\n#  it under the terms of the GNU General Public License as published by\n#  the Free Software Foundation; either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  This is a template unit file. Users may copy and rename the file into\n#  config directories to make new service instances. See systemd.unit(5)\n#  for details.\n\n[Unit]\nDescription=Shadowsocks-Libev Custom Server Service for %I\nDocumentation=man:ss-server(1)\nAfter=network-online.target\n\n[Service]\nType=simple\nCapabilityBoundingSet=CAP_NET_BIND_SERVICE\nExecStart=/usr/bin/ss-server -c /etc/shadowsocks-libev/%i.json\nUser=nobody\nGroup=nobody\nLimitNOFILE=32768\n\n[Install]\nWantedBy=multi-user.target\n\n"
  },
  {
    "path": "rpm/SOURCES/systemd/shadowsocks-libev-tunnel@.service",
    "content": "#  This file is part of shadowsocks-libev.\n#\n#  Shadowsocks-libev is free software; you can redistribute it and/or modify\n#  it under the terms of the GNU General Public License as published by\n#  the Free Software Foundation; either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  This is a template unit file. Users may copy and rename the file into\n#  config directories to make new service instances. See systemd.unit(5)\n#  for details.\n\n[Unit]\nDescription=Shadowsocks-Libev Custom Client Service Tunnel Mode for %I\nDocumentation=man:ss-tunnel(1)\nAfter=network-online.target\n\n[Service]\nType=simple\nCapabilityBoundingSet=CAP_NET_BIND_SERVICE\nExecStart=/usr/bin/ss-tunnel -c /etc/shadowsocks-libev/%i.json\nUser=nobody\nGroup=nobody\nLimitNOFILE=32768\n\n[Install]\nWantedBy=multi-user.target\n\n"
  },
  {
    "path": "rpm/SOURCES/systemd/shadowsocks-libev.default",
    "content": "# Defaults for shadowsocks initscript\n# sourced by /etc/init.d/shadowsocks-libev\n# installed at /etc/sysconfig/shadowsocks-libev by the maintainer scripts\n\n#\n# This is a POSIX shell fragment\n#\n# Note: `START', `GROUP' and `MAXFD' options are not recognized by systemd.\n# Please change those settings in the corresponding systemd unit file.\n\n# Enable during startup?\nSTART=yes\n\n# Configuration file\nCONFFILE=\"/etc/shadowsocks-libev/config.json\"\n\n# Extra command line arguments\nDAEMON_ARGS=\"-u\"\n\n# User and group to run the server as\nUSER=nobody\nGROUP=nobody\n\n# Number of maximum file descriptors\nMAXFD=32768\n"
  },
  {
    "path": "rpm/SOURCES/systemd/shadowsocks-libev.service",
    "content": "#  This file is part of shadowsocks-libev.\n#\n#  Shadowsocks-libev is free software; you can redistribute it and/or modify\n#  it under the terms of the GNU General Public License as published by\n#  the Free Software Foundation; either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  This file is default for RPM packaging. See also\n#  /etc/sysconfig/shadowsocks-libev for environment variables.\n\n[Unit]\nDescription=Shadowsocks-libev Default Server Service\nDocumentation=man:shadowsocks-libev(8)\nAfter=network-online.target network-online.target \n\n[Service]\nType=simple\nEnvironmentFile=/etc/sysconfig/shadowsocks-libev\nUser=nobody\nGroup=nobody\nLimitNOFILE=32768\nExecStart=/usr/bin/ss-server -c \"$CONFFILE\" $DAEMON_ARGS\nCapabilityBoundingSet=CAP_NET_BIND_SERVICE\n\n[Install]\nWantedBy=multi-user.target\n\n"
  },
  {
    "path": "rpm/SPECS/shadowsocks-libev.spec.in",
    "content": "%global requires   pcre openssl mbedtls libsodium >= 1.0.4 libev c-ares\n%global conflicts  python-shadowsocks python3-shadowsocks\n%if 0%{?fedora} || 0%{?rhel}\n%global requires   %{?requires} libcap\n%endif\n%if 0%{?suse_version}\n%global requires   %{?requires} libcap-progs\n%endif\n%global project_desc shadowsocks-libev is a lightweight secured socks5 proxy for embedded devices and low end boxes.\n\n%if 0%{?fedora} >= 15 || 0%{?rhel} >=7 || 0%{?suse_version} >= 1210\n%global use_systemd 1\n%else\n%global use_systemd 0\n%endif\n\n# https://fedoraproject.org/wiki/Changes/RemoveLaFiles\n%global __brp_remove_la_files %nil\n\nName:\t\t    @NAME@\nVersion:\t    @VERSION@\nRelease:\t    @RELEASE@%{?dist}\nSummary:\t    A lightweight and secure socks5 proxy\n\nGroup:\t\t    Applications/Internet\nLicense:\t    GPLv3+\nURL:\t\t    https://github.com/shadowsocks/%{name}\nSource0:\t    @SOURCE@\n\nBuildRequires:\tmake gcc pcre-devel asciidoc xmlto automake libtool mbedtls-devel libsodium-devel >= 1.0.4 libev-devel c-ares-devel\n%if 0%{?suse_version}\nBuildRequires:  libopenssl-devel\n%else\nBuildRequires:  openssl-devel\n%endif\n\nAutoReq:        no\nConflicts:\t    %{?conflicts}\nRequires:       %{?requires}\n\n%if 0%{?use_systemd}\n%{?systemd_requires}\n%if 0%{?suse_version}\nBuildRequires:   systemd-rpm-macros\n%else\nBuildRequires:   systemd\n%endif\n%endif\n\n%description\n%{?project_desc}\n\n%prep\n%setup -q -n @NAME_VERSION@\n\n%build\n./autogen.sh\n\n%if 0%{?use_system_lib}\n%configure --enable-shared --enable-system-shared-lib\n%else\n%configure --enable-shared\n%endif\nmake %{?_smp_mflags}\n\n\n%install\nmake install DESTDIR=%{buildroot}\nmkdir -p %{buildroot}/etc/shadowsocks-libev\n%if ! 0%{?use_systemd}\nmkdir -p %{buildroot}%{_initddir}\ninstall -m 755 %{_builddir}/%{buildsubdir}/rpm/SOURCES/etc/init.d/shadowsocks-libev %{buildroot}%{_initddir}/shadowsocks-libev\n%else\nmkdir -p %{buildroot}%{_sysconfdir}/sysconfig\nmkdir -p %{buildroot}%{_unitdir}\ninstall -m 644 %{_builddir}/%{buildsubdir}/rpm/SOURCES/systemd/shadowsocks-libev.default %{buildroot}%{_sysconfdir}/sysconfig/shadowsocks-libev\ninstall -m 644 %{_builddir}/%{buildsubdir}/rpm/SOURCES/systemd/shadowsocks-libev*.service %{buildroot}%{_unitdir}/\n%endif\ninstall -m 644 %{_builddir}/%{buildsubdir}/debian/config.json %{buildroot}%{_sysconfdir}/shadowsocks-libev/config.json\n\nmkdir -p %{buildroot}%{_datadir}/bash-completion/completions/\ninstall -m 644 %{_builddir}/%{buildsubdir}/completions/bash/* %{buildroot}%{_datadir}/bash-completion/completions/\nmkdir -p %{buildroot}%{_datadir}/zsh/site-functions/\ninstall -m 644 %{_builddir}/%{buildsubdir}/completions/zsh/* %{buildroot}%{_datadir}/zsh/site-functions/\n\n%pre\n%if 0%{?use_systemd} && 0%{?suse_version}\n%service_add_pre shadowsocks-libev.service\n%endif\n\n%post\n%if ! 0%{?use_systemd}\n/sbin/chkconfig --add shadowsocks-libev > /dev/null 2>&1 || :\n%else\n%if 0%{?suse_version}\n%service_add_post shadowsocks-libev.service\n%else\n%systemd_post shadowsocks-libev.service\n%endif\n%endif\nsetcap cap_net_bind_service+ep %{_bindir}/ss-local \\\n       cap_net_bind_service,cap_net_admin+ep %{_bindir}/ss-redir \\\n       cap_net_bind_service+ep %{_bindir}/ss-server \\\n       cap_net_bind_service+ep %{_bindir}/ss-tunnel\n\n%preun\n%if ! 0%{?use_systemd}\nif [ $1 -eq 0 ]; then\n    /sbin/service shadowsocks-libev stop  > /dev/null 2>&1 || :\n    /sbin/chkconfig --del shadowsocks-libev > /dev/null 2>&1 || :\nfi\n%else\n%if 0%{?suse_version}\n%service_del_preun shadowsocks-libev.service\n%service_del_preun shadowsocks-libev-local.service\n%else\n%systemd_preun shadowsocks-libev.service\n%systemd_preun shadowsocks-libev-local.service\nif [ $1 -eq 0 ] ; then\n    # Package removal, not upgrade\n    systemctl stop shadowsocks-libev-server@'*'.service  > /dev/null 2>&1 || :\n    systemctl stop shadowsocks-libev-local@'*'.service  > /dev/null 2>&1 || :\n    systemctl stop shadowsocks-libev-tunnel@'*'.service  > /dev/null 2>&1 || :\n    systemctl stop shadowsocks-libev-redir@'*'.service  > /dev/null 2>&1 || :\n    systemctl --no-reload disable shadowsocks-libev-server@.service  > /dev/null 2>&1 || :\n    systemctl --no-reload disable shadowsocks-libev-local@.service  > /dev/null 2>&1 || :\n    systemctl --no-reload disable shadowsocks-libev-tunnel@.service  > /dev/null 2>&1 || :\n    systemctl --no-reload disable shadowsocks-libev-redir@.service  > /dev/null 2>&1 || :\nfi\n%endif\n%endif\n\n%postun\n%if 0%{?use_systemd}\n%if 0%{?suse_version}\n%service_del_postun shadowsocks-libev.service\n%else\n%systemd_postun_with_restart shadowsocks-libev.service\n%systemd_postun_with_restart shadowsocks-libev-local.service\n%systemd_postun_with_restart shadowsocks-libev-server@'*'.service\n%systemd_postun_with_restart shadowsocks-libev-local@'*'.service\n%systemd_postun_with_restart shadowsocks-libev-tunnel@'*'.service\n%systemd_postun_with_restart shadowsocks-libev-redir@'*'.service\n%endif\n%endif\n\n%files\n%doc %{_docdir}/shadowsocks-libev/*.html\n%exclude %{_docdir}/shadowsocks-libev/ss-nat.html\n%{_bindir}/*\n%exclude %{_bindir}/ss-nat\n%config(noreplace) %{_sysconfdir}/shadowsocks-libev/config.json\n%{_datadir}/bash-completion/completions/*\n%doc %{_mandir}/man*/*\n%exclude %{_mandir}/man1/ss-nat.1.*\n%if ! 0%{?use_systemd}\n%{_initddir}/shadowsocks-libev\n%else\n%{_unitdir}/shadowsocks-libev*.service\n%config(noreplace) %{_sysconfdir}/sysconfig/shadowsocks-libev\n%endif\n\n\n%package -n libshadowsocks-libev\nSummary:        %{?summary} (shared library)\nAutoReq:        no\nRequires:       pcre openssl mbedtls libsodium >= 1.0.4 libev c-ares\n\n%description -n libshadowsocks-libev\nShared library powered by shadowsocks-libev.\n%{?project_desc}\n\n%files -n libshadowsocks-libev\n%{_libdir}/*.so.*\n\n%post -n libshadowsocks-libev\n/sbin/ldconfig\n\n%postun -n libshadowsocks-libev\n/sbin/ldconfig\n\n\n%package -n libshadowsocks-libev-devel\nSummary:    Development files for shadowsocks-libev\nProvides:   shadowsocks-libev-devel = %{version}-%{release}\nRequires:   libshadowsocks-libev = %{version}-%{release}\nObsoletes:  shadowsocks-libev-devel < %{version}-%{release}\n\n%description -n libshadowsocks-libev-devel\nDevelopment files for libshadowsocks-libev.\n%{?project_desc}\n\n%files -n libshadowsocks-libev-devel\n%{_includedir}/*\n%{_libdir}/pkgconfig/*.pc\n%{_libdir}/libshadowsocks-libev.la\n%{_libdir}/libshadowsocks-libev.so\n\n%package zsh-completion\nSummary:        This package installs zsh completion files for shadowsocks-libev.\nRequires:       zsh shadowsocks-libev = %{version}-%{release}\n\n%description zsh-completion\nzsh completion files for shadowsocks-libev.\n%{?project_desc}\n\n%files zsh-completion\n%{_datadir}/zsh/site-functions/*\n\n%changelog\n\n"
  },
  {
    "path": "rpm/genrpm.sh",
    "content": "#!/usr/bin/env bash\nset -e\n\nNAME=shadowsocks-libev\n\nSELF=$(readlink -f -- \"$0\")\nHERE=$(dirname -- \"$SELF\")\n\nSOURCES=\"${HERE}\"/SOURCES\nSPEC_TEMPLATE=\"${HERE}\"/SPECS/${NAME}.spec.in\nSPEC_FILE=\"${SPEC_TEMPLATE%%.in}\"\n\nGIT_VERSION=$(\"${HERE}\"/../scripts/git_version.sh)\n\nOPT_OUTDIR=\"${HERE}/SRPMS\"\nOPT_USE_SYSTEM_LIB=0\nOUT_BUILD_RPM=0\n\nversion=$(echo ${GIT_VERSION} | cut -d' ' -f1)\nrelease=$(echo ${GIT_VERSION} | cut -d' ' -f2)\n\nname_version=${NAME}-${version}-${release}\nsource_name=${name_version}.tar.gz\n\narchive()\n{\n    \"${HERE}\"/../scripts/git_archive.sh -o \"${SOURCES}\" -n ${name_version}\n}\n\nbuild_src_rpm()\n{\n    rpmbuild -bs \"${SPEC_FILE}\" \\\n       --undefine \"dist\" \\\n       --define \"%_topdir ${HERE}\" \\\n       --define \"%_srcrpmdir ${OPT_OUTDIR}\"\n}\n\nbuild_rpm()\n{\n    rpmbuild --rebuild \"${OPT_OUTDIR}\"/${name_version}.src.rpm \\\n       --define \"%_topdir ${HERE}\" \\\n       --define \"%use_system_lib ${OPT_USE_SYSTEM_LIB}\"\n}\n\ncreate_spec()\n{\n    sed -e \"s/@NAME@/${NAME}/g\" \\\n        -e \"s/@VERSION@/${version}/g\" \\\n        -e \"s/@RELEASE@/${release}/g\" \\\n        -e \"s/@SOURCE@/${source_name}/g\" \\\n        -e \"s/@NAME_VERSION@/${name_version}/g\" \\\n        \"${SPEC_TEMPLATE}\" > \"${SPEC_FILE}\"\n}\n\nshow_help()\n{\n    echo -e \"$(basename $0) [OPTION...]\"\n    echo -e \"Create and build shadowsocks-libev SRPM\"\n    echo\n    echo -e \"Options:\"\n    echo -e \"  -h    show this help.\"\n    echo -e \"  -b    use rpmbuld to build resulting SRPM\"\n    echo -e \"  -s    use system shared libraries (RPM only)\"\n    echo -e \"  -o    output directory\"\n}\n\nwhile getopts \"hbso:\" opt\ndo\n    case ${opt} in\n        h)\n            show_help\n            exit 0\n            ;;\n        b)\n            OPT_BUILD_RPM=1\n            ;;\n        s)\n            OPT_USE_SYSTEM_LIB=1\n            ;;\n        o)\n            OPT_OUTDIR=$(readlink -f -- $OPTARG)\n            ;;\n        *)\n            show_help\n            exit 1\n            ;;\n    esac\ndone\n\ncreate_spec\narchive\nbuild_src_rpm\nif [ \"${OPT_BUILD_RPM}\" = \"1\" ] ; then\n    build_rpm\nfi\n"
  },
  {
    "path": "scripts/build_deb.sh",
    "content": "#!/bin/sh\n# Copyright 2017-2018 Roger Shimizu <rosh@debian.org>\n#\n# This is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n\nhelp_usage() {\ncat << EOT\n\nBuild shadowsocks-libev and its dependencies\nUsage:\n\t$(basename $0) [--help|-h] [lib|bin|all]\n\n\t--help|-h\tShow this usage.\n\tkcp\t\tBuild kcptun package (with its dependencies) only.\n\tlib\t\tBuild library packages only.\n\tbin\t\tBuild binary packages only.\n\t\t\tHowever, you need the libraries built previously, in current working directory.\n\t\t\tFor advanced user only.\n\tall\t\tBuild both binary and library packages (default).\n\t\t\tThe safe choice for everyone.\n\nPlease run this script in a clean place.\ne.g.\n\tmkdir -p ~/build-area\n\tcd ~/build-area\n\tln -s $(readlink -f $0) .\n\t./$(basename $0)\n\nEOT\nexit\n}\n\nhelp_lib() {\ncat << EOT\n\nFailed to install required library:\n\t$1\nYou can try to fix it by:\n\n\t$0 lib\n\nEOT\nexit\n}\n\napt_init() {\n\tDEPS=\"$1\"\n\tDEPS_BPO=\"$2\"\n\tDEPS_EXTRA=\"$3\"\n\tif [ -n \"$DEPS_BPO\" ]; then\n\t\tBPO=${OSVER}-backports\n\t\tcase \"$OSID\" in\n\t\tdebian)\n\t\t\tREPO=http://deb.debian.org/debian\n\t\t\t;;\n\t\tubuntu)\n\t\t\tREPO=http://archive.ubuntu.com/ubuntu\n\t\t\t;;\n\t\tesac\n\t\tsudo sh -c \"printf \\\"deb $REPO ${OSVER}-backports main\\\" > /etc/apt/sources.list.d/${OSVER}-backports.list\"\n\t\t[ -n \"$DEPS_EXTRA\" -a \"$DEPS_EXTRA\" = \"sloppy\" ] &&\n\t\t\tsudo sh -c \"printf \\\"\\\\ndeb $REPO ${OSVER}-backports-sloppy main\\\" >> /etc/apt/sources.list.d/${OSVER}-backports.list\"\n\t\tsudo apt-get update\n\t\tsudo apt-get install --no-install-recommends -y -t $BPO $DEPS_BPO\n\t\t[ -n \"$DEPS_EXTRA\" -a \"$DEPS_EXTRA\" = \"sloppy\" ] &&\n\t\t\tsudo apt-get install --no-install-recommends -y -t ${BPO}-sloppy $DEPS_BPO\n\telse\n\t\tsudo apt-get update\n\tfi\n\tsudo apt-get install -y $DEPS\n}\n\n# Cleanup\napt_clean() {\n\tsudo apt-get purge -y $DEPS $DEPS_BPO debhelper \\\n\t\tlibbloom-dev libcork-dev libcorkipset-dev libmbedtls-dev libsodium-dev\n\tsudo apt-get purge -y libcork-build-deps libcorkipset-build-deps \\\n\t\tlibsodium-build-deps mbedtls-build-deps\n\tsudo apt-get purge -y libbloom-build-deps\n\tsudo apt-get purge -y simple-obfs-build-deps\n\tsudo apt-get purge -y shadowsocks-libev-build-deps\n\nif [ $BUILD_KCP -eq 1 ]; then\n\tsudo apt-get purge -y golang-github-klauspost-reedsolomon-build-deps \\\n\t\tgolang-github-xtaci-kcp-build-deps golang-github-xtaci-smux-build-deps \\\n\t\tkcptun-build-deps\n\tsudo apt-get purge -y golang-github-urfave-cli-build-deps\n\tsudo apt-get purge -y golang-github-golang-snappy-build-deps \\\n\t\tdh-golang-build-deps golang-github-pkg-errors-build-deps\n\n\tsudo apt-get purge -y golang-github-klauspost-reedsolomon-dev \\\n\t\tgolang-github-xtaci-kcp-dev golang-github-xtaci-smux-dev\n\tsudo apt-get purge -y golang-github-urfave-cli-dev\n\tsudo apt-get purge -y golang-github-pkg-errors-dev \\\n\t\tgolang-github-golang-snappy-dev dh-golang\nfi\n\n\tsudo apt-get autoremove -y\n}\n\ngbp_build() {\n\tREPO=$1\n\tBRANCH=$2\n\tPROJECT_NAME=$(basename $1|sed s/\\.git$//)\n\tgbp clone --pristine-tar $REPO\n\tcd $PROJECT_NAME\n\t[ -n \"$BRANCH\" ] && git checkout $BRANCH\n\t[ -n \"$BRANCH\" -a \"$BRANCH\" = \"trusty\" ] && # try to rebase the trusty patch\n\t\tif ! git rebase master; then git rebase --abort; git rebase debian; fi\n\t[ -n \"$DEPS_BPO\" ] && BPO_REPO=\"-t ${OSVER}-backports\"\n\tmk-build-deps --root-cmd sudo --install --tool \"apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends -y $BPO_REPO\"\n\trm -f ${PROJECT_NAME}-build-deps_*.deb\n\tgbp buildpackage -us -uc --git-ignore-branch --git-pristine-tar\n\tgit clean -fdx\n\tgit reset --hard HEAD\n\tcd -\n}\n\ngit_build() {\n\tREPO=$1\n\tBRANCH=$2\n\tPROJECT_NAME=$(basename $1|sed s/\\.git$//)\n\tgit clone $REPO\n\tcd $PROJECT_NAME\n\t[ -n \"$BRANCH\" ] && git checkout $BRANCH\n\tmk-build-deps --root-cmd sudo --install --tool \"apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends -y\"\n\trm ${PROJECT_NAME}-build-deps_*.deb\n\tgbp buildpackage -us -uc --git-ignore-branch\n\tgit clean -fdx\n\tgit reset --hard HEAD\n\tcd -\n}\n\ndsc_build() {\n\tDSC=$1\n\tDSC_FILE=$(basename $1)\n\tdget -ux $DSC\n\tPROJECT_NAME=$(grep ^Source: $DSC_FILE|cut -d\" \" -f2)\n\techo cd ${PROJECT_NAME}-*\n\tcd ${PROJECT_NAME}-*\n\tmk-build-deps --root-cmd sudo --install --tool \"apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends -y\"\n\trm ${PROJECT_NAME}-build-deps_*.deb\n\tdpkg-buildpackage -us -uc\n\tcd -\n}\n\n# Build and install libcork deb\nbuild_install_libcork() {\nif [ $BUILD_LIB -eq 1 -o $BUILD_BIN -eq 1 ]; then\n\tBRANCH=$1\n\tif [ $BUILD_LIB -eq 1 ]; then\n\t\tgbp_build https://github.com/rogers0/libcork $BRANCH\n\telse\n\t\tls libcork-dev_*.deb libcork16_*.deb 2>&1 > /dev/null ||\n\t\t\thelp_lib \"libcork-dev libcork16\"\n\tfi\n\tsudo dpkg -i libcork-dev_*.deb libcork16_*.deb\nfi\n}\n\n# Build and install libcorkipset deb\nbuild_install_libcorkipset() {\nif [ $BUILD_LIB -eq 1 -o $BUILD_BIN -eq 1 ]; then\n\tBRANCH=$1\n\tif [ $BUILD_LIB -eq 1 ]; then\n\t\tgbp_build https://github.com/rogers0/libcorkipset $BRANCH\n\telse\n\t\tls libcorkipset-dev_*.deb libcorkipset1_*.deb 2>&1 > /dev/null ||\n\t\t\thelp_lib \"libcorkipset-dev libcorkipset1\"\n\tfi\n\tsudo dpkg -i libcorkipset-dev_*.deb libcorkipset1_*.deb\nfi\n}\n\n# Build libmbedtls deb\nbuild_install_libmbedtls() {\nif [ $BUILD_LIB -eq 1 -o $BUILD_BIN -eq 1 ]; then\n\tBRANCH=$1\n\tif [ $BUILD_LIB -eq 1 ]; then\n\t\tgbp_build https://salsa.debian.org/debian/mbedtls.git $BRANCH\n\telse\n\t\tls libmbed*.deb 2>&1 > /dev/null ||\n\t\t\thelp_lib libmbedtls\n\tfi\n\tsudo dpkg -i libmbed*.deb\nfi\n}\n\n# Build libsodium deb\nbuild_install_libsodium() {\nif [ $BUILD_LIB -eq 1 -o $BUILD_BIN -eq 1 ]; then\n\tif [ $BUILD_LIB -eq 1 ]; then\n\t\tgit clone https://github.com/gcsideal/debian-libsodium.git libsodium\n\t\tcd libsodium; LIBSODIUM=$(dpkg-parsechangelog --show-field Version); cd -\n\t\tdget -ud https://deb.debian.org/debian/pool/main/libs/libsodium/libsodium_${LIBSODIUM}.dsc\n\t\tDHVER=$(dpkg -l debhelper|grep debhelper|awk '{print $3}'|head -n1)\n\t\tcd libsodium\n\t\tif dpkg --compare-versions $DHVER lt 10; then\n\t\t\tsed -i 's/debhelper ( >= 11)/debhelper (>= 9), dh-autoreconf/' debian/control;\n\t\t\tsed -i 's/debhelper ( >= 10)/debhelper (>= 9), dh-autoreconf/' debian/control;\n\t\t\techo 9 > debian/compat;\n\t\t\tdch -D unstable -l~bpo~ \"Rebuild as backports\"\n\t\t\tgit add -u;\n\t\t\tgit commit -m \"Patch to work with ubuntu\"\n\t\telif dpkg --compare-versions $DHVER lt 11; then\n\t\t\tsed -i 's/debhelper ( >= 11)/debhelper (>= 10)/' debian/control;\n\t\t\techo 10 > debian/compat;\n\t\t\tdch -D unstable -l~bpo~ \"Rebuild as backports\"\n\t\t\tgit add -u;\n\t\t\tgit commit -m \"Patch to work with ubuntu\"\n\t\tfi\n\t\tmk-build-deps --root-cmd sudo --install --tool \"apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends -y\"\n\t\trm libsodium-build-deps_*.deb\n\t\tgbp buildpackage -us -uc --git-ignore-branch --git-tarball-dir=.. --git-export-dir=.. --git-overlay\n\t\tcd -\n\telse\n\t\tls libsodium*.deb 2>&1 > /dev/null ||\n\t\t\thelp_lib libsodium\n\tfi\n\tsudo dpkg -i libsodium*.deb\nfi\n}\n\n# Build libbloom deb\nbuild_install_libbloom() {\nif [ $BUILD_LIB -eq 1 -o $BUILD_BIN -eq 1 ]; then\n\tBRANCH=$1\n\tif [ $BUILD_LIB -eq 1 ]; then\n\t\tgbp_build https://salsa.debian.org/bridges-team/libbloom.git $BRANCH\n\telse\n\t\tls libbloom-dev_*.deb libbloom1_*.deb 2>&1 > /dev/null ||\n\t\t\thelp_lib \"libbloom-dev libbloom1\"\n\tfi\n\tsudo dpkg -i libbloom-dev_*.deb libbloom1_*.deb\nfi\n}\n\n# Add patch to work on system with debhelper 9 only\npatch_sslibev_dh9() {\nif [ $BUILD_BIN -eq 1 ]; then\n\tBRANCH=$1\n\tgbp clone --pristine-tar https://salsa.debian.org/bridges-team/shadowsocks-libev.git\n\tcd shadowsocks-libev\n\t[ -n \"$BRANCH\" ] && git checkout $BRANCH\n\tsed -i 's/dh $@/dh $@ --with systemd,autoreconf/' debian/rules\n\tsed -i 's/debhelper (>= 10)/debhelper (>= 9), dh-systemd, dh-autoreconf/' debian/control\n\techo 9 > debian/compat\n\tdch -D unstable -l~bpo~ \"Rebuild as backports\"\n\tgit add -u\n\tgit commit -m \"Patch to work with ubuntu trusty (14.04)\"\n\tcd -\nfi\n}\n\n# Build and install shadowsocks-libev deb\nbuild_install_sslibev() {\nif [ $BUILD_BIN -eq 1 ]; then\n\tBRANCH=$1\n\tgbp_build https://salsa.debian.org/bridges-team/shadowsocks-libev.git $BRANCH\n\tsudo dpkg -i shadowsocks-libev_*.deb\n\tsudo apt-get install -fy\nfi\n}\n\n# Build and install simple-obfs\nbuild_install_simpleobfs() {\nif [ $BUILD_BIN -eq 1 ]; then\n\tBRANCH=$1\n\tgit_build https://salsa.debian.org/bridges-team/simple-obfs.git $BRANCH\n\tsudo dpkg -i simple-obfs_*.deb\n\tsudo apt-get install -fy\nfi\n}\n\n# Build and install dh-golang deb\nbuild_install_dhgolang() {\nif [ $BUILD_KCP -eq 1 ]; then\n\tBRANCH=$1\n\tgbp_build https://salsa.debian.org/go-team/packages/dh-golang.git $BRANCH\n\tsudo dpkg -i dh-golang_*.deb\n\tsudo apt-get install -fy\nfi\n}\n\n# Build and install golang-github-klauspost-reedsolomon deb\nbuild_install_reedsolomondev() {\nif [ $BUILD_KCP -eq 1 ]; then\n\tBRANCH=$1\n\tgbp_build https://salsa.debian.org/go-team/packages/golang-github-klauspost-reedsolomon.git $BRANCH\n\tsudo dpkg -i golang-github-klauspost-reedsolomon-dev_*.deb\n\tsudo apt-get install -fy\nfi\n}\n\n# Build and install golang-github-pkg-errors deb\nbuild_install_errorsdev() {\nif [ $BUILD_KCP -eq 1 ]; then\n\tBRANCH=$1\n\tgbp_build https://salsa.debian.org/go-team/packages/golang-github-pkg-errors.git $BRANCH\n\tsudo dpkg -i golang-github-pkg-errors-dev_*.deb\n\tsudo apt-get install -fy\nfi\n}\n\n# Add patch to work on system with xenial\npatch_urfaveclidev_xenial() {\nif [ $BUILD_KCP -eq 1 ]; then\n\tBRANCH=$1\n\tgbp clone --pristine-tar https://salsa.debian.org/go-team/packages/golang-github-urfave-cli.git\n\tcd golang-github-urfave-cli\n\t[ -n \"$BRANCH\" ] && git checkout $BRANCH\n\tsed -i 's/golang-github-burntsushi-toml-dev/golang-toml-dev/; s/golang-gopkg-yaml.v2-dev/golang-yaml.v2-dev/' debian/control\n\tdch -D unstable -l~bpo~ \"Rebuild as backports\"\n\tgit add -u\n\tgit commit -m \"Patch to work with ubuntu xenial (16.04)\"\n\tcd -\nfi\n}\n\n# Build and install golang-github-urfave-cli-dev deb\nbuild_install_urfaveclidev() {\nif [ $BUILD_KCP -eq 1 ]; then\n\tBRANCH=$1\n\tgbp_build https://salsa.debian.org/go-team/packages/golang-github-urfave-cli.git $BRANCH\n\tsudo dpkg -i build-area/golang-github-urfave-cli-dev_*.deb\n\tsudo apt-get install -fy\nfi\n}\n\n# Build and install golang-github-golang-snappy deb\nbuild_install_snappydev() {\nif [ $BUILD_KCP -eq 1 ]; then\n\tBRANCH=$1\n\tgbp_build https://salsa.debian.org/go-team/packages/golang-github-golang-snappy.git $BRANCH\n\tsudo dpkg -i golang-github-golang-snappy-dev_*.deb\n\tsudo apt-get install -fy\nfi\n}\n\n# Build and install golang-github-xtaci-kcp deb\nbuild_install_kcpdev() {\nif [ $BUILD_KCP -eq 1 ]; then\n\tBRANCH=$1\n\tgbp_build https://salsa.debian.org/go-team/packages/golang-github-xtaci-kcp.git $BRANCH\n\tsudo dpkg -i golang-github-xtaci-kcp-dev_*.deb\n\tsudo apt-get install -fy\nfi\n}\n\n# Build and install golang-github-xtaci-smux deb\nbuild_install_smuxdev() {\nif [ $BUILD_KCP -eq 1 ]; then\n\tBRANCH=$1\n\tgbp_build https://salsa.debian.org/go-team/packages/golang-github-xtaci-smux.git $BRANCH\n\tsudo dpkg -i golang-github-xtaci-smux-dev_*.deb\n\tsudo apt-get install -fy\nfi\n}\n\n# Build and install kcptun deb\nbuild_install_kcptun() {\nif [ $BUILD_KCP -eq 1 ]; then\n\tBRANCH=$1\n\tgbp_build https://salsa.debian.org/go-team/packages/kcptun.git $BRANCH\n\tsudo dpkg -i kcptun_*.deb\n\tsudo apt-get install -fy\nfi\n}\n\nexport XZ_DEFAULTS=--memlimit=128MiB\n\nOSID=$(grep ^ID= /etc/os-release|cut -d= -f2)\nOSVER=$(lsb_release -cs)\nBUILD_KCP=0\nBUILD_LIB=0\nBUILD_BIN=0\n\ncase \"$1\" in\n--help|-h)\n\thelp_usage\n\t;;\nkcp)\n\tBUILD_KCP=1\n\t;;\nlib)\n\tBUILD_LIB=1\n\t;;\nbin)\n\tBUILD_BIN=1\n\t;;\nall|\"\")\n\tBUILD_LIB=1\n\tBUILD_BIN=1\n\t;;\n*)\n\techo Parameter error, exiting ...\n\texit\nesac\n\n# Exit if in a git repo\n[ -d .git ] && help_usage\n\ncase \"$OSVER\" in\njessie)\n\tBPO=\"debhelper libbloom-dev libsodium-dev\"\n\tBPOEXTRA=sloppy\n\t;;\nstretch)\n\tBPO=libbloom-dev\n\t;;\nxenial)\n\tBPO=debhelper\n\t;;\nesac\napt_init \"git-buildpackage pristine-tar equivs\" \"$BPO\" $BPOEXTRA\n\n[ $BUILD_KCP -eq 1 ] && case \"$OSVER\" in\nwheezy|precise|trusty)\n\techo Sorry, your system $OSID/$OSVER is not supported.\n\t;;\njessie)\n\tbuild_install_urfaveclidev\n\tbuild_install_reedsolomondev\n\tbuild_install_kcpdev\n\tbuild_install_smuxdev\n\tbuild_install_kcptun\n\t;;\nstretch|unstable|sid|yakkety|zesty)\n\tbuild_install_reedsolomondev\n\tbuild_install_kcpdev\n\tbuild_install_smuxdev\n\tbuild_install_kcptun\n\t;;\nxenial)\n\tbuild_install_dhgolang debian/jessie-backports\n\tbuild_install_reedsolomondev\n\tbuild_install_errorsdev\n\tpatch_urfaveclidev_xenial\n\tbuild_install_urfaveclidev\n\tbuild_install_snappydev debian/jessie-backports\n\tbuild_install_kcpdev\n\tbuild_install_smuxdev\n\tbuild_install_kcptun\n\t;;\nesac\n\n[ $BUILD_LIB -eq 1 -o $BUILD_BIN -eq 1 ] && case \"$OSVER\" in\nwheezy|precise)\n\techo Sorry, your system $OSID/$OSVER is not supported.\n\t;;\njessie|stretch|buster|testing|unstable|sid)\n\tbuild_install_sslibev\n\t;;\nartful|bionic)\n\tbuild_install_libbloom\n\tbuild_install_sslibev\n\tbuild_install_simpleobfs\n\t;;\nzesty)\n\tbuild_install_libsodium\n\tbuild_install_libbloom\n\tbuild_install_sslibev\n\tbuild_install_simpleobfs\n\t;;\nxenial|yakkety)\n\tbuild_install_libcork debian\n\tbuild_install_libcorkipset debian\n\tbuild_install_libsodium\n\tbuild_install_libbloom\n\tbuild_install_sslibev\n\tbuild_install_simpleobfs\n\t;;\ntrusty)\n\tbuild_install_libcork trusty\n\tbuild_install_libcorkipset trusty\n\tbuild_install_libmbedtls debian/jessie-backports\n\tbuild_install_libsodium\n\tbuild_install_libbloom trusty\n\tpatch_sslibev_dh9\n\tbuild_install_sslibev\n\tbuild_install_simpleobfs trusty\n\t;;\n*)\n\techo Your system $OSID/$OSVER is not supported yet.\n\techo Please report issue:\n\techo \"    https://github.com/shadowsocks/shadowsocks-libev/issues/new\"\n\t;;\nesac\n\napt_clean\n"
  },
  {
    "path": "scripts/chroot_build.sh",
    "content": "#!/bin/sh\n# Copyright 2018 Roger Shimizu <rosh@debian.org>\n#\n# This is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n\nset -e\n\nhelp_usage() {\ncat << EOT\n\nCall build_deb.sh script in a chrooted environment\nUsage:\n\tsudo $(basename $0) [--help|-h] [codename]\n\n\t--help|-h\tShow this usage.\n\t[code name]\tDebian/Ubuntu release codename\n\t\t\te.g. jessie/stretch/trusty/xenial\n\nEOT\nexit\n}\n\n# POSIX-compliant maint function recommend by devref\n# to check for the existence of a command\n# https://www.debian.org/doc/manuals/developers-reference/ch06.html#bpp-debian-maint-scripts\npathfind() {\n\tOLDIFS=\"$IFS\"\n\tIFS=:\n\tfor p in $PATH; do\n\t\tif [ -x \"$p/$*\" ]; then\n\t\tIFS=\"$OLDIFS\"\n\t\treturn 0\n\t\tfi\n\tdone\n\tIFS=\"$OLDIFS\"\n\treturn 1\n}\n\ncase \"$1\" in\nwheezy|precise)\n\techo Sorry, the system $1 is not supported.\n\t;;\njessie|stretch|buster|testing|unstable|sid)\n\tOSID=debian\n\tREPO=http://deb.debian.org/debian\n\t;;\ntrusty|yakkety|zesty|xenial|artful|bionic)\n\tOSID=ubuntu\n\tREPO=http://archive.ubuntu.com/ubuntu\n\t;;\n--help|-h|*)\n\thelp_usage\nesac\n\nif ! pathfind debootstrap; then\n\techo Please install debootstrap package.\n\texit 1\nfi\n\nOSVER=$1\nCHROOT=/tmp/${OSVER}-build-$(date +%Y%m%d%H%M)\nTIMESTAMP0=$(date)\n\nmkdir -p ${CHROOT}/etc\necho en_US.UTF-8 UTF-8 > ${CHROOT}/etc/locale.gen\nif ! debootstrap --variant=minbase --include=ca-certificates,git,sudo,wget,whiptail --exclude=upstart,systemd $OSVER $CHROOT $REPO; then\n\techo debootstrap failed. Please kindly check whether proper sudo or not.\n\texit 1\nfi\ncase \"$OSID\" in\ndebian)\n\techo deb $REPO ${OSVER} main > ${CHROOT}/etc/apt/sources.list\n\techo deb $REPO ${OSVER}-updates main >> ${CHROOT}/etc/apt/sources.list\n\techo deb $REPO-security ${OSVER}/updates main >> ${CHROOT}/etc/apt/sources.list\n\t;;\nubuntu)\n\techo deb $REPO $OSVER main universe > ${CHROOT}/etc/apt/sources.list\n\techo deb $REPO ${OSVER}-updates main universe >> ${CHROOT}/etc/apt/sources.list\n\techo deb $REPO ${OSVER}-security main universe >> ${CHROOT}/etc/apt/sources.list\n\t;;\nesac\n\ncat << EOL | chroot $CHROOT\napt-get purge -y udev\napt-get update\napt-get -fy install\napt-get -y upgrade\napt-get -y install --no-install-recommends lsb-release\n# dh_auto_test of mbedtls (faketime) depends on /dev/shm. https://bugs.debian.org/778462\nmkdir -p ~ /dev/shm\nmount tmpfs /dev/shm -t tmpfs\n\ndate > /TIMESTAMP1\ngit config --global user.email \"script@example.com\"\ngit config --global user.name \"build script\"\nif [ -n \"$http_proxy\" ]; then\n\tgit config --global proxy.http $http_proxy\n\techo Acquire::http::Proxy \\\"$http_proxy\\\"\\; > /etc/apt/apt.conf\n\texport http_proxy=$http_proxy\n\texport https_proxy=$https_proxy\n\texport no_proxy=$no_proxy\nfi\ncd /tmp\nwget https://raw.githubusercontent.com/shadowsocks/shadowsocks-libev/master/scripts/build_deb.sh\nchmod 755 build_deb.sh\n./build_deb.sh\ndate > /TIMESTAMP2\n./build_deb.sh kcp\numount /dev/shm\nEOL\n\nTIMESTAMP1=$(cat ${CHROOT}/TIMESTAMP1)\nTIMESTAMP2=$(cat ${CHROOT}/TIMESTAMP2)\nTIMESTAMP3=$(date)\n\nprintf \\\\n\"All built deb packages:\"\\\\n\nls -l ${CHROOT}/tmp/*.deb\necho\necho Start-Time: $TIMESTAMP0\necho ChrootDone: $TIMESTAMP1\necho SsDeb-Done: $TIMESTAMP2\necho \\ Kcp-Done : $TIMESTAMP3\n"
  },
  {
    "path": "scripts/code-format.bat",
    "content": "@echo off\n\nset root=%~dp0\nset source=%root%src\n\ngoto start\n\n:format\nset filelist=%1\nfor /r \"%filelist%\" %%f in (*) do (\n  if \"%%~xf\" equ \".h\" (\n    call :format_file %%f\n  ) else if \"%%~xf\" equ \".c\" (\n    call :format_file %%f\n  )\n)\ngoto end\n\n:format_file\nset f=%1\nif \"%~n1\" neq \"base64\" (\n  if \"%~n1\" neq \"json\" (\n    if \"%~n1\" neq \"uthash\" (\n      echo 'format file \"%f%\"'\n      uncrustify -c %root%\\.uncrustify.cfg -l C --replace --no-backup %f%\n      DEL %~dp1*.uncrustify >nul 2>nul\n    )\n  )\n)\ngoto end\n\n:start\ncall :format %source%\n\n:end\n"
  },
  {
    "path": "scripts/code-format.sh",
    "content": "#!/usr/bin/env bash\n\nroot=$(pwd)\nsource=\"$root\"/src\n\nfunction format() {\n  filelist=$(ls \"$1\")\n  pushd \"$1\"\n  for file in $filelist; do\n    if test -d \"$file\"; then\n      echo \"format directory $file\"\n      format \"$file\"\n    else\n      if ([ \"${file%%.*}\" != \"base64\" ] &&\n        [ \"${file%%.*}\" != \"json\" ] &&\n        [ \"${file%%.*}\" != \"uthash\" ]) &&\n        ([ \"${file##*.}\" = \"h\" ] || [ \"${file##*.}\" = \"c\" ]); then\n        echo \"format file $file\"\n        uncrustify -c \"$root\"/.uncrustify.cfg -l C --replace --no-backup \"$file\"\n        rm ./*.uncrustify >/dev/null 2>&1\n      fi\n    fi\n  done\n  popd\n}\n\nformat \"$source\"\n"
  },
  {
    "path": "scripts/git_archive.sh",
    "content": "#!/usr/bin/env bash\nset -e\n\narchive() {\n    export TARBALL_NAME=$1\n    export TARBALL_OUTDIR=$2\n\n    # archive this repo\n    cd \"$(git rev-parse --show-toplevel)\"\n    git archive HEAD --format=tar --prefix=\"${TARBALL_NAME}/\" \\\n        -o \"${TARBALL_OUTDIR}/${TARBALL_NAME}.tar\"\n    # archive submodules\n    git submodule update --init\n    git submodule foreach --quiet 'git archive HEAD --format=tar \\\n            --prefix=\"${TARBALL_NAME}/${path}/\" \\\n            -o \"${TARBALL_OUTDIR}/${TARBALL_NAME}-submodule-${path}-${sha1}.tar\"\n        tar -n --concatenate --file=\"${TARBALL_OUTDIR}/${TARBALL_NAME}.tar\" \\\n            \"${TARBALL_OUTDIR}/${TARBALL_NAME}-submodule-${path}-${sha1}.tar\"'\n    gzip -c \"${TARBALL_OUTDIR}/${TARBALL_NAME}.tar\" > \"${TARBALL_OUTDIR}/${TARBALL_NAME}.tar.gz\"\n\n    # clean-up\n    git submodule foreach --quiet 'rm ${TARBALL_OUTDIR}/${TARBALL_NAME}-submodule-${path}-${sha1}.tar'\n    rm \"${TARBALL_OUTDIR}/${TARBALL_NAME}.tar\"\n}\n\nTARGET_TARBALL_NAME=shadowsocks-libev\nTARGET_TARBALL_DIR=$(git rev-parse --show-toplevel)\n\nwhile getopts \"n:o:\" opt\ndo\n    case ${opt} in\n        o)\n            TARGET_TARBALL_DIR=$(readlink -f -- $OPTARG)\n            ;;\n        n)\n            TARGET_TARBALL_NAME=$OPTARG\n            ;;\n        \\?)\n            exit 1\n            ;;\n    esac\ndone\n\narchive \"${TARGET_TARBALL_NAME}\" \"${TARGET_TARBALL_DIR}\"\n"
  },
  {
    "path": "scripts/git_version.sh",
    "content": "#!/usr/bin/env bash\nset -e\n\n# determine version and release number\nGIT_DESCRIBE=$(git describe --tags --match 'v*' --long)\n# GIT_DESCRIBE is like v3.0.3-11-g1e3f35c-dirty\nif [[ ! \"$GIT_DESCRIBE\" =~ ^v([^-]+)-([0-9]+)-g([0-9a-f]+)$ ]]; then\n    >&2 echo 'ERROR - unrecognized `git describe` output: '\"$GIT_DESCRIBE\"\n    exit 1\nfi\n\nversion=${BASH_REMATCH[1]}\ncommits=${BASH_REMATCH[2]}\nshort_hash=${BASH_REMATCH[3]}\n\nrelease=1\nif [ \"${commits}\" -gt 0 ] ; then\n    release+=.${commits}.git${short_hash}\nfi\n\necho \"${version} ${release}\"\n"
  },
  {
    "path": "scripts/iperf.sh",
    "content": "#!/bin/bash\n\nnumber=$1\nmethod=$2\n\nss-tunnel -k test -m $method -l 8387 -L 127.0.0.1:8388 -s 127.0.0.1 -p 8389 &\nss_tunnel_pid=$!\nss-server -k test -m $method -s 127.0.0.1 -p 8389 &\nss_server_pid=$!\n\niperf -s -p 8388 &\niperf_pid=$!\n\nsleep 1\n\niperf -c 127.0.0.1 -p 8387 -n $number\n\n# Wait for iperf server to receive all data.\n# One second should be enough in most cases.\nsleep 1\n\nkill $ss_tunnel_pid\nkill $ss_server_pid\nkill $iperf_pid\n\nsleep 1\necho \"Test Finished\"\n"
  },
  {
    "path": "scripts/ss-setup.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\n\n###############################################################################\n# ss-setup -- Interactive TUI for shadowsocks-libev server/client setup\n#\n# Requires: whiptail or dialog, openssl (optional), curl (for plugin install)\n# Usage:    sudo ss-setup          (full server setup + service management)\n#           ss-setup               (config generation only, no service install)\n###############################################################################\n\nreadonly SS_SETUP_VERSION=\"1.0.0\"\nreadonly CONFIG_DIR=\"/etc/shadowsocks-libev\"\nreadonly SYSTEMD_UNIT_DIR=\"/etc/systemd/system\"\nreadonly SYSTEMD_TEMPLATE=\"shadowsocks-libev-server@.service\"\n\n# AEAD ciphers supported by shadowsocks-libev (from src/aead.c)\nreadonly AEAD_CIPHERS=(\n    \"chacha20-ietf-poly1305\"\n    \"aes-256-gcm\"\n    \"aes-192-gcm\"\n    \"aes-128-gcm\"\n    \"xchacha20-ietf-poly1305\"\n)\n\n# Known SIP003 plugins and their GitHub repos\n# Using a function instead of associative array for bash 3.x compatibility\nplugin_repo() {\n    case \"$1\" in\n        simple-obfs)   echo \"shadowsocks/simple-obfs\" ;;\n        v2ray-plugin)  echo \"shadowsocks/v2ray-plugin\" ;;\n        xray-plugin)   echo \"teddysun/xray-plugin\" ;;\n        kcptun)        echo \"xtaci/kcptun\" ;;\n        *)             echo \"\" ;;\n    esac\n}\n\nreadonly KNOWN_PLUGINS=(\"simple-obfs\" \"v2ray-plugin\" \"xray-plugin\" \"kcptun\")\n\n# Globals set by the setup flows\nTUI_BACKEND=\"\"\nTMPDIR_CLEANUP=\"\"\n\n# Server config globals\nCFG_SERVER=\"0.0.0.0\"\nCFG_SERVER_PORT=\"8388\"\nCFG_METHOD=\"chacha20-ietf-poly1305\"\nCFG_PASSWORD=\"\"\nCFG_TIMEOUT=\"300\"\nCFG_MODE=\"tcp_and_udp\"\nCFG_FAST_OPEN=\"false\"\nCFG_PLUGIN=\"\"\nCFG_PLUGIN_OPTS=\"\"\nCFG_INSTANCE_NAME=\"config\"\n\n# Client config globals\nCFG_CLIENT_SERVER=\"\"\nCFG_CLIENT_SERVER_PORT=\"8388\"\nCFG_CLIENT_LOCAL_PORT=\"1080\"\nCFG_CLIENT_METHOD=\"chacha20-ietf-poly1305\"\nCFG_CLIENT_PASSWORD=\"\"\nCFG_CLIENT_PLUGIN=\"\"\nCFG_CLIENT_PLUGIN_OPTS=\"\"\nCFG_CLIENT_OUTPUT=\"\"\n\n###############################################################################\n# Cleanup\n###############################################################################\n\ncleanup() {\n    if [[ -n \"${TMPDIR_CLEANUP}\" && -d \"${TMPDIR_CLEANUP}\" ]]; then\n        rm -rf \"${TMPDIR_CLEANUP}\"\n    fi\n}\n# Only set trap when executed directly (not when sourced for testing)\nif [[ \"${BASH_SOURCE[0]}\" == \"$0\" ]]; then\n    trap cleanup EXIT\nfi\n\n###############################################################################\n# TUI Backend Detection & Wrappers\n###############################################################################\n\ndetect_tui_backend() {\n    if command -v whiptail >/dev/null 2>&1; then\n        TUI_BACKEND=\"whiptail\"\n    elif command -v dialog >/dev/null 2>&1; then\n        TUI_BACKEND=\"dialog\"\n    else\n        echo \"Error: neither whiptail nor dialog found.\" >&2\n        echo \"Install one of them:\" >&2\n        echo \"  Debian/Ubuntu: sudo apt install whiptail\" >&2\n        echo \"  RHEL/Fedora:   sudo dnf install newt\" >&2\n        echo \"  Arch:          sudo pacman -S libnewt\" >&2\n        exit 1\n    fi\n}\n\n# tui_msgbox title message\ntui_msgbox() {\n    local title=\"$1\" msg=\"$2\"\n    $TUI_BACKEND --title \"$title\" --msgbox \"$msg\" 20 70\n}\n\n# tui_yesno title message → exit code 0=yes 1=no\ntui_yesno() {\n    local title=\"$1\" msg=\"$2\"\n    if $TUI_BACKEND --title \"$title\" --yesno \"$msg\" 12 70; then\n        return 0\n    else\n        return 1\n    fi\n}\n\n# tui_inputbox title message default → prints value\ntui_inputbox() {\n    local title=\"$1\" msg=\"$2\" default=\"${3:-}\"\n    local result\n    result=$($TUI_BACKEND --title \"$title\" --inputbox \"$msg\" 10 70 \"$default\" 3>&1 1>&2 2>&3) || return $?\n    echo \"$result\"\n}\n\n# tui_passwordbox title message → prints value\ntui_passwordbox() {\n    local title=\"$1\" msg=\"$2\"\n    local result\n    result=$($TUI_BACKEND --title \"$title\" --passwordbox \"$msg\" 10 70 3>&1 1>&2 2>&3) || return $?\n    echo \"$result\"\n}\n\n# tui_menu title message tag1 item1 tag2 item2 ... → prints selected tag\ntui_menu() {\n    local title=\"$1\" msg=\"$2\"\n    shift 2\n    local items=(\"$@\")\n    local count=$(( ${#items[@]} / 2 ))\n    local result\n    result=$($TUI_BACKEND --title \"$title\" --menu \"$msg\" 20 70 \"$count\" \"${items[@]}\" 3>&1 1>&2 2>&3) || return $?\n    echo \"$result\"\n}\n\n# tui_radiolist title message tag1 item1 status1 ... → prints selected tag\ntui_radiolist() {\n    local title=\"$1\" msg=\"$2\"\n    shift 2\n    local items=(\"$@\")\n    local count=$(( ${#items[@]} / 3 ))\n    local result\n    result=$($TUI_BACKEND --title \"$title\" --radiolist \"$msg\" 20 70 \"$count\" \"${items[@]}\" 3>&1 1>&2 2>&3) || return $?\n    echo \"$result\"\n}\n\n###############################################################################\n# Utility Functions\n###############################################################################\n\ncheck_root() {\n    if [[ $EUID -ne 0 ]]; then\n        tui_msgbox \"Notice\" \"Not running as root.\\n\\nYou can still generate config files, but service installation and plugin management will be skipped.\\n\\nRe-run with sudo for full functionality.\"\n        return 1\n    fi\n    return 0\n}\n\nis_root() {\n    [[ $EUID -eq 0 ]]\n}\n\nvalidate_port() {\n    local port=\"$1\"\n    if [[ \"$port\" =~ ^[0-9]+$ ]] && (( port >= 1 && port <= 65535 )); then\n        return 0\n    fi\n    return 1\n}\n\nvalidate_instance_name() {\n    local name=\"$1\"\n    if [[ \"$name\" =~ ^[a-zA-Z0-9_-]+$ ]]; then\n        return 0\n    fi\n    return 1\n}\n\ngenerate_password() {\n    local len=\"${1:-32}\"\n    if command -v openssl >/dev/null 2>&1; then\n        openssl rand -base64 \"$len\" | tr -d '\\n'\n    else\n        head -c \"$len\" /dev/urandom | base64 | tr -d '\\n'\n    fi\n}\n\ngenerate_random_port() {\n    local port\n    if [[ -r /dev/urandom ]]; then\n        port=$(( ($(od -An -tu2 -N2 /dev/urandom | tr -d ' ') % 55001) + 10000 ))\n    else\n        port=$(( (RANDOM % 55001) + 10000 ))\n    fi\n    echo \"$port\"\n}\n\njson_escape() {\n    local str=\"$1\"\n    str=\"${str//\\\\/\\\\\\\\}\"\n    str=\"${str//\\\"/\\\\\\\"}\"\n    str=\"${str//$'\\n'/\\\\n}\"\n    str=\"${str//$'\\r'/\\\\r}\"\n    str=\"${str//$'\\t'/\\\\t}\"\n    echo -n \"$str\"\n}\n\nurlencode() {\n    local str=\"$1\"\n    local encoded=\"\"\n    local i c\n    for (( i = 0; i < ${#str}; i++ )); do\n        c=\"${str:$i:1}\"\n        case \"$c\" in\n            [a-zA-Z0-9.~_-]) encoded+=\"$c\" ;;\n            *) encoded+=$(printf '%%%02X' \"'$c\") ;;\n        esac\n    done\n    echo -n \"$encoded\"\n}\n\n# Generate SIP002 ss:// URI\n# ss://BASE64URL(method:password)@host:port[/?plugin=URLENCODE(plugin;opts)]\ngenerate_ss_uri() {\n    local method=\"$1\" password=\"$2\" server=\"$3\" port=\"$4\"\n    local plugin=\"${5:-}\" plugin_opts=\"${6:-}\"\n\n    local userinfo\n    userinfo=$(echo -n \"${method}:${password}\" | base64 | tr -d '\\n' | tr '+/' '-_' | tr -d '=')\n\n    local uri=\"ss://${userinfo}@${server}:${port}\"\n\n    if [[ -n \"$plugin\" ]]; then\n        local plugin_str=\"$plugin\"\n        if [[ -n \"$plugin_opts\" ]]; then\n            plugin_str=\"${plugin};${plugin_opts}\"\n        fi\n        uri=\"${uri}/?plugin=$(urlencode \"$plugin_str\")\"\n    fi\n\n    echo \"$uri\"\n}\n\n# Write JSON config from CFG_* globals (server mode)\n# Produces valid JSON with no trailing commas; booleans unquoted\nwrite_json_config() {\n    local outfile=\"$1\"\n    local fast_open_val=\"false\"\n    [[ \"$CFG_FAST_OPEN\" == \"true\" ]] && fast_open_val=\"true\"\n\n    {\n        printf '{\\n'\n        printf '    \"server\": \"%s\",\\n' \"$(json_escape \"$CFG_SERVER\")\"\n        printf '    \"server_port\": %s,\\n' \"$CFG_SERVER_PORT\"\n        printf '    \"password\": \"%s\",\\n' \"$(json_escape \"$CFG_PASSWORD\")\"\n        printf '    \"timeout\": %s,\\n' \"$CFG_TIMEOUT\"\n        printf '    \"method\": \"%s\",\\n' \"$(json_escape \"$CFG_METHOD\")\"\n        printf '    \"mode\": \"%s\",\\n' \"$(json_escape \"$CFG_MODE\")\"\n        if [[ -n \"$CFG_PLUGIN\" ]]; then\n            printf '    \"fast_open\": %s,\\n' \"$fast_open_val\"\n            printf '    \"plugin\": \"%s\"' \"$(json_escape \"$CFG_PLUGIN\")\"\n            if [[ -n \"$CFG_PLUGIN_OPTS\" ]]; then\n                printf ',\\n'\n                printf '    \"plugin_opts\": \"%s\"' \"$(json_escape \"$CFG_PLUGIN_OPTS\")\"\n            fi\n        else\n            printf '    \"fast_open\": %s' \"$fast_open_val\"\n        fi\n        printf '\\n}\\n'\n    } > \"$outfile\"\n}\n\n# Write JSON config for client mode\nwrite_client_json_config() {\n    local outfile=\"$1\"\n\n    {\n        printf '{\\n'\n        printf '    \"server\": \"%s\",\\n' \"$(json_escape \"$CFG_CLIENT_SERVER\")\"\n        printf '    \"server_port\": %s,\\n' \"$CFG_CLIENT_SERVER_PORT\"\n        printf '    \"local_address\": \"127.0.0.1\",\\n'\n        printf '    \"local_port\": %s,\\n' \"$CFG_CLIENT_LOCAL_PORT\"\n        printf '    \"password\": \"%s\",\\n' \"$(json_escape \"$CFG_CLIENT_PASSWORD\")\"\n        printf '    \"timeout\": 300,\\n'\n        printf '    \"method\": \"%s\",\\n' \"$(json_escape \"$CFG_CLIENT_METHOD\")\"\n        if [[ -n \"$CFG_CLIENT_PLUGIN\" ]]; then\n            printf '    \"mode\": \"tcp_and_udp\",\\n'\n            printf '    \"plugin\": \"%s\"' \"$(json_escape \"$CFG_CLIENT_PLUGIN\")\"\n            if [[ -n \"$CFG_CLIENT_PLUGIN_OPTS\" ]]; then\n                printf ',\\n'\n                printf '    \"plugin_opts\": \"%s\"' \"$(json_escape \"$CFG_CLIENT_PLUGIN_OPTS\")\"\n            fi\n        else\n            printf '    \"mode\": \"tcp_and_udp\"'\n        fi\n        printf '\\n}\\n'\n    } > \"$outfile\"\n}\n\n# Parse an existing config file and populate CFG_* globals\nparse_existing_config() {\n    local file=\"$1\"\n    local val\n\n    val=$(grep -o '\"server\"[[:space:]]*:[[:space:]]*\"[^\"]*\"' \"$file\" | head -1 | sed 's/.*:.*\"\\(.*\\)\"/\\1/') && [[ -n \"$val\" ]] && CFG_SERVER=\"$val\"\n    val=$(grep -o '\"server_port\"[[:space:]]*:[[:space:]]*[0-9]*' \"$file\" | head -1 | sed 's/.*:[[:space:]]*//')  && [[ -n \"$val\" ]] && CFG_SERVER_PORT=\"$val\"\n    val=$(grep -o '\"password\"[[:space:]]*:[[:space:]]*\"[^\"]*\"' \"$file\" | head -1 | sed 's/.*:.*\"\\(.*\\)\"/\\1/')    && [[ -n \"$val\" ]] && CFG_PASSWORD=\"$val\"\n    val=$(grep -o '\"method\"[[:space:]]*:[[:space:]]*\"[^\"]*\"' \"$file\" | head -1 | sed 's/.*:.*\"\\(.*\\)\"/\\1/')      && [[ -n \"$val\" ]] && CFG_METHOD=\"$val\"\n    val=$(grep -o '\"timeout\"[[:space:]]*:[[:space:]]*[0-9]*' \"$file\" | head -1 | sed 's/.*:[[:space:]]*//')       && [[ -n \"$val\" ]] && CFG_TIMEOUT=\"$val\"\n    val=$(grep -o '\"mode\"[[:space:]]*:[[:space:]]*\"[^\"]*\"' \"$file\" | head -1 | sed 's/.*:.*\"\\(.*\\)\"/\\1/')         && [[ -n \"$val\" ]] && CFG_MODE=\"$val\"\n    val=$(grep -o '\"fast_open\"[[:space:]]*:[[:space:]]*[a-z]*' \"$file\" | head -1 | sed 's/.*:[[:space:]]*//')     && [[ -n \"$val\" ]] && CFG_FAST_OPEN=\"$val\"\n    val=$(grep -o '\"plugin\"[[:space:]]*:[[:space:]]*\"[^\"]*\"' \"$file\" | head -1 | sed 's/.*:.*\"\\(.*\\)\"/\\1/')       && [[ -n \"$val\" ]] && CFG_PLUGIN=\"$val\"\n    val=$(grep -o '\"plugin_opts\"[[:space:]]*:[[:space:]]*\"[^\"]*\"' \"$file\" | head -1 | sed 's/.*:.*\"\\(.*\\)\"/\\1/')  && [[ -n \"$val\" ]] && CFG_PLUGIN_OPTS=\"$val\"\n\n    return 0\n}\n\ndetect_arch() {\n    local arch\n    arch=$(uname -m)\n    case \"$arch\" in\n        x86_64|amd64)  echo \"amd64\" ;;\n        aarch64|arm64) echo \"arm64\" ;;\n        armv7*|armhf)  echo \"armv7\" ;;\n        i686|i386)     echo \"386\" ;;\n        *)             echo \"$arch\" ;;\n    esac\n}\n\ndetect_os() {\n    local os\n    os=$(uname -s | tr '[:upper:]' '[:lower:]')\n    case \"$os\" in\n        linux*)  echo \"linux\" ;;\n        darwin*) echo \"darwin\" ;;\n        *)       echo \"$os\" ;;\n    esac\n}\n\ndetect_distro() {\n    if [[ -f /etc/os-release ]]; then\n        # shellcheck disable=SC1091\n        . /etc/os-release\n        echo \"${ID:-unknown}\"\n    elif command -v lsb_release >/dev/null 2>&1; then\n        lsb_release -si | tr '[:upper:]' '[:lower:]'\n    else\n        echo \"unknown\"\n    fi\n}\n\nhas_systemd() {\n    command -v systemctl >/dev/null 2>&1 && [[ -d /run/systemd/system ]]\n}\n\nsystemd_version() {\n    local ver\n    ver=$(systemctl --version 2>/dev/null | head -1 | grep -oE '[0-9]+' | head -1) || ver=\"0\"\n    echo \"$ver\"\n}\n\ncheck_port_in_use() {\n    local port=\"$1\"\n    if command -v ss >/dev/null 2>&1; then\n        ss -tlnp 2>/dev/null | grep -q \":${port} \" && return 0\n    elif command -v netstat >/dev/null 2>&1; then\n        netstat -tlnp 2>/dev/null | grep -q \":${port} \" && return 0\n    fi\n    return 1\n}\n\nfind_installed_plugins() {\n    local plugins=()\n    local p\n    for p in \"${KNOWN_PLUGINS[@]}\"; do\n        if command -v \"$p\" >/dev/null 2>&1; then\n            plugins+=(\"$p\")\n        fi\n    done\n    # Also check obfs-local (simple-obfs installs as obfs-local/obfs-server)\n    if command -v obfs-local >/dev/null 2>&1; then\n        local found=0\n        for p in \"${plugins[@]}\"; do\n            [[ \"$p\" == \"simple-obfs\" ]] && found=1\n        done\n        [[ $found -eq 0 ]] && plugins+=(\"obfs-local\")\n    fi\n    echo \"${plugins[*]}\"\n}\n\n###############################################################################\n# Server Setup Flow\n###############################################################################\n\nserver_ask_listen_address() {\n    local addr\n    while true; do\n        addr=$(tui_inputbox \"Listen Address\" \"Enter the server listen address:\" \"$CFG_SERVER\") || return 1\n        if [[ -n \"$addr\" ]]; then\n            CFG_SERVER=\"$addr\"\n            return 0\n        fi\n        tui_msgbox \"Error\" \"Address cannot be empty.\"\n    done\n}\n\nserver_ask_port() {\n    local choice\n    choice=$(tui_menu \"Server Port\" \"Choose how to set the server port:\" \\\n        \"manual\" \"Enter port manually (default: ${CFG_SERVER_PORT})\" \\\n        \"random\" \"Generate a random high port\") || return 1\n\n    if [[ \"$choice\" == \"random\" ]]; then\n        CFG_SERVER_PORT=$(generate_random_port)\n        tui_msgbox \"Random Port\" \"Selected port: ${CFG_SERVER_PORT}\"\n        return 0\n    fi\n\n    local port\n    while true; do\n        port=$(tui_inputbox \"Server Port\" \"Enter the server port (1-65535):\" \"$CFG_SERVER_PORT\") || return 1\n        if validate_port \"$port\"; then\n            if check_port_in_use \"$port\"; then\n                if ! tui_yesno \"Port In Use\" \"Port ${port} appears to be in use.\\n\\nContinue anyway?\"; then\n                    continue\n                fi\n            fi\n            CFG_SERVER_PORT=\"$port\"\n            return 0\n        fi\n        tui_msgbox \"Error\" \"Invalid port number. Must be 1-65535.\"\n    done\n}\n\nserver_ask_method() {\n    local items=()\n    local cipher\n    for cipher in \"${AEAD_CIPHERS[@]}\"; do\n        if [[ \"$cipher\" == \"$CFG_METHOD\" ]]; then\n            items+=(\"$cipher\" \"\" \"ON\")\n        else\n            items+=(\"$cipher\" \"\" \"OFF\")\n        fi\n    done\n\n    local method\n    method=$(tui_radiolist \"Encryption Method\" \"Select the AEAD cipher to use:\" \"${items[@]}\") || return 1\n    CFG_METHOD=\"$method\"\n}\n\nserver_ask_password() {\n    if tui_yesno \"Password\" \"Auto-generate a secure random password?\\n\\n(Select No to enter manually)\"; then\n        CFG_PASSWORD=$(generate_password 32)\n        tui_msgbox \"Generated Password\" \"Password (save this!):\\n\\n${CFG_PASSWORD}\"\n        return 0\n    fi\n\n    local pass1 pass2\n    while true; do\n        pass1=$(tui_passwordbox \"Password\" \"Enter the password:\") || return 1\n        if [[ -z \"$pass1\" ]]; then\n            tui_msgbox \"Error\" \"Password cannot be empty.\"\n            continue\n        fi\n        pass2=$(tui_passwordbox \"Confirm Password\" \"Confirm the password:\") || return 1\n        if [[ \"$pass1\" == \"$pass2\" ]]; then\n            CFG_PASSWORD=\"$pass1\"\n            return 0\n        fi\n        tui_msgbox \"Error\" \"Passwords do not match. Try again.\"\n    done\n}\n\nserver_ask_timeout() {\n    local timeout\n    while true; do\n        timeout=$(tui_inputbox \"Timeout\" \"Connection timeout in seconds:\" \"$CFG_TIMEOUT\") || return 1\n        if [[ \"$timeout\" =~ ^[0-9]+$ ]] && (( timeout > 0 )); then\n            CFG_TIMEOUT=\"$timeout\"\n            return 0\n        fi\n        tui_msgbox \"Error\" \"Timeout must be a positive integer.\"\n    done\n}\n\nserver_ask_mode() {\n    local items=()\n    local modes=(\"tcp_only\" \"tcp_and_udp\" \"udp_only\")\n    local m\n    for m in \"${modes[@]}\"; do\n        if [[ \"$m\" == \"$CFG_MODE\" ]]; then\n            items+=(\"$m\" \"\" \"ON\")\n        else\n            items+=(\"$m\" \"\" \"OFF\")\n        fi\n    done\n\n    local mode\n    mode=$(tui_radiolist \"Network Mode\" \"Select the network mode:\" \"${items[@]}\") || return 1\n    CFG_MODE=\"$mode\"\n}\n\nserver_ask_fast_open() {\n    # Check if TCP Fast Open is available (Linux only)\n    if [[ -f /proc/sys/net/ipv4/tcp_fastopen ]]; then\n        local tfo_val\n        tfo_val=$(cat /proc/sys/net/ipv4/tcp_fastopen 2>/dev/null) || tfo_val=\"0\"\n        if (( tfo_val >= 2 )); then\n            CFG_FAST_OPEN=\"true\"\n        fi\n        if tui_yesno \"TCP Fast Open\" \"Enable TCP Fast Open?\\n\\n(Current kernel setting: ${tfo_val})\\nRequires kernel support and sysctl net.ipv4.tcp_fastopen >= 2 for server.\"; then\n            CFG_FAST_OPEN=\"true\"\n        else\n            CFG_FAST_OPEN=\"false\"\n        fi\n    else\n        CFG_FAST_OPEN=\"false\"\n        tui_msgbox \"TCP Fast Open\" \"TCP Fast Open is not available on this system.\\nSetting to disabled.\"\n    fi\n}\n\nserver_ask_plugin() {\n    local installed\n    installed=$(find_installed_plugins)\n\n    local items=(\"none\" \"No plugin\")\n    local p\n    for p in $installed; do\n        items+=(\"$p\" \"$(command -v \"$p\" 2>/dev/null || echo \"$p\")\")\n    done\n    items+=(\"custom\" \"Enter custom plugin path\")\n\n    local choice\n    choice=$(tui_menu \"SIP003 Plugin\" \"Select a plugin (optional):\" \"${items[@]}\") || return 1\n\n    if [[ \"$choice\" == \"none\" ]]; then\n        CFG_PLUGIN=\"\"\n        CFG_PLUGIN_OPTS=\"\"\n        return 0\n    fi\n\n    if [[ \"$choice\" == \"custom\" ]]; then\n        local plugin_path\n        plugin_path=$(tui_inputbox \"Custom Plugin\" \"Enter the plugin binary name or full path:\" \"\") || return 1\n        if [[ -z \"$plugin_path\" ]]; then\n            CFG_PLUGIN=\"\"\n            CFG_PLUGIN_OPTS=\"\"\n            return 0\n        fi\n        CFG_PLUGIN=\"$plugin_path\"\n    else\n        CFG_PLUGIN=\"$choice\"\n    fi\n\n    local opts\n    opts=$(tui_inputbox \"Plugin Options\" \"Enter plugin options (or leave empty):\" \"$CFG_PLUGIN_OPTS\") || return 1\n    CFG_PLUGIN_OPTS=\"$opts\"\n}\n\nserver_ask_instance_name() {\n    local name\n    while true; do\n        name=$(tui_inputbox \"Instance Name\" \"Enter a name for this config instance.\\nThe config will be saved as ${CONFIG_DIR}/<name>.json\" \"$CFG_INSTANCE_NAME\") || return 1\n        if ! validate_instance_name \"$name\"; then\n            tui_msgbox \"Error\" \"Invalid name. Use only letters, numbers, hyphens, and underscores.\"\n            continue\n        fi\n        if [[ -f \"${CONFIG_DIR}/${name}.json\" ]]; then\n            local action\n            action=$(tui_menu \"Config Exists\" \"Config '${name}.json' already exists:\" \\\n                \"overwrite\" \"Overwrite the existing config\" \\\n                \"edit\" \"Load and edit the existing config\" \\\n                \"rename\" \"Choose a different name\") || return 1\n            case \"$action\" in\n                overwrite)\n                    CFG_INSTANCE_NAME=\"$name\"\n                    return 0\n                    ;;\n                edit)\n                    parse_existing_config \"${CONFIG_DIR}/${name}.json\"\n                    CFG_INSTANCE_NAME=\"$name\"\n                    return 2  # signal to restart setup with loaded values\n                    ;;\n                rename)\n                    continue\n                    ;;\n            esac\n        else\n            CFG_INSTANCE_NAME=\"$name\"\n            return 0\n        fi\n    done\n}\n\nserver_generate_config() {\n    local config_file=\"${CONFIG_DIR}/${CFG_INSTANCE_NAME}.json\"\n\n    if is_root; then\n        mkdir -p \"$CONFIG_DIR\"\n        write_json_config \"$config_file\"\n        chmod 640 \"$config_file\"\n    else\n        # Non-root: write to current directory\n        config_file=\"${CFG_INSTANCE_NAME}.json\"\n        write_json_config \"$config_file\"\n    fi\n\n    echo \"$config_file\"\n}\n\nserver_install_systemd_template() {\n    if ! has_systemd; then\n        return 1\n    fi\n\n    local template_path=\"${SYSTEMD_UNIT_DIR}/${SYSTEMD_TEMPLATE}\"\n\n    # Only install if missing\n    if [[ -f \"$template_path\" ]]; then\n        return 0\n    fi\n\n    local ss_server_path\n    ss_server_path=$(command -v ss-server 2>/dev/null) || ss_server_path=\"/usr/local/bin/ss-server\"\n\n    local sd_ver\n    sd_ver=$(systemd_version)\n\n    if (( sd_ver >= 232 )); then\n        cat > \"$template_path\" <<UNIT\n[Unit]\nDescription=Shadowsocks-Libev Custom Server Service for %I\nDocumentation=man:ss-server(1)\nAfter=network-online.target\n\n[Service]\nType=simple\nCapabilityBoundingSet=CAP_NET_BIND_SERVICE\nAmbientCapabilities=CAP_NET_BIND_SERVICE\nDynamicUser=true\nLimitNOFILE=32768\nExecStart=${ss_server_path} -c /etc/shadowsocks-libev/%i.json\n\n[Install]\nWantedBy=multi-user.target\nUNIT\n    else\n        cat > \"$template_path\" <<UNIT\n[Unit]\nDescription=Shadowsocks-Libev Custom Server Service for %I\nDocumentation=man:ss-server(1)\nAfter=network-online.target\n\n[Service]\nType=simple\nCapabilityBoundingSet=CAP_NET_BIND_SERVICE\nUser=nobody\nGroup=nogroup\nLimitNOFILE=32768\nExecStart=${ss_server_path} -c /etc/shadowsocks-libev/%i.json\n\n[Install]\nWantedBy=multi-user.target\nUNIT\n    fi\n\n    systemctl daemon-reload\n}\n\nserver_install_service() {\n    local name=\"$1\"\n    local unit=\"shadowsocks-libev-server@${name}.service\"\n\n    server_install_systemd_template || {\n        tui_msgbox \"No systemd\" \"systemd not detected. Skipping service installation.\\n\\nStart manually:\\n  ss-server -c ${CONFIG_DIR}/${name}.json\"\n        return 1\n    }\n\n    systemctl enable \"$unit\" 2>/dev/null\n    systemctl restart \"$unit\" 2>/dev/null\n\n    if systemctl is-active --quiet \"$unit\"; then\n        return 0\n    else\n        return 1\n    fi\n}\n\nserver_show_summary() {\n    local config_file=\"$1\"\n    local uri\n    uri=$(generate_ss_uri \"$CFG_METHOD\" \"$CFG_PASSWORD\" \"$CFG_SERVER\" \"$CFG_SERVER_PORT\" \"$CFG_PLUGIN\" \"$CFG_PLUGIN_OPTS\")\n\n    local service_status=\"(not installed)\"\n    if is_root && has_systemd; then\n        local unit=\"shadowsocks-libev-server@${CFG_INSTANCE_NAME}.service\"\n        if systemctl is-active --quiet \"$unit\" 2>/dev/null; then\n            service_status=\"active (running)\"\n        else\n            service_status=\"inactive or failed\"\n        fi\n    fi\n\n    local summary=\"\"\n    summary+=\"Config file: ${config_file}\\n\"\n    summary+=\"\\n\"\n    summary+=\"Server:    ${CFG_SERVER}:${CFG_SERVER_PORT}\\n\"\n    summary+=\"Method:    ${CFG_METHOD}\\n\"\n    summary+=\"Password:  ${CFG_PASSWORD}\\n\"\n    summary+=\"Mode:      ${CFG_MODE}\\n\"\n    summary+=\"Fast Open: ${CFG_FAST_OPEN}\\n\"\n    if [[ -n \"$CFG_PLUGIN\" ]]; then\n        summary+=\"Plugin:    ${CFG_PLUGIN}\\n\"\n        [[ -n \"$CFG_PLUGIN_OPTS\" ]] && summary+=\"Opts:      ${CFG_PLUGIN_OPTS}\\n\"\n    fi\n    summary+=\"Service:   ${service_status}\\n\"\n    summary+=\"\\n\"\n    summary+=\"ss:// URI (for client import):\\n\"\n    summary+=\"${uri}\\n\"\n\n    tui_msgbox \"Server Setup Complete\" \"$summary\"\n}\n\nserver_setup() {\n    while true; do\n        server_ask_instance_name\n        local rc=$?\n        if [[ $rc -eq 1 ]]; then\n            return  # user cancelled\n        fi\n        # rc=2 means config was loaded for editing, restart the flow\n        # rc=0 means proceed\n\n        server_ask_listen_address || return\n        server_ask_port || return\n        server_ask_method || return\n        server_ask_password || return\n        server_ask_timeout || return\n        server_ask_mode || return\n        server_ask_fast_open\n        server_ask_plugin || return\n\n        # Confirm before writing\n        local confirm_msg=\"\"\n        confirm_msg+=\"Server:    ${CFG_SERVER}:${CFG_SERVER_PORT}\\n\"\n        confirm_msg+=\"Method:    ${CFG_METHOD}\\n\"\n        confirm_msg+=\"Mode:      ${CFG_MODE}\\n\"\n        confirm_msg+=\"Fast Open: ${CFG_FAST_OPEN}\\n\"\n        confirm_msg+=\"Instance:  ${CFG_INSTANCE_NAME}\\n\"\n        [[ -n \"$CFG_PLUGIN\" ]] && confirm_msg+=\"Plugin:    ${CFG_PLUGIN}\\n\"\n\n        if ! tui_yesno \"Confirm\" \"Review your settings:\\n\\n${confirm_msg}\\nProceed?\"; then\n            if tui_yesno \"Restart\" \"Start over with new settings?\"; then\n                continue\n            fi\n            return\n        fi\n\n        break\n    done\n\n    # Generate config\n    local config_file\n    config_file=$(server_generate_config)\n\n    # Install systemd service if root\n    if is_root && has_systemd; then\n        if tui_yesno \"Systemd Service\" \"Install and start a systemd service for this instance?\"; then\n            if server_install_service \"$CFG_INSTANCE_NAME\"; then\n                tui_msgbox \"Service Started\" \"Service shadowsocks-libev-server@${CFG_INSTANCE_NAME} is now running.\"\n            else\n                tui_msgbox \"Service Error\" \"Service failed to start.\\n\\nCheck: journalctl -u shadowsocks-libev-server@${CFG_INSTANCE_NAME} -n 20\"\n            fi\n        fi\n    fi\n\n    # Show summary\n    server_show_summary \"$config_file\"\n}\n\n###############################################################################\n# Client Config Flow\n###############################################################################\n\nclient_ask_server_address() {\n    local addr\n    while true; do\n        addr=$(tui_inputbox \"Server Address\" \"Enter the remote ss-server address (IP or hostname):\" \"$CFG_CLIENT_SERVER\") || return 1\n        if [[ -n \"$addr\" ]]; then\n            CFG_CLIENT_SERVER=\"$addr\"\n            return 0\n        fi\n        tui_msgbox \"Error\" \"Server address cannot be empty.\"\n    done\n}\n\nclient_ask_server_port() {\n    local port\n    while true; do\n        port=$(tui_inputbox \"Server Port\" \"Enter the remote ss-server port:\" \"$CFG_CLIENT_SERVER_PORT\") || return 1\n        if validate_port \"$port\"; then\n            CFG_CLIENT_SERVER_PORT=\"$port\"\n            return 0\n        fi\n        tui_msgbox \"Error\" \"Invalid port number. Must be 1-65535.\"\n    done\n}\n\nclient_ask_local_port() {\n    local port\n    while true; do\n        port=$(tui_inputbox \"Local Port\" \"Enter the local SOCKS5 listen port:\" \"$CFG_CLIENT_LOCAL_PORT\") || return 1\n        if validate_port \"$port\"; then\n            CFG_CLIENT_LOCAL_PORT=\"$port\"\n            return 0\n        fi\n        tui_msgbox \"Error\" \"Invalid port number. Must be 1-65535.\"\n    done\n}\n\nclient_ask_method() {\n    local items=()\n    local cipher\n    for cipher in \"${AEAD_CIPHERS[@]}\"; do\n        if [[ \"$cipher\" == \"$CFG_CLIENT_METHOD\" ]]; then\n            items+=(\"$cipher\" \"\" \"ON\")\n        else\n            items+=(\"$cipher\" \"\" \"OFF\")\n        fi\n    done\n\n    local method\n    method=$(tui_radiolist \"Encryption Method\" \"Select the cipher (must match server):\" \"${items[@]}\") || return 1\n    CFG_CLIENT_METHOD=\"$method\"\n}\n\nclient_ask_password() {\n    local pass\n    while true; do\n        pass=$(tui_passwordbox \"Password\" \"Enter the password (must match server):\") || return 1\n        if [[ -n \"$pass\" ]]; then\n            CFG_CLIENT_PASSWORD=\"$pass\"\n            return 0\n        fi\n        tui_msgbox \"Error\" \"Password cannot be empty.\"\n    done\n}\n\nclient_ask_plugin() {\n    local installed\n    installed=$(find_installed_plugins)\n\n    local items=(\"none\" \"No plugin\")\n    local p\n    for p in $installed; do\n        items+=(\"$p\" \"$(command -v \"$p\" 2>/dev/null || echo \"$p\")\")\n    done\n    items+=(\"custom\" \"Enter custom plugin path\")\n\n    local choice\n    choice=$(tui_menu \"SIP003 Plugin\" \"Select a plugin (must match server):\" \"${items[@]}\") || return 1\n\n    if [[ \"$choice\" == \"none\" ]]; then\n        CFG_CLIENT_PLUGIN=\"\"\n        CFG_CLIENT_PLUGIN_OPTS=\"\"\n        return 0\n    fi\n\n    if [[ \"$choice\" == \"custom\" ]]; then\n        local plugin_path\n        plugin_path=$(tui_inputbox \"Custom Plugin\" \"Enter the plugin binary name or full path:\" \"\") || return 1\n        if [[ -z \"$plugin_path\" ]]; then\n            CFG_CLIENT_PLUGIN=\"\"\n            CFG_CLIENT_PLUGIN_OPTS=\"\"\n            return 0\n        fi\n        CFG_CLIENT_PLUGIN=\"$plugin_path\"\n    else\n        CFG_CLIENT_PLUGIN=\"$choice\"\n    fi\n\n    local opts\n    opts=$(tui_inputbox \"Plugin Options\" \"Enter plugin options (or leave empty):\" \"$CFG_CLIENT_PLUGIN_OPTS\") || return 1\n    CFG_CLIENT_PLUGIN_OPTS=\"$opts\"\n}\n\nclient_ask_output_path() {\n    local default_path\n    if is_root; then\n        default_path=\"${CONFIG_DIR}/client.json\"\n    else\n        default_path=\"${HOME}/ss-client.json\"\n    fi\n    [[ -n \"$CFG_CLIENT_OUTPUT\" ]] && default_path=\"$CFG_CLIENT_OUTPUT\"\n\n    local path\n    path=$(tui_inputbox \"Output Path\" \"Where to save the client config:\" \"$default_path\") || return 1\n    CFG_CLIENT_OUTPUT=\"$path\"\n}\n\nclient_generate_config() {\n    local outdir\n    outdir=$(dirname \"$CFG_CLIENT_OUTPUT\")\n    if [[ ! -d \"$outdir\" ]]; then\n        mkdir -p \"$outdir\" 2>/dev/null || {\n            tui_msgbox \"Error\" \"Cannot create directory: ${outdir}\"\n            return 1\n        }\n    fi\n    write_client_json_config \"$CFG_CLIENT_OUTPUT\"\n    chmod 640 \"$CFG_CLIENT_OUTPUT\" 2>/dev/null || true\n}\n\nclient_show_summary() {\n    local uri\n    uri=$(generate_ss_uri \"$CFG_CLIENT_METHOD\" \"$CFG_CLIENT_PASSWORD\" \"$CFG_CLIENT_SERVER\" \"$CFG_CLIENT_SERVER_PORT\" \"$CFG_CLIENT_PLUGIN\" \"$CFG_CLIENT_PLUGIN_OPTS\")\n\n    local summary=\"\"\n    summary+=\"Config file: ${CFG_CLIENT_OUTPUT}\\n\"\n    summary+=\"\\n\"\n    summary+=\"Server:     ${CFG_CLIENT_SERVER}:${CFG_CLIENT_SERVER_PORT}\\n\"\n    summary+=\"Local:      127.0.0.1:${CFG_CLIENT_LOCAL_PORT}\\n\"\n    summary+=\"Method:     ${CFG_CLIENT_METHOD}\\n\"\n    if [[ -n \"$CFG_CLIENT_PLUGIN\" ]]; then\n        summary+=\"Plugin:     ${CFG_CLIENT_PLUGIN}\\n\"\n        [[ -n \"$CFG_CLIENT_PLUGIN_OPTS\" ]] && summary+=\"Opts:       ${CFG_CLIENT_PLUGIN_OPTS}\\n\"\n    fi\n    summary+=\"\\n\"\n    summary+=\"ss:// URI:\\n${uri}\\n\"\n    summary+=\"\\n\"\n    summary+=\"Usage:\\n  ss-local -c ${CFG_CLIENT_OUTPUT}\\n\"\n\n    tui_msgbox \"Client Config Complete\" \"$summary\"\n}\n\nclient_setup() {\n    client_ask_server_address || return\n    client_ask_server_port || return\n    client_ask_local_port || return\n    client_ask_method || return\n    client_ask_password || return\n    client_ask_plugin || return\n    client_ask_output_path || return\n\n    # Confirm\n    local confirm_msg=\"\"\n    confirm_msg+=\"Server:  ${CFG_CLIENT_SERVER}:${CFG_CLIENT_SERVER_PORT}\\n\"\n    confirm_msg+=\"Local:   127.0.0.1:${CFG_CLIENT_LOCAL_PORT}\\n\"\n    confirm_msg+=\"Method:  ${CFG_CLIENT_METHOD}\\n\"\n    confirm_msg+=\"Output:  ${CFG_CLIENT_OUTPUT}\\n\"\n    [[ -n \"$CFG_CLIENT_PLUGIN\" ]] && confirm_msg+=\"Plugin:  ${CFG_CLIENT_PLUGIN}\\n\"\n\n    if ! tui_yesno \"Confirm\" \"Review your settings:\\n\\n${confirm_msg}\\nProceed?\"; then\n        return\n    fi\n\n    client_generate_config || return\n    client_show_summary\n}\n\n###############################################################################\n# Plugin Installation Flow\n###############################################################################\n\nplugin_download_github_release() {\n    local repo=\"$1\" binary_name=\"$2\"\n    local os arch api_url assets_json download_url asset_name\n\n    os=$(detect_os)\n    arch=$(detect_arch)\n\n    if ! command -v curl >/dev/null 2>&1; then\n        tui_msgbox \"Error\" \"curl is required for downloading plugins.\"\n        return 1\n    fi\n\n    api_url=\"https://api.github.com/repos/${repo}/releases/latest\"\n\n    tui_msgbox \"Downloading\" \"Fetching latest release info from:\\n${repo}\\n\\nPlease wait...\"\n\n    assets_json=$(curl -sS --connect-timeout 15 --max-time 30 \"$api_url\") || {\n        tui_msgbox \"Error\" \"Failed to fetch release info from GitHub.\\n\\nCheck your network connection.\"\n        return 1\n    }\n\n    # Find matching asset URL -- look for os and arch in filename\n    download_url=\"\"\n    # Try common naming patterns\n    local patterns=()\n    patterns+=(\"${os}-${arch}\")\n    patterns+=(\"${os}_${arch}\")\n    # Map arch names for different projects\n    case \"$arch\" in\n        amd64) patterns+=(\"${os}-amd64\" \"${os}_amd64\" \"${os}-x86_64\" \"${os}_x86_64\" \"linux-64\") ;;\n        arm64) patterns+=(\"${os}-arm64\" \"${os}_arm64\" \"${os}-aarch64\" \"${os}_aarch64\") ;;\n    esac\n\n    local p\n    for p in \"${patterns[@]}\"; do\n        download_url=$(echo \"$assets_json\" | grep -o '\"browser_download_url\"[[:space:]]*:[[:space:]]*\"[^\"]*'\"$p\"'[^\"]*\"' | head -1 | sed 's/.*\"\\(http[^\"]*\\)\".*/\\1/')\n        [[ -n \"$download_url\" ]] && break\n    done\n\n    if [[ -z \"$download_url\" ]]; then\n        tui_msgbox \"Error\" \"Could not find a matching release for ${os}-${arch}.\\n\\nYou may need to build from source or download manually.\"\n        return 1\n    fi\n\n    asset_name=$(basename \"$download_url\")\n\n    TMPDIR_CLEANUP=$(mktemp -d)\n    local tmpdir=\"$TMPDIR_CLEANUP\"\n\n    tui_msgbox \"Downloading\" \"Downloading:\\n${asset_name}\\n\\nThis may take a moment...\"\n\n    if ! curl -sSL --connect-timeout 15 --max-time 120 -o \"${tmpdir}/${asset_name}\" \"$download_url\"; then\n        tui_msgbox \"Error\" \"Download failed.\"\n        return 1\n    fi\n\n    # Extract based on file type\n    local extract_dir=\"${tmpdir}/extract\"\n    mkdir -p \"$extract_dir\"\n\n    case \"$asset_name\" in\n        *.tar.gz|*.tgz)\n            tar xzf \"${tmpdir}/${asset_name}\" -C \"$extract_dir\" || {\n                tui_msgbox \"Error\" \"Failed to extract archive.\"\n                return 1\n            }\n            ;;\n        *.zip)\n            unzip -q \"${tmpdir}/${asset_name}\" -d \"$extract_dir\" || {\n                tui_msgbox \"Error\" \"Failed to extract archive.\"\n                return 1\n            }\n            ;;\n        *)\n            # Assume it's the binary itself\n            cp \"${tmpdir}/${asset_name}\" \"${extract_dir}/${binary_name}\"\n            chmod +x \"${extract_dir}/${binary_name}\"\n            ;;\n    esac\n\n    # Find the binary\n    local found_binary=\"\"\n    found_binary=$(find \"$extract_dir\" -name \"$binary_name\" -type f 2>/dev/null | head -1)\n\n    # Some plugins have different names in the archive\n    if [[ -z \"$found_binary\" ]]; then\n        # Try finding any executable\n        found_binary=$(find \"$extract_dir\" -type f -executable 2>/dev/null | head -1)\n    fi\n    if [[ -z \"$found_binary\" ]]; then\n        found_binary=$(find \"$extract_dir\" -type f -name \"${binary_name}*\" 2>/dev/null | head -1)\n    fi\n\n    if [[ -z \"$found_binary\" ]]; then\n        tui_msgbox \"Error\" \"Could not find '${binary_name}' in the downloaded archive.\\n\\nContents of archive:\\n$(ls -la \"$extract_dir\" 2>/dev/null)\"\n        return 1\n    fi\n\n    chmod +x \"$found_binary\"\n    cp \"$found_binary\" \"/usr/local/bin/${binary_name}\"\n\n    if command -v \"$binary_name\" >/dev/null 2>&1; then\n        tui_msgbox \"Success\" \"${binary_name} installed to /usr/local/bin/${binary_name}\"\n        return 0\n    else\n        tui_msgbox \"Warning\" \"Installed to /usr/local/bin/${binary_name} but it was not found in PATH.\"\n        return 0\n    fi\n}\n\nplugin_install_simple_obfs() {\n    local distro\n    distro=$(detect_distro)\n\n    local method\n    method=$(tui_menu \"Install simple-obfs\" \"Choose installation method:\" \\\n        \"package\" \"Install via package manager (if available)\" \\\n        \"source\" \"Build from source (requires git, build tools)\") || return 1\n\n    if [[ \"$method\" == \"package\" ]]; then\n        case \"$distro\" in\n            ubuntu|debian)\n                apt-get update && apt-get install -y simple-obfs && {\n                    tui_msgbox \"Success\" \"simple-obfs installed via apt.\"\n                    return 0\n                }\n                tui_msgbox \"Notice\" \"Package not available. Trying source build...\"\n                ;;\n            *)\n                tui_msgbox \"Notice\" \"No package available for ${distro}. Building from source...\"\n                ;;\n        esac\n    fi\n\n    # Build from source\n    if ! command -v git >/dev/null 2>&1; then\n        tui_msgbox \"Error\" \"git is required to build from source.\"\n        return 1\n    fi\n    if ! command -v make >/dev/null 2>&1; then\n        tui_msgbox \"Error\" \"make is required to build from source.\"\n        return 1\n    fi\n\n    TMPDIR_CLEANUP=$(mktemp -d)\n    local tmpdir=\"$TMPDIR_CLEANUP\"\n\n    tui_msgbox \"Building\" \"Cloning and building simple-obfs...\\nThis may take a few minutes.\"\n\n    (\n        cd \"$tmpdir\"\n        git clone https://github.com/shadowsocks/simple-obfs.git\n        cd simple-obfs\n        git submodule update --init --recursive\n        ./autogen.sh\n        ./configure\n        make\n        make install\n    ) || {\n        tui_msgbox \"Error\" \"Build failed. Check that build dependencies are installed:\\n  autoconf, automake, libtool, libev-dev\"\n        return 1\n    }\n\n    if command -v obfs-local >/dev/null 2>&1; then\n        tui_msgbox \"Success\" \"simple-obfs built and installed.\\nBinaries: obfs-local, obfs-server\"\n    else\n        tui_msgbox \"Warning\" \"Build completed but obfs-local not found in PATH.\"\n    fi\n}\n\nplugin_install_custom() {\n    local path\n    path=$(tui_inputbox \"Custom Plugin\" \"Enter the full path to the plugin binary:\" \"\") || return 1\n\n    if [[ -z \"$path\" ]]; then\n        return 1\n    fi\n\n    if [[ ! -f \"$path\" ]]; then\n        tui_msgbox \"Error\" \"File not found: ${path}\"\n        return 1\n    fi\n\n    if [[ ! -x \"$path\" ]]; then\n        chmod +x \"$path\"\n    fi\n\n    local name\n    name=$(basename \"$path\")\n\n    if tui_yesno \"Symlink\" \"Create a symlink in /usr/local/bin/${name}?\"; then\n        ln -sf \"$path\" \"/usr/local/bin/${name}\"\n        tui_msgbox \"Done\" \"Symlinked ${path} → /usr/local/bin/${name}\"\n    else\n        tui_msgbox \"Done\" \"Plugin at ${path} is ready to use.\\nSpecify the full path when configuring.\"\n    fi\n}\n\nplugin_install() {\n    if ! is_root; then\n        tui_msgbox \"Root Required\" \"Plugin installation requires root privileges.\\n\\nRe-run with sudo.\"\n        return\n    fi\n\n    local items=()\n    local p\n    for p in \"${KNOWN_PLUGINS[@]}\"; do\n        local status=\"not installed\"\n        if command -v \"$p\" >/dev/null 2>&1; then\n            status=\"installed\"\n        fi\n        items+=(\"$p\" \"$(plugin_repo \"$p\") (${status})\")\n    done\n    items+=(\"custom\" \"Install a custom binary\")\n\n    local choice\n    choice=$(tui_menu \"Install Plugin\" \"Select a plugin to install:\" \"${items[@]}\") || return\n\n    case \"$choice\" in\n        simple-obfs)\n            plugin_install_simple_obfs\n            ;;\n        v2ray-plugin)\n            plugin_download_github_release \"$(plugin_repo v2ray-plugin)\" \"v2ray-plugin\"\n            ;;\n        xray-plugin)\n            plugin_download_github_release \"$(plugin_repo xray-plugin)\" \"xray-plugin\"\n            ;;\n        kcptun)\n            plugin_download_github_release \"$(plugin_repo kcptun)\" \"kcptun-client\"\n            ;;\n        custom)\n            plugin_install_custom\n            ;;\n    esac\n}\n\n###############################################################################\n# Service Management\n###############################################################################\n\nservice_list_instances() {\n    local instances=()\n\n    # Scan config files\n    if [[ -d \"$CONFIG_DIR\" ]]; then\n        local f name\n        for f in \"${CONFIG_DIR}\"/*.json; do\n            [[ -f \"$f\" ]] || continue\n            name=$(basename \"$f\" .json)\n            local status=\"no service\"\n            local unit=\"shadowsocks-libev-server@${name}.service\"\n            if has_systemd; then\n                if systemctl is-active --quiet \"$unit\" 2>/dev/null; then\n                    status=\"running\"\n                elif systemctl is-enabled --quiet \"$unit\" 2>/dev/null; then\n                    status=\"stopped (enabled)\"\n                fi\n            fi\n            instances+=(\"$name\" \"${status}\")\n        done\n    fi\n\n    if [[ ${#instances[@]} -eq 0 ]]; then\n        tui_msgbox \"No Instances\" \"No config files found in ${CONFIG_DIR}/\"\n        return 1\n    fi\n\n    local choice\n    choice=$(tui_menu \"Instances\" \"Select an instance:\" \"${instances[@]}\") || return 1\n    echo \"$choice\"\n}\n\nservice_action_menu() {\n    local name=\"$1\"\n    local unit=\"shadowsocks-libev-server@${name}.service\"\n\n    while true; do\n        local action\n        action=$(tui_menu \"Manage: ${name}\" \"Select an action:\" \\\n            \"status\" \"View service status\" \\\n            \"start\" \"Start the service\" \\\n            \"stop\" \"Stop the service\" \\\n            \"restart\" \"Restart the service\" \\\n            \"enable\" \"Enable on boot\" \\\n            \"disable\" \"Disable on boot\" \\\n            \"logs\" \"View recent logs\" \\\n            \"back\" \"Return to instance list\") || return\n\n        case \"$action\" in\n            status)\n                local st\n                st=$(systemctl status \"$unit\" 2>&1 || true)\n                tui_msgbox \"Status: ${name}\" \"$st\"\n                ;;\n            start)\n                systemctl start \"$unit\" 2>&1 && \\\n                    tui_msgbox \"Started\" \"Service ${unit} started.\" || \\\n                    tui_msgbox \"Error\" \"Failed to start ${unit}.\"\n                ;;\n            stop)\n                systemctl stop \"$unit\" 2>&1 && \\\n                    tui_msgbox \"Stopped\" \"Service ${unit} stopped.\" || \\\n                    tui_msgbox \"Error\" \"Failed to stop ${unit}.\"\n                ;;\n            restart)\n                systemctl restart \"$unit\" 2>&1 && \\\n                    tui_msgbox \"Restarted\" \"Service ${unit} restarted.\" || \\\n                    tui_msgbox \"Error\" \"Failed to restart ${unit}.\"\n                ;;\n            enable)\n                systemctl enable \"$unit\" 2>&1 && \\\n                    tui_msgbox \"Enabled\" \"Service ${unit} enabled on boot.\" || \\\n                    tui_msgbox \"Error\" \"Failed to enable ${unit}.\"\n                ;;\n            disable)\n                systemctl disable \"$unit\" 2>&1 && \\\n                    tui_msgbox \"Disabled\" \"Service ${unit} disabled.\" || \\\n                    tui_msgbox \"Error\" \"Failed to disable ${unit}.\"\n                ;;\n            logs)\n                local logs\n                logs=$(journalctl -u \"$unit\" -n 50 --no-pager 2>&1 || echo \"(no logs available)\")\n                tui_msgbox \"Logs: ${name}\" \"$logs\"\n                ;;\n            back)\n                return\n                ;;\n        esac\n    done\n}\n\nservice_manage() {\n    if ! is_root; then\n        tui_msgbox \"Root Required\" \"Service management requires root privileges.\\n\\nRe-run with sudo.\"\n        return\n    fi\n\n    if ! has_systemd; then\n        tui_msgbox \"No systemd\" \"systemd was not detected on this system.\\n\\nService management is not available.\"\n        return\n    fi\n\n    while true; do\n        local instance\n        instance=$(service_list_instances) || return\n        service_action_menu \"$instance\"\n    done\n}\n\n###############################################################################\n# Main Menu\n###############################################################################\n\nmain_menu() {\n    while true; do\n        local choice\n        choice=$(tui_menu \"ss-setup v${SS_SETUP_VERSION}\" \"shadowsocks-libev setup tool\" \\\n            \"server\" \"Setup ss-server (generate config + service)\" \\\n            \"client\" \"Generate ss-local client config\" \\\n            \"plugin\" \"Install a SIP003 plugin\" \\\n            \"service\" \"Manage running services\" \\\n            \"exit\" \"Exit\") || break\n\n        case \"$choice\" in\n            server)  server_setup ;;\n            client)  client_setup ;;\n            plugin)  plugin_install ;;\n            service) service_manage ;;\n            exit)    break ;;\n        esac\n    done\n}\n\n###############################################################################\n# Entry Point\n###############################################################################\n\nmain() {\n    # Non-interactive check\n    if [[ ! -t 0 ]]; then\n        echo \"Error: ss-setup requires an interactive terminal.\" >&2\n        echo \"Usage: ss-setup\" >&2\n        exit 1\n    fi\n\n    detect_tui_backend\n    check_root || true  # warn but continue\n    main_menu\n\n    echo \"Goodbye.\"\n}\n\n# Only run main when executed directly (not when sourced for testing)\nif [[ \"${BASH_SOURCE[0]}\" == \"$0\" ]]; then\n    main \"$@\"\nfi\n"
  },
  {
    "path": "snap/snapcraft.yaml",
    "content": "base: core22\nname: shadowsocks-libev\nversion: '3.3.6'\nsummary: libev port of shadowsocks\ndescription: |\n  Shadowsocks-libev is a lightweight and secure SOCKS5 proxy for embedded\n  devices and low-end boxes.\n\n  It is rewritten in pure C and depends on libev, designed to be a\n  lightweight implementation of the shadowsocks protocol.\ngrade: stable\nconfinement: strict\n\napps:\n  ss-local:\n    command: usr/bin/ss-local\n    plugs: [network, network-bind]\n\n  ss-local-daemon:\n    command: usr/bin/ss-local\n    daemon: simple\n    plugs: [network, network-bind]\n\n  ss-server:\n    command: usr/bin/ss-server\n    plugs: [network, network-bind]\n\n  ss-server-daemon:\n    command: usr/bin/ss-server\n    daemon: simple\n    plugs: [network, network-bind]\n\n  ss-redir:\n    command: usr/bin/ss-redir\n    plugs: [network, network-bind]\n\n  ss-tunnel:\n    command: usr/bin/ss-tunnel\n    plugs: [network, network-bind]\n\n  ss-manager:\n    command: usr/bin/ss-manager\n    plugs: [network]\n\nlayout:\n  /etc/shadowsocks-libev:\n    bind: $SNAP_COMMON/etc/shadowsocks-libev\n\nparts:\n  shadowsocks-libev:\n    plugin: cmake\n    source: .\n    source-type: git\n    cmake-parameters:\n      - -DCMAKE_INSTALL_PREFIX=/usr\n      - -DCMAKE_BUILD_TYPE=Release\n      - -DWITH_DOC_MAN=OFF\n      - -DBUILD_TESTING=OFF\n    build-packages:\n      - libpcre2-dev\n      - libev-dev\n      - libc-ares-dev\n      - libmbedtls-dev\n      - libsodium-dev\n    stage-packages:\n      - libc-ares2\n      - libev4\n      - libmbedcrypto7\n      - libmbedtls14\n      - libmbedx509-1\n      - libpcre2-8-0\n      - libsodium23\n    override-build: |\n      craftctl default\n      rm -rf $SNAPCRAFT_PART_INSTALL/usr/share/doc\n"
  },
  {
    "path": "src/CMakeLists.txt",
    "content": "# redir need linux/* stuff\nif (LINUX)\n    option(WITH_SS_REDIR \"Build ss-redir\" ON)\n    option(WITH_SS_MANAGER \"Build ss-manager\" ON)\nelse ()\n    option(WITH_SS_REDIR \"Build ss-redir\" OFF)\n    option(WITH_SS_MANAGER \"Build ss-manager\" OFF)\nendif ()\n\n\nset(SS_ACL_SOURCE\n        acl.c\n        rule.c\n        )\n\nset(SS_CRYPTO_SOURCE\n        crypto.c\n        aead.c\n        stream.c\n        base64.c\n        )\n\nset(SS_PLUGIN_SOURCE\n        plugin.c\n        )\n\nset(SS_SHARED_SOURCES\n        ppbloom.c\n        utils.c\n        jconf.c\n        json.c\n        netutils.c\n        )\nif (MINGW)\nset(SS_SHARED_SOURCES ${SS_SHARED_SOURCES} winsock.c)\nendif ()\n\nset(LIBSHADOWSOCKS_LIBEV_SOURCE\n        ${SS_SHARED_SOURCES}\n        udprelay.c\n        cache.c\n        local.c\n        ${SS_CRYPTO_SOURCE}\n        ${SS_PLUGIN_SOURCE}\n        ${SS_ACL_SOURCE}\n        )\n\nset(SS_LOCAL_SOURCE\n        ${LIBSHADOWSOCKS_LIBEV_SOURCE}\n\n        )\n\nset(SS_TUNNEL_SOURCE\n        ${SS_SHARED_SOURCES}\n        udprelay.c\n        cache.c\n        tunnel.c\n        ${SS_CRYPTO_SOURCE}\n        ${SS_PLUGIN_SOURCE}\n        )\n\nset(SS_SERVER_SOURCE\n        ${SS_SHARED_SOURCES}\n        udprelay.c\n        cache.c\n        resolv.c\n        server.c\n        ${SS_CRYPTO_SOURCE}\n        ${SS_PLUGIN_SOURCE}\n        ${SS_ACL_SOURCE}\n        )\n\nset(SS_MANAGER_SOURCE\n        ${SS_SHARED_SOURCES}\n        manager.c\n        )\n\nset(SS_REDIR_SOURCE\n        ${SS_SHARED_SOURCES}\n        udprelay.c\n        cache.c\n        redir.c\n        ${SS_CRYPTO_SOURCE}\n        ${SS_PLUGIN_SOURCE}\n        )\n\n# Apply -Werror only to project sources (not bundled submodules)\nset(SS_WERROR_FLAGS -Werror)\n\n# Include directories from Find modules\n# MbedTLS must come first to avoid conflicts with other mbedtls versions\n# that may be in /opt/homebrew/include (e.g. mbedtls 4.x vs 3.x)\ninclude_directories(BEFORE ${MBEDTLS_INCLUDE_DIRS})\ninclude_directories(${SODIUM_INCLUDE_DIRS})\ninclude_directories(${PCRE2_INCLUDE_DIRS})\ninclude_directories(${CARES_INCLUDE_DIRS})\n\n# Extract mbedTLS lib dir to ensure static/shared libs come from same version\nget_filename_component(_MBEDTLS_LIB_DIR \"${MBEDTLS_CRYPTO_LIBRARY}\" DIRECTORY)\n\nif (WITH_STATIC)\nfind_library(LIBSODIUM libsodium.a)\nfind_library(LIBMBEDTLS libmbedtls.a HINTS ${_MBEDTLS_LIB_DIR} NO_DEFAULT_PATH)\nfind_library(LIBMBEDTLS libmbedtls.a)\nfind_library(LIBMBEDCRYPTO libmbedcrypto.a HINTS ${_MBEDTLS_LIB_DIR} NO_DEFAULT_PATH)\nfind_library(LIBMBEDCRYPTO libmbedcrypto.a)\nfind_library(LIBEV libev.a)\nfind_library(LIBUDNS libcares.a)\nfind_library(LIBPCRE2 libpcre2-8.a)\n\n# Dependencies we need for static and shared\nlist(APPEND DEPS\n        m\n        bloom\n        ${LIBEV}\n        ${LIBUDNS}\n        ${LIBPCRE2}\n        ${LIBSODIUM}\n        ${LIBMBEDTLS}\n        ${LIBMBEDCRYPTO}\n        )\n\nif (MINGW)\nlist(APPEND DEPS ws2_32 iphlpapi)\nadd_compile_definitions(CARES_STATICLIB PCRE2_STATIC)\nendif ()\nendif ()\n\nfind_library(LIBSODIUM_SHARED sodium)\nfind_library(LIBMBEDTLS_SHARED mbedtls HINTS ${_MBEDTLS_LIB_DIR} NO_DEFAULT_PATH)\nfind_library(LIBMBEDTLS_SHARED mbedtls)\nfind_library(LIBMBEDCRYPTO_SHARED mbedcrypto HINTS ${_MBEDTLS_LIB_DIR} NO_DEFAULT_PATH)\nfind_library(LIBMBEDCRYPTO_SHARED mbedcrypto)\nfind_library(LIBEV_SHARED ev)\nfind_library(LIBUDNS_SHARED cares)\nfind_library(LIBPCRE2_SHARED pcre2-8)\n\nif (WITH_EMBEDDED_SRC)\nlist(APPEND DEPS_SHARED\n        m\n        bloom\n        cork\n        ipset\n        ${LIBEV_SHARED}\n        ${LIBUDNS_SHARED}\n        ${LIBPCRE2_SHARED}\n        ${LIBSODIUM_SHARED}\n        ${LIBMBEDTLS_SHARED}\n        ${LIBMBEDCRYPTO_SHARED}\n        )\nelse ()\nfind_library(LIBBLOOM_SHARED bloom)\nfind_library(LIBCORK_SHARED cork)\nfind_library(LIBCORKIPSET_SHARED corkipset)\nlist(APPEND DEPS_SHARED\n        m\n        ${LIBBLOOM_SHARED}\n        ${LIBCORK_SHARED}\n        ${LIBCORKIPSET_SHARED}\n        ${LIBEV_SHARED}\n        ${LIBUDNS_SHARED}\n        ${LIBPCRE2_SHARED}\n        ${LIBSODIUM_SHARED}\n        ${LIBMBEDTLS_SHARED}\n        ${LIBMBEDCRYPTO_SHARED}\n        )\nendif ()\n\n# Connmarktos/nftables libraries for ss-server\nif(ENABLE_CONNMARKTOS)\n    list(APPEND DEPS_CONNMARKTOS ${NETFILTER_CONNTRACK_LIB})\n    if(NFNETLINK_LIB)\n        list(APPEND DEPS_CONNMARKTOS ${NFNETLINK_LIB})\n    endif()\nendif()\nif(ENABLE_NFTABLES)\n    list(APPEND DEPS_NFTABLES ${MNL_LIB} ${NFTNL_LIB})\nendif()\n\nfind_package (Threads)\n\nif (WITH_STATIC)\n# ------------------------------------------------------------------\n# Static\n# By default we use normal name for static, all shared targets will add a `-shared' suffix\nadd_executable(ss-server ${SS_SERVER_SOURCE})\nadd_executable(ss-tunnel ${SS_TUNNEL_SOURCE})\nif (WITH_SS_MANAGER)\n    add_executable(ss-manager ${SS_MANAGER_SOURCE})\nelse ()\n    add_executable(ss-manager EXCLUDE_FROM_ALL ${SS_MANAGER_SOURCE})\nendif ()\nadd_executable(ss-local ${SS_LOCAL_SOURCE})\nif (WITH_SS_REDIR)\n    add_executable(ss-redir ${SS_REDIR_SOURCE})\nelse ()\n    add_executable(ss-redir EXCLUDE_FROM_ALL ${SS_REDIR_SOURCE})\nendif ()\nadd_library(shadowsocks-libev STATIC ${LIBSHADOWSOCKS_LIBEV_SOURCE})\n\n\ntarget_compile_definitions(ss-server PUBLIC -DMODULE_REMOTE)\ntarget_compile_definitions(ss-tunnel PUBLIC -DMODULE_TUNNEL)\ntarget_compile_definitions(ss-manager PUBLIC -DMODULE_MANAGER)\ntarget_compile_definitions(ss-local PUBLIC -DMODULE_LOCAL)\ntarget_compile_definitions(ss-redir PUBLIC -DMODULE_REDIR)\ntarget_compile_definitions(shadowsocks-libev PUBLIC -DMODULE_LOCAL -DLIB_ONLY)\n\ntarget_compile_options(ss-server PRIVATE ${SS_WERROR_FLAGS})\ntarget_compile_options(ss-tunnel PRIVATE ${SS_WERROR_FLAGS})\ntarget_compile_options(ss-manager PRIVATE ${SS_WERROR_FLAGS})\ntarget_compile_options(ss-local PRIVATE ${SS_WERROR_FLAGS})\ntarget_compile_options(ss-redir PRIVATE ${SS_WERROR_FLAGS})\ntarget_compile_options(shadowsocks-libev PRIVATE ${SS_WERROR_FLAGS})\n\n# Connmarktos/nftables compile definitions\nif(ENABLE_CONNMARKTOS)\n    target_compile_definitions(ss-server PUBLIC -DUSE_NFCONNTRACK_TOS)\nendif()\nif(ENABLE_NFTABLES)\n    target_compile_definitions(ss-server PUBLIC -DUSE_NFTABLES)\nendif()\n\ntarget_include_directories(shadowsocks-libev PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})\n\ntarget_link_libraries(ss-server cork ipset ${DEPS} ${DEPS_CONNMARKTOS} ${DEPS_NFTABLES})\ntarget_link_libraries(ss-tunnel cork ${DEPS})\ntarget_link_libraries(ss-manager m bloom cork ${LIBEV} ${LIBUDNS})\ntarget_link_libraries(ss-local cork ipset ${DEPS})\ntarget_link_libraries(ss-redir cork ipset ${DEPS})\ntarget_link_libraries(shadowsocks-libev cork ipset ${DEPS})\nendif ()\n\n# ------------------------------------------------------------------\n# Shared\n# Shared target will have a `-shared' suffix\n# All shared dependency also have `-shared' suffix\n# For shared binary, we still use the same name as static, without `-shared', but will output to shared directory\nadd_executable(ss-server-shared ${SS_SERVER_SOURCE})\nadd_executable(ss-tunnel-shared ${SS_TUNNEL_SOURCE})\nif (WITH_SS_MANAGER)\n    add_executable(ss-manager-shared ${SS_MANAGER_SOURCE})\nelse ()\n    add_executable(ss-manager-shared EXCLUDE_FROM_ALL ${SS_MANAGER_SOURCE})\nendif ()\nadd_executable(ss-local-shared ${SS_LOCAL_SOURCE})\nif (WITH_SS_REDIR)\n    add_executable(ss-redir-shared ${SS_REDIR_SOURCE})\nelse ()\n    add_executable(ss-redir-shared EXCLUDE_FROM_ALL ${SS_REDIR_SOURCE})\nendif ()\nadd_library(shadowsocks-libev-shared SHARED ${LIBSHADOWSOCKS_LIBEV_SOURCE})\n\ntarget_compile_definitions(ss-server-shared PUBLIC -DMODULE_REMOTE)\ntarget_compile_definitions(ss-tunnel-shared PUBLIC -DMODULE_TUNNEL)\ntarget_compile_definitions(ss-manager-shared PUBLIC -DMODULE_MANAGER)\ntarget_compile_definitions(ss-local-shared PUBLIC -DMODULE_LOCAL)\ntarget_compile_definitions(ss-redir-shared PUBLIC -DMODULE_REDIR)\ntarget_compile_definitions(shadowsocks-libev-shared PUBLIC -DMODULE_LOCAL -DLIB_ONLY)\n\ntarget_compile_options(ss-server-shared PRIVATE ${SS_WERROR_FLAGS})\ntarget_compile_options(ss-tunnel-shared PRIVATE ${SS_WERROR_FLAGS})\ntarget_compile_options(ss-manager-shared PRIVATE ${SS_WERROR_FLAGS})\ntarget_compile_options(ss-local-shared PRIVATE ${SS_WERROR_FLAGS})\ntarget_compile_options(ss-redir-shared PRIVATE ${SS_WERROR_FLAGS})\ntarget_compile_options(shadowsocks-libev-shared PRIVATE ${SS_WERROR_FLAGS})\n\n# Connmarktos/nftables compile definitions for shared\nif(ENABLE_CONNMARKTOS)\n    target_compile_definitions(ss-server-shared PUBLIC -DUSE_NFCONNTRACK_TOS)\nendif()\nif(ENABLE_NFTABLES)\n    target_compile_definitions(ss-server-shared PUBLIC -DUSE_NFTABLES)\nendif()\n\ntarget_include_directories(shadowsocks-libev-shared PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})\n\ntarget_link_libraries(ss-server-shared ${DEPS_SHARED} ${DEPS_CONNMARKTOS} ${DEPS_NFTABLES})\ntarget_link_libraries(ss-tunnel-shared ${DEPS_SHARED})\ntarget_link_libraries(ss-manager-shared ${CMAKE_THREAD_LIBS_INIT} ${LIBEV_SHARED} ${LIBUDNS_SHARED} ${DEPS_SHARED})\ntarget_link_libraries(ss-local-shared ${DEPS_SHARED})\ntarget_link_libraries(ss-redir-shared ${DEPS_SHARED})\ntarget_link_libraries(shadowsocks-libev-shared ${DEPS_SHARED})\n\nset_target_properties(ss-server-shared PROPERTIES OUTPUT_NAME ss-server)\nset_target_properties(ss-tunnel-shared PROPERTIES OUTPUT_NAME ss-tunnel)\nset_target_properties(ss-manager-shared PROPERTIES OUTPUT_NAME ss-manager)\nset_target_properties(ss-local-shared PROPERTIES OUTPUT_NAME ss-local)\nset_target_properties(ss-redir-shared PROPERTIES OUTPUT_NAME ss-redir)\n\nset_target_properties(ss-server-shared ss-tunnel-shared ss-manager-shared ss-local-shared ss-redir-shared\n        PROPERTIES\n        RUNTIME_OUTPUT_DIRECTORY ${RUNTIME_SHARED_OUTPUT_DIRECTORY}\n        )\n\nset_target_properties(shadowsocks-libev-shared PROPERTIES OUTPUT_NAME shadowsocks-libev)\nset_target_properties(shadowsocks-libev-shared PROPERTIES VERSION 2.0.0 SOVERSION 2)\ntarget_compile_definitions(shadowsocks-libev-shared PUBLIC -DMODULE_LOCAL)\ntarget_link_libraries(shadowsocks-libev-shared ${DEPS_SHARED})\n\n# ------------------------------------------------------------------\n# Misc\n# Recommend to install shared by default\ninstall(DIRECTORY ${RUNTIME_SHARED_OUTPUT_DIRECTORY}/\n        USE_SOURCE_PERMISSIONS\n        DESTINATION ${CMAKE_INSTALL_BINDIR})\n\nif (WITH_STATIC)\n    install(TARGETS shadowsocks-libev\n        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})\nendif ()\n\ninstall(TARGETS shadowsocks-libev-shared\n        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})\n\ninstall(FILES shadowsocks.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})\n\n\nadd_custom_target(distclean\n        COMMAND ${CMAKE_COMMAND} -E echo WARNING: distclean target is not functional\n        COMMAND ${CMAKE_COMMAND} -E echo Use 'git clean -fdx' instead\n        VERBATIM\n        )\n"
  },
  {
    "path": "src/acl.c",
    "content": "/*\n * acl.c - Manage the ACL (Access Control List)\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <ctype.h>\n\n#ifdef USE_SYSTEM_SHARED_LIB\n#include <libcorkipset/ipset.h>\n#else\n#include <ipset/ipset.h>\n#endif\n\n#include \"rule.h\"\n#include \"netutils.h\"\n#include \"utils.h\"\n#include \"cache.h\"\n#include \"acl.h\"\n\nstatic struct ip_set white_list_ipv4;\nstatic struct ip_set white_list_ipv6;\n\nstatic struct ip_set black_list_ipv4;\nstatic struct ip_set black_list_ipv6;\n\nstatic struct cork_dllist black_list_rules;\nstatic struct cork_dllist white_list_rules;\n\nstatic int acl_mode = BLACK_LIST;\n\nstatic struct ip_set outbound_block_list_ipv4;\nstatic struct ip_set outbound_block_list_ipv6;\nstatic struct cork_dllist outbound_block_list_rules;\n\nstatic void\nparse_addr_cidr(const char *str, char *host, int *cidr)\n{\n    int ret = -1;\n    char *pch;\n\n    pch = strchr(str, '/');\n    while (pch != NULL) {\n        ret = pch - str;\n        pch = strchr(pch + 1, '/');\n    }\n    if (ret == -1) {\n        strcpy(host, str);\n        *cidr = -1;\n    } else {\n        memcpy(host, str, ret);\n        host[ret] = '\\0';\n        *cidr     = atoi(str + ret + 1);\n    }\n}\n\nchar *\ntrimwhitespace(char *str)\n{\n    char *end;\n\n    // Trim leading space\n    while (isspace((unsigned char)*str))\n        str++;\n\n    if (*str == 0)   // All spaces?\n        return str;\n\n    // Trim trailing space\n    end = str + strlen(str) - 1;\n    while (end > str && isspace((unsigned char)*end))\n        end--;\n\n    // Write new null terminator\n    *(end + 1) = 0;\n\n    return str;\n}\n\nint\ninit_acl(const char *path)\n{\n    if (path == NULL) {\n        return -1;\n    }\n\n    // initialize ipset\n    ipset_init_library();\n\n    ipset_init(&white_list_ipv4);\n    ipset_init(&white_list_ipv6);\n    ipset_init(&black_list_ipv4);\n    ipset_init(&black_list_ipv6);\n    ipset_init(&outbound_block_list_ipv4);\n    ipset_init(&outbound_block_list_ipv6);\n\n    cork_dllist_init(&black_list_rules);\n    cork_dllist_init(&white_list_rules);\n    cork_dllist_init(&outbound_block_list_rules);\n\n    struct ip_set *list_ipv4  = &black_list_ipv4;\n    struct ip_set *list_ipv6  = &black_list_ipv6;\n    struct cork_dllist *rules = &black_list_rules;\n\n    FILE *f = fopen(path, \"r\");\n    if (f == NULL) {\n        LOGE(\"Invalid acl path.\");\n        return -1;\n    }\n\n    char buf[MAX_HOSTNAME_LEN];\n\n    while (!feof(f))\n        if (fgets(buf, 256, f)) {\n            // Discards the whole line if longer than 255 characters\n            int long_line = 0;  // 1: Long  2: Error\n            while ((strlen(buf) == 255) && (buf[254] != '\\n')) {\n                long_line = 1;\n                LOGE(\"Discarding long ACL content: %s\", buf);\n                if (fgets(buf, 256, f) == NULL) {\n                    long_line = 2;\n                    break;\n                }\n            }\n            if (long_line) {\n                if (long_line == 1) {\n                    LOGE(\"Discarding long ACL content: %s\", buf);\n                }\n                continue;\n            }\n\n            // Trim the newline\n            int len = strlen(buf);\n            if (len > 0 && buf[len - 1] == '\\n') {\n                buf[len - 1] = '\\0';\n            }\n\n            char *comment = strchr(buf, '#');\n            if (comment) {\n                *comment = '\\0';\n            }\n\n            char *line = trimwhitespace(buf);\n            if (strlen(line) == 0) {\n                continue;\n            }\n\n            if (strcmp(line, \"[outbound_block_list]\") == 0) {\n                list_ipv4 = &outbound_block_list_ipv4;\n                list_ipv6 = &outbound_block_list_ipv6;\n                rules     = &outbound_block_list_rules;\n                continue;\n            } else if (strcmp(line, \"[black_list]\") == 0\n                       || strcmp(line, \"[bypass_list]\") == 0) {\n                list_ipv4 = &black_list_ipv4;\n                list_ipv6 = &black_list_ipv6;\n                rules     = &black_list_rules;\n                continue;\n            } else if (strcmp(line, \"[white_list]\") == 0\n                       || strcmp(line, \"[proxy_list]\") == 0) {\n                list_ipv4 = &white_list_ipv4;\n                list_ipv6 = &white_list_ipv6;\n                rules     = &white_list_rules;\n                continue;\n            } else if (strcmp(line, \"[reject_all]\") == 0\n                       || strcmp(line, \"[bypass_all]\") == 0) {\n                acl_mode = WHITE_LIST;\n                continue;\n            } else if (strcmp(line, \"[accept_all]\") == 0\n                       || strcmp(line, \"[proxy_all]\") == 0) {\n                acl_mode = BLACK_LIST;\n                continue;\n            }\n\n            char host[MAX_HOSTNAME_LEN];\n            int cidr;\n            parse_addr_cidr(line, host, &cidr);\n\n            struct cork_ip addr;\n            int err = cork_ip_init(&addr, host);\n            if (!err) {\n                if (addr.version == 4) {\n                    if (cidr >= 0) {\n                        ipset_ipv4_add_network(list_ipv4, &(addr.ip.v4), cidr);\n                    } else {\n                        ipset_ipv4_add(list_ipv4, &(addr.ip.v4));\n                    }\n                } else if (addr.version == 6) {\n                    if (cidr >= 0) {\n                        ipset_ipv6_add_network(list_ipv6, &(addr.ip.v6), cidr);\n                    } else {\n                        ipset_ipv6_add(list_ipv6, &(addr.ip.v6));\n                    }\n                }\n            } else {\n                rule_t *rule = new_rule();\n                accept_rule_arg(rule, line);\n                init_rule(rule);\n                add_rule(rules, rule);\n            }\n        }\n\n    fclose(f);\n\n    return 0;\n}\n\nvoid\nfree_rules(struct cork_dllist *rules)\n{\n    struct cork_dllist_item *iter;\n    while ((iter = cork_dllist_head(rules)) != NULL) {\n        rule_t *rule = cork_container_of(iter, rule_t, entries);\n        remove_rule(rule);\n    }\n}\n\nvoid\nfree_acl(void)\n{\n    ipset_done(&black_list_ipv4);\n    ipset_done(&black_list_ipv6);\n    ipset_done(&white_list_ipv4);\n    ipset_done(&white_list_ipv6);\n\n    free_rules(&black_list_rules);\n    free_rules(&white_list_rules);\n}\n\nint\nget_acl_mode(void)\n{\n    return acl_mode;\n}\n\n/*\n * Return 0,  if not match.\n * Return 1,  if match black list.\n * Return -1, if match white list.\n */\nint\nacl_match_host(const char *host)\n{\n    struct cork_ip addr;\n    int ret = 0;\n    int err = cork_ip_init(&addr, host);\n\n    if (err) {\n        int host_len = strlen(host);\n        if (lookup_rule(&black_list_rules, host, host_len) != NULL)\n            ret = 1;\n        else if (lookup_rule(&white_list_rules, host, host_len) != NULL)\n            ret = -1;\n        return ret;\n    }\n\n    if (addr.version == 4) {\n        if (ipset_contains_ipv4(&black_list_ipv4, &(addr.ip.v4)))\n            ret = 1;\n        else if (ipset_contains_ipv4(&white_list_ipv4, &(addr.ip.v4)))\n            ret = -1;\n    } else if (addr.version == 6) {\n        if (ipset_contains_ipv6(&black_list_ipv6, &(addr.ip.v6)))\n            ret = 1;\n        else if (ipset_contains_ipv6(&white_list_ipv6, &(addr.ip.v6)))\n            ret = -1;\n    }\n\n    return ret;\n}\n\nint\nacl_add_ip(const char *ip)\n{\n    struct cork_ip addr;\n    int err = cork_ip_init(&addr, ip);\n    if (err) {\n        return -1;\n    }\n\n    if (addr.version == 4) {\n        ipset_ipv4_add(&black_list_ipv4, &(addr.ip.v4));\n    } else if (addr.version == 6) {\n        ipset_ipv6_add(&black_list_ipv6, &(addr.ip.v6));\n    }\n\n    return 0;\n}\n\nint\nacl_remove_ip(const char *ip)\n{\n    struct cork_ip addr;\n    int err = cork_ip_init(&addr, ip);\n    if (err) {\n        return -1;\n    }\n\n    if (addr.version == 4) {\n        ipset_ipv4_remove(&black_list_ipv4, &(addr.ip.v4));\n    } else if (addr.version == 6) {\n        ipset_ipv6_remove(&black_list_ipv6, &(addr.ip.v6));\n    }\n\n    return 0;\n}\n\n/*\n * Return 0,  if not match.\n * Return 1,  if match black list.\n */\nint\noutbound_block_match_host(const char *host)\n{\n    struct cork_ip addr;\n    int ret = 0;\n    int err = cork_ip_init(&addr, host);\n\n    if (err) {\n        int host_len = strlen(host);\n        if (lookup_rule(&outbound_block_list_rules, host, host_len) != NULL)\n            ret = 1;\n        return ret;\n    }\n\n    if (addr.version == 4) {\n        if (ipset_contains_ipv4(&outbound_block_list_ipv4, &(addr.ip.v4)))\n            ret = 1;\n    } else if (addr.version == 6) {\n        if (ipset_contains_ipv6(&outbound_block_list_ipv6, &(addr.ip.v6)))\n            ret = 1;\n    }\n\n    return ret;\n}\n"
  },
  {
    "path": "src/acl.h",
    "content": "/*\n * acl.h - Define the ACL interface\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _ACL_H\n#define _ACL_H\n\n#define BLACK_LIST 0\n#define WHITE_LIST 1\n\nint init_acl(const char *path);\nvoid free_acl(void);\n\nint acl_match_host(const char *ip);\nint acl_add_ip(const char *ip);\nint acl_remove_ip(const char *ip);\n\nint get_acl_mode(void);\n\nint outbound_block_match_host(const char *host);\n\n#endif // _ACL_H\n"
  },
  {
    "path": "src/aead.c",
    "content": "/*\n * aead.c - Manage AEAD ciphers\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <mbedtls/version.h>\n#define CIPHER_UNSUPPORTED \"unsupported\"\n#include <time.h>\n#include <stdio.h>\n#include <assert.h>\n\n#include <sodium.h>\n#ifndef __MINGW32__\n#include <arpa/inet.h>\n#endif\n\n#include \"ppbloom.h\"\n#include \"aead.h\"\n#include \"utils.h\"\n#include \"winsock.h\"\n\n#define NONE                    (-1)\n#define AES128GCM               0\n#define AES192GCM               1\n#define AES256GCM               2\n/*\n * methods above requires gcm context\n * methods below doesn't require it,\n * then we need to fake one\n */\n#define CHACHA20POLY1305IETF    3\n\n#ifdef FS_HAVE_XCHACHA20IETF\n#define XCHACHA20POLY1305IETF   4\n#endif\n\n#define CHUNK_SIZE_LEN          2\n#define CHUNK_SIZE_MASK         0x3FFF\n\n/*\n * Spec: http://shadowsocks.org/en/spec/AEAD-Ciphers.html\n *\n * The way Shadowsocks using AEAD ciphers is specified in SIP004 and amended in SIP007. SIP004 was proposed by @Mygod\n * with design inspirations from @wongsyrone, @Noisyfox and @breakwa11. SIP007 was proposed by @riobard with input from\n * @madeye, @Mygod, @wongsyrone, and many others.\n *\n * Key Derivation\n *\n * HKDF_SHA1 is a function that takes a secret key, a non-secret salt, an info string, and produces a subkey that is\n * cryptographically strong even if the input secret key is weak.\n *\n *      HKDF_SHA1(key, salt, info) => subkey\n *\n * The info string binds the generated subkey to a specific application context. In our case, it must be the string\n * \"ss-subkey\" without quotes.\n *\n * We derive a per-session subkey from a pre-shared master key using HKDF_SHA1. Salt must be unique through the entire\n * life of the pre-shared master key.\n *\n * TCP\n *\n * An AEAD encrypted TCP stream starts with a randomly generated salt to derive the per-session subkey, followed by any\n * number of encrypted chunks. Each chunk has the following structure:\n *\n *      [encrypted payload length][length tag][encrypted payload][payload tag]\n *\n * Payload length is a 2-byte big-endian unsigned integer capped at 0x3FFF. The higher two bits are reserved and must be\n * set to zero. Payload is therefore limited to 16*1024 - 1 bytes.\n *\n * The first AEAD encrypt/decrypt operation uses a counting nonce starting from 0. After each encrypt/decrypt operation,\n * the nonce is incremented by one as if it were an unsigned little-endian integer. Note that each TCP chunk involves\n * two AEAD encrypt/decrypt operation: one for the payload length, and one for the payload. Therefore each chunk\n * increases the nonce twice.\n *\n * UDP\n *\n * An AEAD encrypted UDP packet has the following structure:\n *\n *      [salt][encrypted payload][tag]\n *\n * The salt is used to derive the per-session subkey and must be generated randomly to ensure uniqueness. Each UDP\n * packet is encrypted/decrypted independently, using the derived subkey and a nonce with all zero bytes.\n *\n */\n\nconst char *supported_aead_ciphers[AEAD_CIPHER_NUM] = {\n    \"aes-128-gcm\",\n    \"aes-192-gcm\",\n    \"aes-256-gcm\",\n    \"chacha20-ietf-poly1305\",\n#ifdef FS_HAVE_XCHACHA20IETF\n    \"xchacha20-ietf-poly1305\"\n#endif\n};\n\n/*\n * use mbed TLS cipher wrapper to unify handling\n */\nstatic const char *supported_aead_ciphers_mbedtls[AEAD_CIPHER_NUM] = {\n    \"AES-128-GCM\",\n    \"AES-192-GCM\",\n    \"AES-256-GCM\",\n    CIPHER_UNSUPPORTED,\n#ifdef FS_HAVE_XCHACHA20IETF\n    CIPHER_UNSUPPORTED\n#endif\n};\n\nstatic const int supported_aead_ciphers_nonce_size[AEAD_CIPHER_NUM] = {\n    12, 12, 12, 12,\n#ifdef FS_HAVE_XCHACHA20IETF\n    24\n#endif\n};\n\nstatic const int supported_aead_ciphers_key_size[AEAD_CIPHER_NUM] = {\n    16, 24, 32, 32,\n#ifdef FS_HAVE_XCHACHA20IETF\n    32\n#endif\n};\n\nstatic const int supported_aead_ciphers_tag_size[AEAD_CIPHER_NUM] = {\n    16, 16, 16, 16,\n#ifdef FS_HAVE_XCHACHA20IETF\n    16\n#endif\n};\n\nstatic int\naead_cipher_encrypt(cipher_ctx_t *cipher_ctx,\n                    uint8_t *c,\n                    size_t *clen,\n                    uint8_t *m,\n                    size_t mlen,\n                    uint8_t *ad,\n                    size_t adlen,\n                    uint8_t *n,\n                    uint8_t *k)\n{\n    int err                      = CRYPTO_OK;\n    unsigned long long long_clen = 0;\n\n    size_t nlen = cipher_ctx->cipher->nonce_len;\n    size_t tlen = cipher_ctx->cipher->tag_len;\n\n    switch (cipher_ctx->cipher->method) {\n    case AES256GCM: // Only AES-256-GCM is supported by libsodium.\n        if (cipher_ctx->aes256gcm_ctx != NULL) { // Use it if availble\n            err = crypto_aead_aes256gcm_encrypt_afternm(c, &long_clen, m, mlen,\n                                                        ad, adlen, NULL, n,\n                                                        (const aes256gcm_ctx *)cipher_ctx->aes256gcm_ctx);\n            *clen = (size_t)long_clen; // it's safe to cast 64bit to 32bit length here\n            break;\n        }\n    // Otherwise, just use the mbedTLS one with crappy AES-NI.\n    case AES192GCM:\n    case AES128GCM:\n#if MBEDTLS_VERSION_NUMBER < 0x03000000\n        err = mbedtls_cipher_auth_encrypt(cipher_ctx->evp, n, nlen, ad, adlen,\n                                          m, mlen, c, clen, c + mlen, tlen);\n#else\n        err = mbedtls_cipher_auth_encrypt_ext(cipher_ctx->evp, n, nlen, ad, adlen,\n                                              m, mlen, c, mlen + tlen, clen, tlen);\n#endif\n        *clen += tlen;\n        break;\n    case CHACHA20POLY1305IETF:\n        err = crypto_aead_chacha20poly1305_ietf_encrypt(c, &long_clen, m, mlen,\n                                                        ad, adlen, NULL, n, k);\n        *clen = (size_t)long_clen;\n        break;\n#ifdef FS_HAVE_XCHACHA20IETF\n    case XCHACHA20POLY1305IETF:\n        err = crypto_aead_xchacha20poly1305_ietf_encrypt(c, &long_clen, m, mlen,\n                                                         ad, adlen, NULL, n, k);\n        *clen = (size_t)long_clen;\n        break;\n#endif\n    default:\n        return CRYPTO_ERROR;\n    }\n\n    return err;\n}\n\nstatic int\naead_cipher_decrypt(cipher_ctx_t *cipher_ctx,\n                    uint8_t *p, size_t *plen,\n                    uint8_t *m, size_t mlen,\n                    uint8_t *ad, size_t adlen,\n                    uint8_t *n, uint8_t *k)\n{\n    int err                      = CRYPTO_ERROR;\n    unsigned long long long_plen = 0;\n\n    size_t nlen = cipher_ctx->cipher->nonce_len;\n    size_t tlen = cipher_ctx->cipher->tag_len;\n\n    switch (cipher_ctx->cipher->method) {\n    case AES256GCM: // Only AES-256-GCM is supported by libsodium.\n        if (cipher_ctx->aes256gcm_ctx != NULL) { // Use it if availble\n            err = crypto_aead_aes256gcm_decrypt_afternm(p, &long_plen, NULL, m, mlen,\n                                                        ad, adlen, n,\n                                                        (const aes256gcm_ctx *)cipher_ctx->aes256gcm_ctx);\n            *plen = (size_t)long_plen; // it's safe to cast 64bit to 32bit length here\n            break;\n        }\n    // Otherwise, just use the mbedTLS one with crappy AES-NI.\n    case AES192GCM:\n    case AES128GCM:\n#if MBEDTLS_VERSION_NUMBER < 0x03000000\n        err = mbedtls_cipher_auth_decrypt(cipher_ctx->evp, n, nlen, ad, adlen,\n                                          m, mlen - tlen, p, plen, m + mlen - tlen, tlen);\n#else\n        err = mbedtls_cipher_auth_decrypt_ext(cipher_ctx->evp, n, nlen, ad, adlen,\n                                              m, mlen, p, mlen - tlen, plen, tlen);\n#endif\n        break;\n    case CHACHA20POLY1305IETF:\n        err = crypto_aead_chacha20poly1305_ietf_decrypt(p, &long_plen, NULL, m, mlen,\n                                                        ad, adlen, n, k);\n        *plen = (size_t)long_plen; // it's safe to cast 64bit to 32bit length here\n        break;\n#ifdef FS_HAVE_XCHACHA20IETF\n    case XCHACHA20POLY1305IETF:\n        err = crypto_aead_xchacha20poly1305_ietf_decrypt(p, &long_plen, NULL, m, mlen,\n                                                         ad, adlen, n, k);\n        *plen = (size_t)long_plen; // it's safe to cast 64bit to 32bit length here\n        break;\n#endif\n    default:\n        return CRYPTO_ERROR;\n    }\n\n    // The success return value ln libsodium and mbedTLS are both 0\n    if (err != 0)\n        // Although we never return any library specific value in the caller,\n        // here we still set the error code to CRYPTO_ERROR to avoid confusion.\n        err = CRYPTO_ERROR;\n\n    return err;\n}\n\n/*\n * get basic cipher info structure\n * it's a wrapper offered by crypto library\n */\nconst cipher_kt_t *\naead_get_cipher_type(int method)\n{\n    if (method < AES128GCM || method >= AEAD_CIPHER_NUM) {\n        LOGE(\"aead_get_cipher_type(): Illegal method\");\n        return NULL;\n    }\n\n    /* cipher that don't use mbed TLS, just return */\n    if (method >= CHACHA20POLY1305IETF) {\n        return NULL;\n    }\n\n    const char *ciphername  = supported_aead_ciphers[method];\n    const char *mbedtlsname = supported_aead_ciphers_mbedtls[method];\n    if (strcmp(mbedtlsname, CIPHER_UNSUPPORTED) == 0) {\n        LOGE(\"Cipher %s currently is not supported by mbed TLS library\",\n             ciphername);\n        return NULL;\n    }\n    return mbedtls_cipher_info_from_string(mbedtlsname);\n}\n\nstatic void\naead_cipher_ctx_set_key(cipher_ctx_t *cipher_ctx, int enc)\n{\n    const digest_type_t *md = mbedtls_md_info_from_string(\"SHA1\");\n    if (md == NULL) {\n        FATAL(\"SHA1 Digest not found in crypto library\");\n    }\n\n    int err = crypto_hkdf(md,\n                          cipher_ctx->salt, cipher_ctx->cipher->key_len,\n                          cipher_ctx->cipher->key, cipher_ctx->cipher->key_len,\n                          (uint8_t *)SUBKEY_INFO, strlen(SUBKEY_INFO),\n                          cipher_ctx->skey, cipher_ctx->cipher->key_len);\n    if (err) {\n        FATAL(\"Unable to generate subkey\");\n    }\n\n    memset(cipher_ctx->nonce, 0, cipher_ctx->cipher->nonce_len);\n\n    /* cipher that don't use mbed TLS, just return */\n    if (cipher_ctx->cipher->method >= CHACHA20POLY1305IETF) {\n        return;\n    }\n    if (cipher_ctx->aes256gcm_ctx != NULL) {\n        if (crypto_aead_aes256gcm_beforenm(cipher_ctx->aes256gcm_ctx,\n                                           cipher_ctx->skey) != 0) {\n            FATAL(\"Cannot set libsodium cipher key\");\n        }\n        return;\n    }\n    if (mbedtls_cipher_setkey(cipher_ctx->evp, cipher_ctx->skey,\n                              cipher_ctx->cipher->key_len * 8, enc) != 0) {\n        FATAL(\"Cannot set mbed TLS cipher key\");\n    }\n    if (mbedtls_cipher_reset(cipher_ctx->evp) != 0) {\n        FATAL(\"Cannot finish preparation of mbed TLS cipher context\");\n    }\n}\n\nstatic void\naead_cipher_ctx_init(cipher_ctx_t *cipher_ctx, int method, int enc)\n{\n    if (method < AES128GCM || method >= AEAD_CIPHER_NUM) {\n        LOGE(\"cipher_context_init(): Illegal method\");\n        return;\n    }\n\n    if (method >= CHACHA20POLY1305IETF) {\n        return;\n    }\n\n    const char *ciphername = supported_aead_ciphers[method];\n\n    const cipher_kt_t *cipher = aead_get_cipher_type(method);\n\n    if (method == AES256GCM && crypto_aead_aes256gcm_is_available()) {\n        cipher_ctx->aes256gcm_ctx = ss_aligned_malloc(sizeof(aes256gcm_ctx));\n        memset(cipher_ctx->aes256gcm_ctx, 0, sizeof(aes256gcm_ctx));\n    } else {\n        cipher_ctx->aes256gcm_ctx = NULL;\n        cipher_ctx->evp           = ss_malloc(sizeof(cipher_evp_t));\n        memset(cipher_ctx->evp, 0, sizeof(cipher_evp_t));\n        cipher_evp_t *evp = cipher_ctx->evp;\n        mbedtls_cipher_init(evp);\n        if (mbedtls_cipher_setup(evp, cipher) != 0) {\n            FATAL(\"Cannot initialize mbed TLS cipher context\");\n        }\n    }\n\n    if (cipher == NULL) {\n        LOGE(\"Cipher %s not found in mbed TLS library\", ciphername);\n        FATAL(\"Cannot initialize mbed TLS cipher\");\n    }\n\n#ifdef SS_DEBUG\n    dump(\"KEY\", (char *)cipher_ctx->cipher->key, cipher_ctx->cipher->key_len);\n#endif\n}\n\nvoid\naead_ctx_init(cipher_t *cipher, cipher_ctx_t *cipher_ctx, int enc)\n{\n    sodium_memzero(cipher_ctx, sizeof(cipher_ctx_t));\n    cipher_ctx->cipher = cipher;\n\n    aead_cipher_ctx_init(cipher_ctx, cipher->method, enc);\n\n    if (enc) {\n        rand_bytes(cipher_ctx->salt, cipher->key_len);\n    }\n}\n\nvoid\naead_ctx_release(cipher_ctx_t *cipher_ctx)\n{\n    if (cipher_ctx->chunk != NULL) {\n        bfree(cipher_ctx->chunk);\n        ss_free(cipher_ctx->chunk);\n        cipher_ctx->chunk = NULL;\n    }\n\n    if (cipher_ctx->cipher->method >= CHACHA20POLY1305IETF) {\n        return;\n    }\n\n    if (cipher_ctx->aes256gcm_ctx != NULL) {\n        ss_aligned_free(cipher_ctx->aes256gcm_ctx);\n        return;\n    }\n\n    mbedtls_cipher_free(cipher_ctx->evp);\n    ss_free(cipher_ctx->evp);\n}\n\nint\naead_encrypt_all(buffer_t *plaintext, cipher_t *cipher, size_t capacity)\n{\n    cipher_ctx_t cipher_ctx;\n    aead_ctx_init(cipher, &cipher_ctx, 1);\n\n    size_t salt_len = cipher->key_len;\n    size_t tag_len  = cipher->tag_len;\n    int err         = CRYPTO_OK;\n\n    static buffer_t tmp = { 0, 0, 0, NULL };\n    brealloc(&tmp, salt_len + tag_len + plaintext->len, capacity);\n    buffer_t *ciphertext = &tmp;\n    ciphertext->len = tag_len + plaintext->len;\n\n    /* copy salt to first pos */\n    memcpy(ciphertext->data, cipher_ctx.salt, salt_len);\n\n    ppbloom_add((void *)cipher_ctx.salt, salt_len);\n\n    aead_cipher_ctx_set_key(&cipher_ctx, 1);\n\n    size_t clen = ciphertext->len;\n    err = aead_cipher_encrypt(&cipher_ctx,\n                              (uint8_t *)ciphertext->data + salt_len, &clen,\n                              (uint8_t *)plaintext->data, plaintext->len,\n                              NULL, 0, cipher_ctx.nonce, cipher_ctx.skey);\n\n    aead_ctx_release(&cipher_ctx);\n\n    if (err)\n        return CRYPTO_ERROR;\n\n    assert(ciphertext->len == clen);\n\n    bswap_data(plaintext, ciphertext);\n    plaintext->len = salt_len + ciphertext->len;\n\n    return CRYPTO_OK;\n}\n\nint\naead_decrypt_all(buffer_t *ciphertext, cipher_t *cipher, size_t capacity)\n{\n    size_t salt_len = cipher->key_len;\n    size_t tag_len  = cipher->tag_len;\n    int err         = CRYPTO_OK;\n\n    if (ciphertext->len <= salt_len + tag_len) {\n        return CRYPTO_ERROR;\n    }\n\n    cipher_ctx_t cipher_ctx;\n    aead_ctx_init(cipher, &cipher_ctx, 0);\n\n    static buffer_t tmp = { 0, 0, 0, NULL };\n    brealloc(&tmp, ciphertext->len, capacity);\n    buffer_t *plaintext = &tmp;\n    plaintext->len = ciphertext->len - salt_len - tag_len;\n\n    /* get salt */\n    uint8_t *salt = cipher_ctx.salt;\n    memcpy(salt, ciphertext->data, salt_len);\n\n    if (ppbloom_check((void *)salt, salt_len) == 1) {\n        LOGE(\"crypto: AEAD: repeat salt detected\");\n        return CRYPTO_ERROR;\n    }\n\n    aead_cipher_ctx_set_key(&cipher_ctx, 0);\n\n    size_t plen = plaintext->len;\n    err = aead_cipher_decrypt(&cipher_ctx,\n                              (uint8_t *)plaintext->data, &plen,\n                              (uint8_t *)ciphertext->data + salt_len,\n                              ciphertext->len - salt_len, NULL, 0,\n                              cipher_ctx.nonce, cipher_ctx.skey);\n\n    aead_ctx_release(&cipher_ctx);\n\n    if (err)\n        return CRYPTO_ERROR;\n\n    ppbloom_add((void *)salt, salt_len);\n\n    bswap_data(ciphertext, plaintext);\n    ciphertext->len = plaintext->len;\n\n    return CRYPTO_OK;\n}\n\nstatic int\naead_chunk_encrypt(cipher_ctx_t *ctx, uint8_t *p, uint8_t *c,\n                   uint8_t *n, uint16_t plen)\n{\n    size_t nlen = ctx->cipher->nonce_len;\n    size_t tlen = ctx->cipher->tag_len;\n\n    assert(plen <= CHUNK_SIZE_MASK);\n\n    int err;\n    size_t clen;\n    uint8_t len_buf[CHUNK_SIZE_LEN];\n    uint16_t t = htons(plen & CHUNK_SIZE_MASK);\n    memcpy(len_buf, &t, CHUNK_SIZE_LEN);\n\n    clen = CHUNK_SIZE_LEN + tlen;\n    err  = aead_cipher_encrypt(ctx, c, &clen, len_buf, CHUNK_SIZE_LEN,\n                               NULL, 0, n, ctx->skey);\n    if (err)\n        return CRYPTO_ERROR;\n\n    assert(clen == CHUNK_SIZE_LEN + tlen);\n\n    sodium_increment(n, nlen);\n\n    clen = plen + tlen;\n    err  = aead_cipher_encrypt(ctx, c + CHUNK_SIZE_LEN + tlen, &clen, p, plen,\n                               NULL, 0, n, ctx->skey);\n    if (err)\n        return CRYPTO_ERROR;\n\n    assert(clen == plen + tlen);\n\n    sodium_increment(n, nlen);\n\n    return CRYPTO_OK;\n}\n\n/* TCP */\nint\naead_encrypt(buffer_t *plaintext, cipher_ctx_t *cipher_ctx, size_t capacity)\n{\n    if (cipher_ctx == NULL)\n        return CRYPTO_ERROR;\n\n    if (plaintext->len == 0) {\n        return CRYPTO_OK;\n    }\n\n    static buffer_t tmp = { 0, 0, 0, NULL };\n    buffer_t *ciphertext;\n\n    cipher_t *cipher = cipher_ctx->cipher;\n    int err          = CRYPTO_ERROR;\n    size_t salt_ofst = 0;\n    size_t salt_len  = cipher->key_len;\n    size_t tag_len   = cipher->tag_len;\n\n    if (!cipher_ctx->init) {\n        salt_ofst = salt_len;\n    }\n\n    size_t out_len = salt_ofst + 2 * tag_len + plaintext->len + CHUNK_SIZE_LEN;\n    brealloc(&tmp, out_len, capacity);\n    ciphertext      = &tmp;\n    ciphertext->len = out_len;\n\n    if (!cipher_ctx->init) {\n        memcpy(ciphertext->data, cipher_ctx->salt, salt_len);\n        aead_cipher_ctx_set_key(cipher_ctx, 1);\n        cipher_ctx->init = 1;\n\n        ppbloom_add((void *)cipher_ctx->salt, salt_len);\n    }\n\n    err = aead_chunk_encrypt(cipher_ctx,\n                             (uint8_t *)plaintext->data,\n                             (uint8_t *)ciphertext->data + salt_ofst,\n                             cipher_ctx->nonce, plaintext->len);\n    if (err)\n        return err;\n\n    bswap_data(plaintext, ciphertext);\n    plaintext->len = ciphertext->len;\n\n    return 0;\n}\n\nstatic int\naead_chunk_decrypt(cipher_ctx_t *ctx, uint8_t *p, uint8_t *c, uint8_t *n,\n                   size_t *plen, size_t *clen)\n{\n    int err;\n    size_t mlen;\n    size_t nlen = ctx->cipher->nonce_len;\n    size_t tlen = ctx->cipher->tag_len;\n\n    if (*clen <= 2 * tlen + CHUNK_SIZE_LEN)\n        return CRYPTO_NEED_MORE;\n\n    uint8_t len_buf[2];\n    err = aead_cipher_decrypt(ctx, len_buf, plen, c, CHUNK_SIZE_LEN + tlen,\n                              NULL, 0, n, ctx->skey);\n    if (err)\n        return CRYPTO_ERROR;\n    assert(*plen == CHUNK_SIZE_LEN);\n\n    mlen = load16_be(len_buf);\n    mlen = mlen & CHUNK_SIZE_MASK;\n\n    if (mlen == 0)\n        return CRYPTO_ERROR;\n\n    size_t chunk_len = 2 * tlen + CHUNK_SIZE_LEN + mlen;\n\n    if (*clen < chunk_len)\n        return CRYPTO_NEED_MORE;\n\n    sodium_increment(n, nlen);\n\n    err = aead_cipher_decrypt(ctx, p, plen, c + CHUNK_SIZE_LEN + tlen, mlen + tlen,\n                              NULL, 0, n, ctx->skey);\n    if (err)\n        return CRYPTO_ERROR;\n    assert(*plen == mlen);\n\n    sodium_increment(n, nlen);\n\n    *clen = *clen - chunk_len;\n\n    return CRYPTO_OK;\n}\n\nint\naead_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity)\n{\n    int err          = CRYPTO_OK;\n    cipher_t *cipher = cipher_ctx->cipher;\n\n    size_t salt_len = cipher->key_len;\n\n    if (cipher_ctx->chunk == NULL) {\n        cipher_ctx->chunk = (buffer_t *)ss_malloc(sizeof(buffer_t));\n        memset(cipher_ctx->chunk, 0, sizeof(buffer_t));\n        balloc(cipher_ctx->chunk, capacity);\n    }\n\n    buffer_t *chunk = cipher_ctx->chunk;\n\n    if (chunk->len == 0) {\n        bswap_data(chunk, ciphertext);\n        chunk->len = ciphertext->len;\n        chunk->idx = 0;\n        ciphertext->len = 0;\n    } else {\n        if (chunk->idx > 0) {\n            memmove(chunk->data, chunk->data + chunk->idx, chunk->len);\n            chunk->idx = 0;\n        }\n        brealloc(chunk, chunk->len + ciphertext->len, capacity);\n        memcpy(chunk->data + chunk->len,\n               ciphertext->data, ciphertext->len);\n        chunk->len += ciphertext->len;\n    }\n\n    // Write plaintext directly into the (now-free) ciphertext buffer.\n    brealloc(ciphertext, chunk->len, capacity);\n\n    if (!cipher_ctx->init) {\n        if (chunk->len <= salt_len)\n            return CRYPTO_NEED_MORE;\n\n        memcpy(cipher_ctx->salt, chunk->data + chunk->idx, salt_len);\n\n        if (ppbloom_check((void *)cipher_ctx->salt, salt_len) == 1) {\n            LOGE(\"crypto: AEAD: repeat salt detected\");\n            return CRYPTO_ERROR;\n        }\n\n        aead_cipher_ctx_set_key(cipher_ctx, 0);\n\n        chunk->idx += salt_len;\n        chunk->len -= salt_len;\n\n        cipher_ctx->init = 1;\n    }\n\n    size_t plen = 0;\n    size_t cidx = 0;\n    while (chunk->len > 0) {\n        size_t chunk_clen = chunk->len;\n        size_t chunk_plen = 0;\n        err = aead_chunk_decrypt(cipher_ctx,\n                                 (uint8_t *)ciphertext->data + plen,\n                                 (uint8_t *)chunk->data + chunk->idx + cidx,\n                                 cipher_ctx->nonce, &chunk_plen, &chunk_clen);\n        if (err == CRYPTO_ERROR) {\n            return err;\n        } else if (err == CRYPTO_NEED_MORE) {\n            if (plen == 0)\n                return err;\n            else {\n                chunk->idx += cidx;\n                break;\n            }\n        }\n        chunk->len = chunk_clen;\n        cidx += cipher_ctx->cipher->tag_len * 2 + CHUNK_SIZE_LEN + chunk_plen;\n        plen += chunk_plen;\n    }\n\n    if (chunk->len == 0)\n        chunk->idx = 0;\n\n    ciphertext->len = plen;\n\n    // Add the salt to bloom filter\n    if (cipher_ctx->init == 1) {\n        if (ppbloom_check((void *)cipher_ctx->salt, salt_len) == 1) {\n            LOGE(\"crypto: AEAD: repeat salt detected\");\n            return CRYPTO_ERROR;\n        }\n        ppbloom_add((void *)cipher_ctx->salt, salt_len);\n        cipher_ctx->init = 2;\n    }\n\n    return CRYPTO_OK;\n}\n\ncipher_t *\naead_key_init(int method, const char *pass, const char *key)\n{\n    if (method < AES128GCM || method >= AEAD_CIPHER_NUM) {\n        LOGE(\"aead_key_init(): Illegal method\");\n        return NULL;\n    }\n\n    cipher_t *cipher = (cipher_t *)ss_malloc(sizeof(cipher_t));\n    memset(cipher, 0, sizeof(cipher_t));\n\n    if (method < CHACHA20POLY1305IETF && aead_get_cipher_type(method) == NULL) {\n        LOGE(\"Cipher %s not found in crypto library\", supported_aead_ciphers[method]);\n        FATAL(\"Cannot initialize cipher\");\n    }\n\n    if (key != NULL)\n        cipher->key_len = crypto_parse_key(key, cipher->key,\n                                           supported_aead_ciphers_key_size[method]);\n    else\n        cipher->key_len = crypto_derive_key(pass, cipher->key,\n                                            supported_aead_ciphers_key_size[method]);\n\n    if (cipher->key_len == 0) {\n        FATAL(\"Cannot generate key and nonce\");\n    }\n\n    cipher->nonce_len = supported_aead_ciphers_nonce_size[method];\n    cipher->tag_len   = supported_aead_ciphers_tag_size[method];\n    cipher->method    = method;\n\n    return cipher;\n}\n\ncipher_t *\naead_init(const char *pass, const char *key, const char *method)\n{\n    int m = AES128GCM;\n    if (method != NULL) {\n        /* check method validity */\n        for (m = AES128GCM; m < AEAD_CIPHER_NUM; m++)\n            if (strcmp(method, supported_aead_ciphers[m]) == 0) {\n                break;\n            }\n        if (m >= AEAD_CIPHER_NUM) {\n            LOGE(\"Invalid cipher name: %s, use chacha20-ietf-poly1305 instead\", method);\n            m = CHACHA20POLY1305IETF;\n        }\n    }\n    return aead_key_init(m, pass, key);\n}\n"
  },
  {
    "path": "src/aead.h",
    "content": "/*\n * aead.h - Define the AEAD interface\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _AEAD_H\n#define _AEAD_H\n\n#include \"crypto.h\"\n\n// currently, XCHACHA20POLY1305IETF is not released yet\n// XCHACHA20POLY1305 is removed in upstream\n#ifdef FS_HAVE_XCHACHA20IETF\n#define AEAD_CIPHER_NUM              5\n#else\n#define AEAD_CIPHER_NUM              4\n#endif\n\nint aead_encrypt_all(buffer_t *, cipher_t *, size_t);\nint aead_decrypt_all(buffer_t *, cipher_t *, size_t);\n\nint aead_encrypt(buffer_t *, cipher_ctx_t *, size_t);\nint aead_decrypt(buffer_t *, cipher_ctx_t *, size_t);\n\nvoid aead_ctx_init(cipher_t *, cipher_ctx_t *, int);\nvoid aead_ctx_release(cipher_ctx_t *);\n\ncipher_t *aead_init(const char *pass, const char *key, const char *method);\n\n#endif // _AEAD_H\n"
  },
  {
    "path": "src/android.c",
    "content": "/*\n * android.c - Setup IPC for shadowsocks-android\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <fcntl.h>\n#include <locale.h>\n#include <signal.h>\n#include <string.h>\n#include <strings.h>\n#include <unistd.h>\n\n#include <errno.h>\n#include <arpa/inet.h>\n#include <netdb.h>\n#include <netinet/in.h>\n#include <netinet/tcp.h>\n\n#include <sys/un.h>\n#include <ancillary.h>\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include \"netutils.h\"\n#include \"utils.h\"\n\nint\nprotect_socket(int fd)\n{\n    int sock;\n    struct sockaddr_un addr;\n\n    if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {\n        LOGE(\"[android] socket() failed: %s (socket fd = %d)\\n\", strerror(errno), sock);\n        return -1;\n    }\n\n    // Set timeout to 3s\n    struct timeval tv;\n    tv.tv_sec  = 3;\n    tv.tv_usec = 0;\n    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));\n    setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval));\n\n    memset(&addr, 0, sizeof(addr));\n    addr.sun_family = AF_UNIX;\n    strncpy(addr.sun_path, \"protect_path\", sizeof(addr.sun_path) - 1);\n\n    if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {\n        LOGE(\"[android] connect() failed for protect_path: %s (socket fd = %d)\\n\",\n             strerror(errno), sock);\n        close(sock);\n        return -1;\n    }\n\n    if (ancil_send_fd(sock, fd)) {\n        ERROR(\"[android] ancil_send_fd\");\n        close(sock);\n        return -1;\n    }\n\n    char ret = 0;\n\n    if (recv(sock, &ret, 1, 0) == -1) {\n        ERROR(\"[android] recv\");\n        close(sock);\n        return -1;\n    }\n\n    close(sock);\n    return ret;\n}\n\nextern char *stat_path;\n\nint\nsend_traffic_stat(uint64_t tx, uint64_t rx)\n{\n    if (!stat_path)\n        return 0;\n    int sock;\n    struct sockaddr_un addr;\n\n    if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {\n        LOGE(\"[android] socket() failed: %s (socket fd = %d)\\n\", strerror(errno), sock);\n        return -1;\n    }\n\n    // Set timeout to 1s\n    struct timeval tv;\n    tv.tv_sec  = 1;\n    tv.tv_usec = 0;\n    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));\n    setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval));\n\n    memset(&addr, 0, sizeof(addr));\n    addr.sun_family = AF_UNIX;\n    strncpy(addr.sun_path, stat_path, sizeof(addr.sun_path) - 1);\n\n    if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {\n        LOGE(\"[android] connect() failed for stat_path: %s (socket fd = %d)\\n\",\n             strerror(errno), sock);\n        close(sock);\n        return -1;\n    }\n\n    uint64_t stat[2] = { tx, rx };\n\n    if (send(sock, stat, sizeof(stat), 0) == -1) {\n        ERROR(\"[android] send\");\n        close(sock);\n        return -1;\n    }\n\n    close(sock);\n    return 0;\n}\n"
  },
  {
    "path": "src/base64.c",
    "content": "/*\n * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @brief Base64 encode/decode\n * @author Ryan Martell <rdm4@martellventures.com> (with lots of Michael)\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <limits.h>\n#include <stddef.h>\n\n#include \"base64.h\"\n\n/* ---------------- private code */\nstatic const uint8_t map2[] =\n{\n    0xff, 0xff, 0x3e, 0xff, 0xff, 0x34, 0x35, 0x36,\n    0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,\n    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01,\n    0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,\n    0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,\n    0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,\n    0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0x1a, 0x1b,\n    0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,\n    0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,\n    0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33\n};\n\nint base64_decode(uint8_t *out, const char *in, int out_size)\n{\n    int i, v;\n    uint8_t *dst = out;\n\n    v = 0;\n    for (i = 0; in[i] && in[i] != '='; i++) {\n        unsigned int index = in[i] - 43;\n        if (index >= sizeof(map2) || map2[index] == 0xff)\n            return -1;\n        v = (v << 6) + map2[index];\n        if (i & 3) {\n            if (dst - out < out_size) {\n                *dst++ = v >> (6 - 2 * (i & 3));\n            }\n        }\n    }\n\n    return dst - out;\n}\n\n/*****************************************************************************\n* b64_encode: Stolen from VLC's http.c.\n* Simplified by Michael.\n* Fixed edge cases and made it work from data (vs. strings) by Ryan.\n*****************************************************************************/\n\nchar *base64_encode(char *out, int out_size, const uint8_t *in, int in_size)\n{\n    static const char b64[] =\n        \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n    char *ret, *dst;\n    unsigned i_bits = 0;\n    int i_shift = 0;\n    int bytes_remaining = in_size;\n\n    if (in_size >= UINT_MAX / 4 ||\n        out_size < BASE64_SIZE(in_size))\n        return NULL;\n    ret = dst = out;\n    while (bytes_remaining) {\n        i_bits = (i_bits << 8) + *in++;\n        bytes_remaining--;\n        i_shift += 8;\n\n        do {\n            *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];\n            i_shift -= 6;\n        } while (i_shift > 6 || (bytes_remaining == 0 && i_shift > 0));\n    }\n    while ((dst - ret) & 3)\n        *dst++ = '=';\n    *dst = '\\0';\n\n    return ret;\n}\n"
  },
  {
    "path": "src/base64.h",
    "content": "/*\n * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef BASE64_H\n#define BASE64_H\n\n#include <stdint.h>\n\n/**\n * Decode a base64-encoded string.\n *\n * @param out      buffer for decoded data\n * @param in       null-terminated input string\n * @param out_size size in bytes of the out buffer, must be at\n *                 least 3/4 of the length of in\n * @return         number of bytes written, or a negative value in case of\n *                 invalid input\n */\nint base64_decode(uint8_t *out, const char *in, int out_size);\n\n/**\n * Encode data to base64 and null-terminate.\n *\n * @param out      buffer for encoded data\n * @param out_size size in bytes of the output buffer, must be at\n *                 least BASE64_SIZE(in_size)\n * @param in_size  size in bytes of the 'in' buffer\n * @return         'out' or NULL in case of error\n */\nchar *base64_encode(char *out, int out_size, const uint8_t *in, int in_size);\n\n/**\n * Calculate the output size needed to base64-encode x bytes.\n */\n#define BASE64_SIZE(x)  (((x)+2) / 3 * 4 + 1)\n\n#endif /* BASE64_H */\n"
  },
  {
    "path": "src/cache.c",
    "content": "/*\n * cache.c - Manage the connection cache for UDPRELAY\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n/*\n * Original Author:  Oliver Lorenz (ol), olli@olorenz.org, https://olorenz.org\n * License:  This is licensed under the same terms as uthash itself\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <errno.h>\n#include <stdlib.h>\n\n#include \"cache.h\"\n#include \"utils.h\"\n\n/** Creates a new cache object\n *\n *  @param dst\n *  Where the newly allocated cache object will be stored in\n *\n *  @param capacity\n *  The maximum number of elements this cache object can hold\n *\n *  @return EINVAL if dst is NULL, ENOMEM if malloc fails, 0 otherwise\n */\nint\ncache_create(struct cache **dst, const size_t capacity,\n             void (*free_cb)(void *key, void *element))\n{\n    struct cache *new = NULL;\n\n    if (!dst) {\n        return EINVAL;\n    }\n\n    if ((new = malloc(sizeof(*new))) == NULL) {\n        return ENOMEM;\n    }\n\n    new->max_entries = capacity;\n    new->entries     = NULL;\n    new->free_cb     = free_cb;\n    *dst             = new;\n    return 0;\n}\n\n/** Frees an allocated cache object\n *\n *  @param cache\n *  The cache object to free\n *\n *  @param keep_data\n *  Whether to free contained data or just delete references to it\n *\n *  @return EINVAL if cache is NULL, 0 otherwise\n */\nint\ncache_delete(struct cache *cache, int keep_data)\n{\n    struct cache_entry *entry, *tmp;\n\n    if (!cache) {\n        return EINVAL;\n    }\n\n    if (keep_data) {\n        HASH_CLEAR(hh, cache->entries);\n    } else {\n        HASH_ITER(hh, cache->entries, entry, tmp){\n            HASH_DEL(cache->entries, entry);\n            if (entry->data != NULL) {\n                if (cache->free_cb) {\n                    cache->free_cb(entry->key, entry->data);\n                } else {\n                    ss_free(entry->data);\n                }\n            }\n            ss_free(entry->key);\n            ss_free(entry);\n        }\n    }\n\n    ss_free(cache);\n    return 0;\n}\n\n/** Clear old cache object\n *\n *  @param cache\n *  The cache object to clear\n *\n *  @param age\n *  Clear only objects older than the age (sec)\n *\n *  @return EINVAL if cache is NULL, 0 otherwise\n */\nint\ncache_clear(struct cache *cache, ev_tstamp age)\n{\n    struct cache_entry *entry, *tmp;\n\n    if (!cache) {\n        return EINVAL;\n    }\n\n    ev_tstamp now = ev_time();\n\n    HASH_ITER(hh, cache->entries, entry, tmp){\n        if (now - entry->ts > age) {\n            HASH_DEL(cache->entries, entry);\n            if (entry->data != NULL) {\n                if (cache->free_cb) {\n                    cache->free_cb(entry->key, entry->data);\n                } else {\n                    ss_free(entry->data);\n                }\n            }\n            ss_free(entry->key);\n            ss_free(entry);\n        }\n    }\n\n    return 0;\n}\n\n/** Removes a cache entry\n *\n *  @param cache\n *  The cache object\n *\n *  @param key\n *  The key of the entry to remove\n *\n *  @param key_len\n *  The length of key\n *\n *  @return EINVAL if cache is NULL, 0 otherwise\n */\nint\ncache_remove(struct cache *cache, char *key, size_t key_len)\n{\n    struct cache_entry *tmp;\n\n    if (!cache || !key) {\n        return EINVAL;\n    }\n\n    HASH_FIND(hh, cache->entries, key, key_len, tmp);\n\n    if (tmp) {\n        HASH_DEL(cache->entries, tmp);\n        if (tmp->data != NULL) {\n            if (cache->free_cb) {\n                cache->free_cb(tmp->key, tmp->data);\n            } else {\n                ss_free(tmp->data);\n            }\n        }\n        ss_free(tmp->key);\n        ss_free(tmp);\n    }\n\n    return 0;\n}\n\n/** Checks if a given key is in the cache\n *\n *  @param cache\n *  The cache object\n *\n *  @param key\n *  The key to look-up\n *\n *  @param key_len\n *  The length of key\n *\n *  @param result\n *  Where to store the result if key is found.\n *\n *  A warning: Even though result is just a pointer,\n *  you have to call this function with a **ptr,\n *  otherwise this will blow up in your face.\n *\n *  @return EINVAL if cache is NULL, 0 otherwise\n */\nint\ncache_lookup(struct cache *cache, char *key, size_t key_len, void *result)\n{\n    struct cache_entry *tmp = NULL;\n    char **dirty_hack       = result;\n\n    if (!cache || !key || !result) {\n        return EINVAL;\n    }\n\n    HASH_FIND(hh, cache->entries, key, key_len, tmp);\n    if (tmp) {\n        HASH_DELETE(hh, cache->entries, tmp);\n        tmp->ts = ev_time();\n        HASH_ADD_KEYPTR(hh, cache->entries, tmp->key, key_len, tmp);\n        *dirty_hack = tmp->data;\n    } else {\n        *dirty_hack = result = NULL;\n    }\n\n    return 0;\n}\n\nint\ncache_key_exist(struct cache *cache, char *key, size_t key_len)\n{\n    struct cache_entry *tmp = NULL;\n\n    if (!cache || !key) {\n        return 0;\n    }\n\n    HASH_FIND(hh, cache->entries, key, key_len, tmp);\n    if (tmp) {\n        HASH_DELETE(hh, cache->entries, tmp);\n        tmp->ts = ev_time();\n        HASH_ADD_KEYPTR(hh, cache->entries, tmp->key, key_len, tmp);\n        return 1;\n    }\n\n    return 0;\n}\n\n/** Inserts a given <key, value> pair into the cache\n *\n *  @param cache\n *  The cache object\n *\n *  @param key\n *  The key that identifies <value>\n *\n *  @param key_len\n *  The length of key\n *\n *  @param data\n *  Data associated with <key>\n *\n *  @return EINVAL if cache is NULL, ENOMEM if malloc fails, 0 otherwise\n */\nint\ncache_insert(struct cache *cache, char *key, size_t key_len, void *data)\n{\n    struct cache_entry *entry     = NULL;\n    struct cache_entry *tmp_entry = NULL;\n\n    if (!cache) {\n        return EINVAL;\n    }\n\n    if ((entry = malloc(sizeof(*entry))) == NULL) {\n        return ENOMEM;\n    }\n\n    entry->key = ss_malloc(key_len + 1);\n    memcpy(entry->key, key, key_len);\n    entry->key[key_len] = 0;\n\n    entry->data = data;\n    entry->ts   = ev_time();\n    HASH_ADD_KEYPTR(hh, cache->entries, entry->key, key_len, entry);\n\n    if (HASH_COUNT(cache->entries) >= cache->max_entries) {\n        HASH_ITER(hh, cache->entries, entry, tmp_entry){\n            HASH_DELETE(hh, cache->entries, entry);\n            if (entry->data != NULL) {\n                if (cache->free_cb) {\n                    cache->free_cb(entry->key, entry->data);\n                } else {\n                    ss_free(entry->data);\n                }\n            }\n            ss_free(entry->key);\n            ss_free(entry);\n            break;\n        }\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "src/cache.h",
    "content": "/*\n * cache.h - Define the cache manager interface\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n/*\n * Original Author:  Oliver Lorenz (ol), olli@olorenz.org, https://olorenz.org\n * License:  This is licensed under the same terms as uthash itself\n */\n\n#ifndef _CACHE_\n#define _CACHE_\n\n#include \"uthash.h\"\n\n#ifdef HAVE_LIBEV_EV_H\n#include <libev/ev.h>\n#else\n#include <ev.h>\n#endif\n\n/**\n * A cache entry\n */\nstruct cache_entry {\n    char *key;         /**<The key */\n    void *data;        /**<Payload */\n    ev_tstamp ts;    /**<Timestamp */\n    UT_hash_handle hh; /**<Hash Handle for uthash */\n};\n\n/**\n * A cache object\n */\nstruct cache {\n    size_t max_entries;              /**<Amount of entries this cache object can hold */\n    struct cache_entry *entries;     /**<Head pointer for uthash */\n    void (*free_cb)(void *key, void *element);  /**<Callback function to free cache entries */\n};\n\nint cache_create(struct cache **dst, const size_t capacity,\n                 void (*free_cb)(void *key, void *element));\nint cache_delete(struct cache *cache, int keep_data);\nint cache_clear(struct cache *cache, ev_tstamp age);\nint cache_lookup(struct cache *cache, char *key, size_t key_len, void *result);\nint cache_insert(struct cache *cache, char *key, size_t key_len, void *data);\nint cache_remove(struct cache *cache, char *key, size_t key_len);\nint cache_key_exist(struct cache *cache, char *key, size_t key_len);\n\n#endif\n"
  },
  {
    "path": "src/common.h",
    "content": "/*\n * common.h - Provide global definitions\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _COMMON_H\n#define _COMMON_H\n\n#ifndef SOL_TCP\n#define SOL_TCP IPPROTO_TCP\n#endif\n\n#if defined(MODULE_TUNNEL) || defined(MODULE_REDIR)\n#define MODULE_LOCAL\n#endif\n\n#include \"crypto.h\"\n\nint init_udprelay(const char *server_host, const char *server_port,\n#ifdef MODULE_LOCAL\n                  const struct sockaddr *remote_addr, const int remote_addr_len,\n#ifdef MODULE_TUNNEL\n                  const ss_addr_t tunnel_addr,\n#endif\n#endif\n                  int mtu, crypto_t *crypto, int timeout, const char *iface);\n\nvoid free_udprelay(void);\n\n#ifdef __ANDROID__\nint protect_socket(int fd);\nint send_traffic_stat(uint64_t tx, uint64_t rx);\n#endif\n\n#define STAGE_ERROR     -1  /* Error detected                   */\n#define STAGE_INIT       0  /* Initial stage                    */\n#define STAGE_HANDSHAKE  1  /* Handshake with client            */\n#define STAGE_RESOLVE    4  /* Resolve the hostname             */\n#define STAGE_STREAM     5  /* Stream between client and server */\n#define STAGE_STOP       6  /* Server stop to response          */\n\n/* Vals for long options */\nenum {\n    GETOPT_VAL_HELP = 257,\n    GETOPT_VAL_REUSE_PORT,\n    GETOPT_VAL_FAST_OPEN,\n    GETOPT_VAL_NODELAY,\n    GETOPT_VAL_ACL,\n    GETOPT_VAL_MTU,\n    GETOPT_VAL_MPTCP,\n    GETOPT_VAL_PLUGIN,\n    GETOPT_VAL_PLUGIN_OPTS,\n    GETOPT_VAL_PASSWORD,\n    GETOPT_VAL_KEY,\n    GETOPT_VAL_MANAGER_ADDRESS,\n    GETOPT_VAL_EXECUTABLE,\n    GETOPT_VAL_WORKDIR,\n    GETOPT_VAL_TCP_INCOMING_SNDBUF,\n    GETOPT_VAL_TCP_INCOMING_RCVBUF,\n    GETOPT_VAL_TCP_OUTGOING_SNDBUF,\n    GETOPT_VAL_TCP_OUTGOING_RCVBUF,\n    GETOPT_VAL_NFTABLES_SETS\n};\n\n#endif // _COMMON_H\n"
  },
  {
    "path": "src/crypto.c",
    "content": "/*\n * crypto.c - Manage the global crypto\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#if defined(__linux__) && defined(HAVE_LINUX_RANDOM_H)\n#include <fcntl.h>\n#include <unistd.h>\n#include <sys/ioctl.h>\n#include <linux/random.h>\n#endif\n\n#include <stdint.h>\n#include <sodium.h>\n#include <mbedtls/version.h>\n#include <mbedtls/md5.h>\n\n#include \"base64.h\"\n#include \"crypto.h\"\n#include \"stream.h\"\n#include \"aead.h\"\n#include \"utils.h\"\n#include \"ppbloom.h\"\n\nint\nballoc(buffer_t *ptr, size_t capacity)\n{\n    sodium_memzero(ptr, sizeof(buffer_t));\n    ptr->data     = ss_malloc(capacity);\n    ptr->capacity = capacity;\n    return capacity;\n}\n\nint\nbrealloc(buffer_t *ptr, size_t len, size_t capacity)\n{\n    if (ptr == NULL)\n        return -1;\n    size_t real_capacity = max(len, capacity);\n    if (ptr->capacity < real_capacity) {\n        ptr->data     = ss_realloc(ptr->data, real_capacity);\n        ptr->capacity = real_capacity;\n    }\n    return real_capacity;\n}\n\nvoid\nbfree(buffer_t *ptr)\n{\n    if (ptr == NULL)\n        return;\n    ptr->idx      = 0;\n    ptr->len      = 0;\n    ptr->capacity = 0;\n    if (ptr->data != NULL) {\n        ss_free(ptr->data);\n    }\n}\n\nint\nbprepend(buffer_t *dst, buffer_t *src, size_t capacity)\n{\n    brealloc(dst, dst->len + src->len, capacity);\n    memmove(dst->data + src->len, dst->data, dst->len);\n    memcpy(dst->data, src->data, src->len);\n    dst->len = dst->len + src->len;\n    return dst->len;\n}\n\nint\nrand_bytes(void *output, int len)\n{\n    randombytes_buf(output, len);\n    // always return success\n    return 0;\n}\n\nunsigned char *\ncrypto_md5(const unsigned char *d, size_t n, unsigned char *md)\n{\n    static unsigned char m[16];\n    if (md == NULL) {\n        md = m;\n    }\n#if MBEDTLS_VERSION_NUMBER < 0x03000000 && MBEDTLS_VERSION_NUMBER >= 0x02070000\n    if (mbedtls_md5_ret(d, n, md) != 0)\n        FATAL(\"Failed to calculate MD5\");\n#else\n    mbedtls_md5(d, n, md);\n#endif\n    return md;\n}\n\nstatic void\nentropy_check(void)\n{\n#if defined(__linux__) && defined(HAVE_LINUX_RANDOM_H) && defined(RNDGETENTCNT)\n    int fd;\n    int c;\n\n    if ((fd = open(\"/dev/random\", O_RDONLY)) != -1) {\n        if (ioctl(fd, RNDGETENTCNT, &c) == 0 && c < 160) {\n            LOGI(\"This system doesn't provide enough entropy to quickly generate high-quality random numbers.\\n\"\n                 \"Installing the rng-utils/rng-tools, jitterentropy or haveged packages may help.\\n\"\n                 \"On virtualized Linux environments, also consider using virtio-rng.\\n\"\n                 \"The service will not start until enough entropy has been collected.\\n\");\n        }\n        close(fd);\n    }\n#endif\n}\n\ncrypto_t *\ncrypto_init(const char *password, const char *key, const char *method)\n{\n    int i, m = -1;\n\n    entropy_check();\n    // Initialize sodium for random generator\n    if (sodium_init() == -1) {\n        FATAL(\"Failed to initialize sodium\");\n    }\n\n    // Initialize NONCE bloom filter\n#ifdef MODULE_REMOTE\n    ppbloom_init(BF_NUM_ENTRIES_FOR_SERVER, BF_ERROR_RATE_FOR_SERVER);\n#else\n    ppbloom_init(BF_NUM_ENTRIES_FOR_CLIENT, BF_ERROR_RATE_FOR_CLIENT);\n#endif\n\n    if (method != NULL) {\n        for (i = 0; i < STREAM_CIPHER_NUM; i++)\n            if (strcmp(method, supported_stream_ciphers[i]) == 0) {\n                m = i;\n                break;\n            }\n        if (m != -1) {\n            LOGI(\"Stream ciphers are insecure, therefore deprecated, and should be almost always avoided.\");\n            cipher_t *cipher = stream_init(password, key, method);\n            if (cipher == NULL)\n                return NULL;\n            crypto_t *crypto = (crypto_t *)ss_malloc(sizeof(crypto_t));\n            crypto_t tmp     = {\n                .cipher      = cipher,\n                .encrypt_all = &stream_encrypt_all,\n                .decrypt_all = &stream_decrypt_all,\n                .encrypt     = &stream_encrypt,\n                .decrypt     = &stream_decrypt,\n                .ctx_init    = &stream_ctx_init,\n                .ctx_release = &stream_ctx_release,\n            };\n            memcpy(crypto, &tmp, sizeof(crypto_t));\n            return crypto;\n        }\n\n        for (i = 0; i < AEAD_CIPHER_NUM; i++)\n            if (strcmp(method, supported_aead_ciphers[i]) == 0) {\n                m = i;\n                break;\n            }\n        if (m != -1) {\n            cipher_t *cipher = aead_init(password, key, method);\n            if (cipher == NULL)\n                return NULL;\n            crypto_t *crypto = (crypto_t *)ss_malloc(sizeof(crypto_t));\n            crypto_t tmp     = {\n                .cipher      = cipher,\n                .encrypt_all = &aead_encrypt_all,\n                .decrypt_all = &aead_decrypt_all,\n                .encrypt     = &aead_encrypt,\n                .decrypt     = &aead_decrypt,\n                .ctx_init    = &aead_ctx_init,\n                .ctx_release = &aead_ctx_release,\n            };\n            memcpy(crypto, &tmp, sizeof(crypto_t));\n            return crypto;\n        }\n    }\n\n    LOGE(\"invalid cipher name: %s\", method);\n    return NULL;\n}\n\nint\ncrypto_derive_key(const char *pass, uint8_t *key, size_t key_len)\n{\n    size_t datal;\n    datal = strlen((const char *)pass);\n\n    const digest_type_t *md = mbedtls_md_info_from_string(\"MD5\");\n    if (md == NULL) {\n        FATAL(\"MD5 Digest not found in crypto library\");\n    }\n\n    mbedtls_md_context_t c;\n    unsigned char md_buf[MAX_MD_SIZE];\n    int addmd;\n    unsigned int i, j, mds;\n\n    mds = mbedtls_md_get_size(md);\n    memset(&c, 0, sizeof(mbedtls_md_context_t));\n\n    if (pass == NULL)\n        return key_len;\n    if (mbedtls_md_setup(&c, md, 0))\n        return 0;\n\n    for (j = 0, addmd = 0; j < key_len; addmd++) {\n        mbedtls_md_starts(&c);\n        if (addmd) {\n            mbedtls_md_update(&c, md_buf, mds);\n        }\n        mbedtls_md_update(&c, (uint8_t *)pass, datal);\n        mbedtls_md_finish(&c, &(md_buf[0]));\n\n        for (i = 0; i < mds; i++, j++) {\n            if (j >= key_len)\n                break;\n            key[j] = md_buf[i];\n        }\n    }\n\n    mbedtls_md_free(&c);\n    return key_len;\n}\n\n/* HKDF-Extract + HKDF-Expand */\nint\ncrypto_hkdf(const mbedtls_md_info_t *md, const unsigned char *salt,\n            int salt_len, const unsigned char *ikm, int ikm_len,\n            const unsigned char *info, int info_len, unsigned char *okm,\n            int okm_len)\n{\n    unsigned char prk[MBEDTLS_MD_MAX_SIZE];\n\n    return crypto_hkdf_extract(md, salt, salt_len, ikm, ikm_len, prk) ||\n           crypto_hkdf_expand(md, prk, mbedtls_md_get_size(md), info, info_len,\n                              okm, okm_len);\n}\n\n/* HKDF-Extract(salt, IKM) -> PRK */\nint\ncrypto_hkdf_extract(const mbedtls_md_info_t *md, const unsigned char *salt,\n                    int salt_len, const unsigned char *ikm, int ikm_len,\n                    unsigned char *prk)\n{\n    int hash_len;\n    unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\\0' };\n\n    if (salt_len < 0) {\n        return CRYPTO_ERROR;\n    }\n\n    hash_len = mbedtls_md_get_size(md);\n\n    if (salt == NULL) {\n        salt     = null_salt;\n        salt_len = hash_len;\n    }\n\n    return mbedtls_md_hmac(md, salt, salt_len, ikm, ikm_len, prk);\n}\n\n/* HKDF-Expand(PRK, info, L) -> OKM */\nint\ncrypto_hkdf_expand(const mbedtls_md_info_t *md, const unsigned char *prk,\n                   int prk_len, const unsigned char *info, int info_len,\n                   unsigned char *okm, int okm_len)\n{\n    int hash_len;\n    int N;\n    int T_len = 0, where = 0, i, ret;\n    mbedtls_md_context_t ctx;\n    unsigned char T[MBEDTLS_MD_MAX_SIZE];\n\n    if (info_len < 0 || okm_len < 0 || okm == NULL) {\n        return CRYPTO_ERROR;\n    }\n\n    hash_len = mbedtls_md_get_size(md);\n\n    if (prk_len < hash_len) {\n        return CRYPTO_ERROR;\n    }\n\n    if (info == NULL) {\n        info = (const unsigned char *)\"\";\n    }\n\n    N = okm_len / hash_len;\n\n    if ((okm_len % hash_len) != 0) {\n        N++;\n    }\n\n    if (N > 255) {\n        return CRYPTO_ERROR;\n    }\n\n    mbedtls_md_init(&ctx);\n\n    if ((ret = mbedtls_md_setup(&ctx, md, 1)) != 0) {\n        mbedtls_md_free(&ctx);\n        return ret;\n    }\n\n    /* Section 2.3. */\n    for (i = 1; i <= N; i++) {\n        unsigned char c = i;\n\n        ret = mbedtls_md_hmac_starts(&ctx, prk, prk_len) ||\n              mbedtls_md_hmac_update(&ctx, T, T_len) ||\n              mbedtls_md_hmac_update(&ctx, info, info_len) ||\n              /* The constant concatenated to the end of each T(n) is a single\n               * octet. */\n              mbedtls_md_hmac_update(&ctx, &c, 1) ||\n              mbedtls_md_hmac_finish(&ctx, T);\n\n        if (ret != 0) {\n            mbedtls_md_free(&ctx);\n            return ret;\n        }\n\n        memcpy(okm + where, T, (i != N) ? hash_len : (okm_len - where));\n        where += hash_len;\n        T_len  = hash_len;\n    }\n\n    mbedtls_md_free(&ctx);\n\n    return 0;\n}\n\nint\ncrypto_parse_key(const char *base64, uint8_t *key, size_t key_len)\n{\n    size_t base64_len = strlen(base64);\n    int out_len       = BASE64_SIZE(base64_len);\n    uint8_t out[out_len];\n\n    out_len = base64_decode(out, base64, out_len);\n    if (out_len > 0 && out_len >= key_len) {\n        memcpy(key, out, key_len);\n#ifdef SS_DEBUG\n        dump(\"KEY\", (char *)key, key_len);\n#endif\n        return key_len;\n    }\n\n    out_len = BASE64_SIZE(key_len);\n    char out_key[out_len];\n    rand_bytes(key, key_len);\n    base64_encode(out_key, out_len, key, key_len);\n    LOGE(\"Invalid key for your chosen cipher!\");\n    LOGE(\"It requires a \" SIZE_FMT \"-byte key encoded with URL-safe Base64\", key_len);\n    LOGE(\"Generating a new random key: %s\", out_key);\n    FATAL(\"Please use the key above or input a valid key\");\n    return key_len;\n}\n\n#ifdef SS_DEBUG\nvoid\ndump(char *tag, char *text, int len)\n{\n    int i;\n    printf(\"%s: \", tag);\n    for (i = 0; i < len; i++)\n        printf(\"0x%02x \", (uint8_t)text[i]);\n    printf(\"\\n\");\n}\n\n#endif\n"
  },
  {
    "path": "src/crypto.h",
    "content": "/*\n * crypto.h - Define the enryptor's interface\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have recenonceed a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _CRYPTO_H\n#define _CRYPTO_H\n\n#ifndef __MINGW32__\n#include <sys/socket.h>\n#endif\n#include <string.h>\n#include <stdlib.h>\n#include <stdio.h>\n\n#ifdef HAVE_STDINT_H\n#include <stdint.h>\n#elif HAVE_INTTYPES_H\n#include <inttypes.h>\n#endif\n\n/* Definitions for libsodium */\n#include <sodium.h>\ntypedef crypto_aead_aes256gcm_state aes256gcm_ctx;\n/* Definitions for mbedTLS */\n#include <mbedtls/cipher.h>\n#include <mbedtls/md.h>\ntypedef mbedtls_cipher_info_t cipher_kt_t;\ntypedef mbedtls_cipher_context_t cipher_evp_t;\ntypedef mbedtls_md_info_t digest_type_t;\n#define MAX_KEY_LENGTH 64\n#define MAX_NONCE_LENGTH 32\n#define MAX_MD_SIZE MBEDTLS_MD_MAX_SIZE\n/* we must have MBEDTLS_CIPHER_MODE_CFB defined */\n#if !defined(MBEDTLS_CIPHER_MODE_CFB)\n#error Cipher Feedback mode a.k.a CFB not supported by your mbed TLS.\n#endif\n#ifndef MBEDTLS_GCM_C\n#error No GCM support detected\n#endif\n#ifdef crypto_aead_xchacha20poly1305_ietf_ABYTES\n#define FS_HAVE_XCHACHA20IETF\n#endif\n\n#define ADDRTYPE_MASK 0xF\n\n#define CRYPTO_ERROR     -2\n#define CRYPTO_NEED_MORE -1\n#define CRYPTO_OK         0\n\n#define min(a, b) (((a) < (b)) ? (a) : (b))\n#define max(a, b) (((a) > (b)) ? (a) : (b))\n\n#define SUBKEY_INFO \"ss-subkey\"\n#define IV_INFO \"ss-iv\"\n\n#ifndef BF_NUM_ENTRIES_FOR_SERVER\n#define BF_NUM_ENTRIES_FOR_SERVER 1e6\n#endif\n\n#ifndef BF_NUM_ENTRIES_FOR_CLIENT\n#define BF_NUM_ENTRIES_FOR_CLIENT 1e4\n#endif\n\n#ifndef BF_ERROR_RATE_FOR_SERVER\n#define BF_ERROR_RATE_FOR_SERVER 1e-10\n#endif\n\n#ifndef BF_ERROR_RATE_FOR_CLIENT\n#define BF_ERROR_RATE_FOR_CLIENT 1e-15\n#endif\n\ntypedef struct buffer {\n    size_t idx;\n    size_t len;\n    size_t capacity;\n    char   *data;\n} buffer_t;\n\ntypedef struct {\n    int method;\n    int skey;\n    size_t nonce_len;\n    size_t key_len;\n    size_t tag_len;\n    uint8_t key[MAX_KEY_LENGTH];\n} cipher_t;\n\ntypedef struct {\n    uint32_t init;\n    uint64_t counter;\n    cipher_evp_t *evp;\n    aes256gcm_ctx *aes256gcm_ctx;\n    cipher_t *cipher;\n    buffer_t *chunk;\n    uint8_t salt[MAX_KEY_LENGTH];\n    uint8_t skey[MAX_KEY_LENGTH];\n    uint8_t nonce[MAX_NONCE_LENGTH];\n} cipher_ctx_t;\n\ntypedef struct crypto {\n    cipher_t *cipher;\n\n    int(*const encrypt_all) (buffer_t *, cipher_t *, size_t);\n    int(*const decrypt_all) (buffer_t *, cipher_t *, size_t);\n    int(*const encrypt) (buffer_t *, cipher_ctx_t *, size_t);\n    int(*const decrypt) (buffer_t *, cipher_ctx_t *, size_t);\n\n    void(*const ctx_init) (cipher_t *, cipher_ctx_t *, int);\n    void(*const ctx_release) (cipher_ctx_t *);\n} crypto_t;\n\nint balloc(buffer_t *, size_t);\nint brealloc(buffer_t *, size_t, size_t);\nint bprepend(buffer_t *, buffer_t *, size_t);\nvoid bfree(buffer_t *);\n\nstatic inline void\nbswap_data(buffer_t *a, buffer_t *b)\n{\n    char *tmp_data      = a->data;\n    size_t tmp_capacity = a->capacity;\n    a->data             = b->data;\n    a->capacity         = b->capacity;\n    b->data             = tmp_data;\n    b->capacity         = tmp_capacity;\n}\n\nint rand_bytes(void *, int);\n\ncrypto_t *crypto_init(const char *, const char *, const char *);\nunsigned char *crypto_md5(const unsigned char *, size_t, unsigned char *);\n\nint crypto_derive_key(const char *, uint8_t *, size_t);\nint crypto_parse_key(const char *, uint8_t *, size_t);\nint crypto_hkdf(const mbedtls_md_info_t *md, const unsigned char *salt,\n                int salt_len, const unsigned char *ikm, int ikm_len,\n                const unsigned char *info, int info_len, unsigned char *okm,\n                int okm_len);\nint crypto_hkdf_extract(const mbedtls_md_info_t *md, const unsigned char *salt,\n                        int salt_len, const unsigned char *ikm, int ikm_len,\n                        unsigned char *prk);\nint crypto_hkdf_expand(const mbedtls_md_info_t *md, const unsigned char *prk,\n                       int prk_len, const unsigned char *info, int info_len,\n                       unsigned char *okm, int okm_len);\n#ifdef SS_DEBUG\nvoid dump(char *tag, char *text, int len);\n#endif\n\nextern struct cache *nonce_cache;\nextern const char *supported_stream_ciphers[];\nextern const char *supported_aead_ciphers[];\n\n#endif // _CRYPTO_H\n"
  },
  {
    "path": "src/jconf.c",
    "content": "/*\n * jconf.c - Parse the JSON format config file\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <unistd.h>\n#include <string.h>\n#include <time.h>\n\n#include \"netutils.h\"\n#include \"utils.h\"\n#include \"jconf.h\"\n#include \"json.h\"\n#include \"string.h\"\n\n#include <libcork/core.h>\n\n#define check_json_value_type(value, expected_type, message) \\\n    do { \\\n        if ((value)->type != (expected_type)) \\\n            FATAL((message)); \\\n    } while (0)\n\nstatic char *\nto_string(const json_value *value)\n{\n    if (value->type == json_string) {\n        return ss_strndup(value->u.string.ptr, value->u.string.length);\n    } else if (value->type == json_integer) {\n        return strdup(ss_itoa(value->u.integer));\n    } else if (value->type == json_null) {\n        return NULL;\n    } else {\n        LOGE(\"%d\", value->type);\n        FATAL(\"Invalid config format.\");\n    }\n    return 0;\n}\n\nvoid\nfree_addr(ss_addr_t *addr)\n{\n    ss_free(addr->host);\n    ss_free(addr->port);\n}\n\nvoid\nparse_addr(const char *str_in, ss_addr_t *addr)\n{\n    if (str_in == NULL)\n        return;\n\n    int ipv6 = 0, ret = -1, n = 0, len;\n    char *pch;\n    char *str = strdup(str_in);\n    len = strlen(str_in);\n\n    struct cork_ip ip;\n    if (cork_ip_init(&ip, str) != -1) {\n        addr->host = str;\n        addr->port = NULL;\n        return;\n    }\n\n    pch = strchr(str, ':');\n    while (pch != NULL) {\n        n++;\n        ret = pch - str;\n        pch = strchr(pch + 1, ':');\n    }\n\n    if (n > 1) {\n        ipv6 = 1;\n        if (str[ret - 1] != ']') {\n            ret = -1;\n        }\n    }\n\n    if (ret == -1) {\n        if (ipv6) {\n            addr->host = ss_strndup(str + 1, strlen(str) - 2);\n        } else {\n            addr->host = strdup(str);\n        }\n        addr->port = NULL;\n    } else {\n        if (ipv6) {\n            addr->host = ss_strndup(str + 1, ret - 2);\n        } else {\n            addr->host = ss_strndup(str, ret);\n        }\n        if (ret < len - 1) {\n            addr->port = strdup(str + ret + 1);\n        } else {\n            addr->port = NULL;\n        }\n    }\n\n    free(str);\n}\n\nstatic int\nparse_dscp(char *str)\n{\n    size_t str_len = strlen(str);\n\n    // Pre-defined values (EF, CSx, AFxy)\n    if (str_len == 2 && strcasecmp(str, \"EF\") == 0) {\n        return DSCP_EF;\n    }\n\n    if (str_len == DSCP_CS_LEN && strncasecmp(str, \"CS\", 2) == 0) {\n        if (str[2] >= '0' && str[2] <= '7') {\n            // CSx = 8x\n            return (str[2] - '0') << 3;\n        }\n    }\n\n    if (str_len == DSCP_AF_LEN && strncasecmp(str, \"AF\", 2) == 0) {\n        if (str[2] >= '1' && str[2] <= '4' && str[3] >= '1' && str[3] <= '3') {\n            // AFxy = 8x + 2y\n            return ((str[2] - '0') << 3) | ((str[3] - '0') << 1);\n        }\n    }\n\n    // Manual hexadecimal mode (0xYZ)\n    char *endptr;\n    int dscp = (int)strtol(str, &endptr, 0);\n    if (*endptr == '\\0' && dscp >= DSCP_MIN && dscp <= DSCP_MAX) {\n        return dscp;\n    }\n\n    LOGE(\"Invalid DSCP value (%s)\", str);\n    return DSCP_DEFAULT;\n}\n\njconf_t *\nread_jconf(const char *file)\n{\n    static jconf_t conf;\n\n    memset(&conf, 0, sizeof(jconf_t));\n\n    char *buf;\n    json_value *obj;\n\n    FILE *f = fopen(file, \"rb\");\n    if (f == NULL) {\n        FATAL(\"Invalid config path.\");\n    }\n\n    fseek(f, 0, SEEK_END);\n    long pos = ftell(f);\n    fseek(f, 0, SEEK_SET);\n\n    if (pos < 0) {\n        FATAL(\"Invalid config path.\");\n    }\n\n    if (pos >= MAX_CONF_SIZE) {\n        FATAL(\"Too large config file.\");\n    }\n\n    buf = ss_malloc(pos + 1);\n    if (buf == NULL) {\n        FATAL(\"No enough memory.\");\n    }\n\n    int nread = fread(buf, pos, 1, f);\n    if (!nread) {\n        FATAL(\"Failed to read the config file.\");\n    }\n    fclose(f);\n\n    buf[pos] = '\\0'; // end of string\n\n    json_settings settings = { 0UL, 0, NULL, NULL, NULL };\n    char error_buf[512];\n    obj = json_parse_ex(&settings, buf, pos, error_buf);\n\n    if (obj == NULL) {\n        FATAL(error_buf);\n    }\n\n    if (obj->type == json_object) {\n        unsigned int i, j;\n        for (i = 0; i < obj->u.object.length; i++) {\n            char *name        = obj->u.object.values[i].name;\n            json_value *value = obj->u.object.values[i].value;\n            if (strcmp(name, \"server\") == 0) {\n                if (value->type == json_array) {\n                    for (j = 0; j < value->u.array.length; j++) {\n                        if (j >= MAX_REMOTE_NUM) {\n                            break;\n                        }\n                        json_value *v  = value->u.array.values[j];\n                        char *addr_str = to_string(v);\n                        parse_addr(addr_str, conf.remote_addr + j);\n                        ss_free(addr_str);\n                        conf.remote_num = j + 1;\n                    }\n                } else if (value->type == json_string) {\n                    char* tmp_str = to_string(value);\n                    parse_addr(tmp_str, conf.remote_addr);\n                    ss_free(tmp_str);\n                    conf.remote_num = 1;\n                }\n            } else if (strcmp(name, \"port_password\") == 0) {\n                if (value->type == json_object) {\n                    for (j = 0; j < value->u.object.length; j++) {\n                        if (j >= MAX_PORT_NUM) {\n                            break;\n                        }\n                        json_value *v = value->u.object.values[j].value;\n                        if (v->type == json_string) {\n                            conf.port_password[j].port = ss_strndup(value->u.object.values[j].name,\n                                                                    value->u.object.values[j].name_length);\n                            conf.port_password[j].password = to_string(v);\n                            conf.port_password_num         = j + 1;\n                        }\n                    }\n                }\n            } else if (strcmp(name, \"server_port\") == 0) {\n                conf.remote_port = to_string(value);\n            } else if (strcmp(name, \"local_address\") == 0) {\n                conf.local_addr = to_string(value);\n            } else if (strcmp(name, \"local_ipv4_address\") == 0) {\n                conf.local_addr_v4 = to_string(value);\n            } else if (strcmp(name, \"local_ipv6_address\") == 0) {\n                conf.local_addr_v6 = to_string(value);\n            } else if (strcmp(name, \"local_port\") == 0) {\n                conf.local_port = to_string(value);\n            } else if (strcmp(name, \"password\") == 0) {\n                conf.password = to_string(value);\n            } else if (strcmp(name, \"key\") == 0) {\n                conf.key = to_string(value);\n            } else if (strcmp(name, \"method\") == 0) {\n                conf.method = to_string(value);\n            } else if (strcmp(name, \"timeout\") == 0) {\n                conf.timeout = to_string(value);\n            } else if (strcmp(name, \"user\") == 0) {\n                conf.user = to_string(value);\n            } else if (strcmp(name, \"plugin\") == 0) {\n                conf.plugin = to_string(value);\n                if (conf.plugin && strlen(conf.plugin) == 0) {\n                    ss_free(conf.plugin);\n                    conf.plugin = NULL;\n                }\n            } else if (strcmp(name, \"plugin_opts\") == 0) {\n                conf.plugin_opts = to_string(value);\n            } else if (strcmp(name, \"fast_open\") == 0) {\n                check_json_value_type(value, json_boolean,\n                                      \"invalid config file: option 'fast_open' must be a boolean\");\n                conf.fast_open = value->u.boolean;\n            } else if (strcmp(name, \"reuse_port\") == 0) {\n                check_json_value_type(value, json_boolean,\n                                      \"invalid config file: option 'reuse_port' must be a boolean\");\n                conf.reuse_port = value->u.boolean;\n            } else if (strcmp(name, \"tcp_incoming_sndbuf\") == 0) {\n                check_json_value_type(value, json_integer,\n                                      \"invalid config file: option 'tcp_incoming_sndbuf' must be an integer\");\n                conf.tcp_incoming_sndbuf = value->u.integer;\n            } else if (strcmp(name, \"tcp_incoming_rcvbuf\") == 0) {\n                check_json_value_type(value, json_integer,\n                                      \"invalid config file: option 'tcp_incoming_rcvbuf' must be an integer\");\n                conf.tcp_incoming_rcvbuf = value->u.integer;\n            } else if (strcmp(name, \"tcp_outgoing_sndbuf\") == 0) {\n                check_json_value_type(value, json_integer,\n                                      \"invalid config file: option 'tcp_outgoing_sndbuf' must be an integer\");\n                conf.tcp_outgoing_sndbuf = value->u.integer;\n            } else if (strcmp(name, \"tcp_outgoing_rcvbuf\") == 0) {\n                check_json_value_type(value, json_integer,\n                                      \"invalid config file: option 'tcp_outgoing_rcvbuf' must be an integer\");\n                conf.tcp_outgoing_rcvbuf = value->u.integer;\n            } else if (strcmp(name, \"auth\") == 0) {\n                FATAL(\"One time auth has been deprecated. Try AEAD ciphers instead.\");\n            } else if (strcmp(name, \"nofile\") == 0) {\n                check_json_value_type(value, json_integer,\n                                      \"invalid config file: option 'nofile' must be an integer\");\n                conf.nofile = value->u.integer;\n            } else if (strcmp(name, \"nameserver\") == 0) {\n                conf.nameserver = to_string(value);\n            } else if (strcmp(name, \"dscp\") == 0) {\n                if (value->type == json_object) {\n                    for (j = 0; j < value->u.object.length; j++) {\n                        if (j >= MAX_DSCP_NUM) {\n                            break;\n                        }\n                        json_value *v = value->u.object.values[j].value;\n                        if (v->type == json_string) {\n                            int dscp   = parse_dscp(to_string(v));\n                            char *port = ss_strndup(value->u.object.values[j].name,\n                                                    value->u.object.values[j].name_length);\n                            conf.dscp[j].port = port;\n                            conf.dscp[j].dscp = dscp;\n                            conf.dscp_num     = j + 1;\n                        }\n                    }\n                }\n            } else if (strcmp(name, \"tunnel_address\") == 0) {\n                conf.tunnel_address = to_string(value);\n            } else if (strcmp(name, \"mode\") == 0) {\n                char *mode_str = to_string(value);\n\n                if (mode_str == NULL)\n                    conf.mode = TCP_ONLY;\n                else if (strcmp(mode_str, \"tcp_only\") == 0)\n                    conf.mode = TCP_ONLY;\n                else if (strcmp(mode_str, \"tcp_and_udp\") == 0)\n                    conf.mode = TCP_AND_UDP;\n                else if (strcmp(mode_str, \"udp_only\") == 0)\n                    conf.mode = UDP_ONLY;\n                else\n                    LOGI(\"ignore unknown mode: %s, use tcp_only as fallback\",\n                         mode_str);\n\n                ss_free(mode_str);\n            } else if (strcmp(name, \"mtu\") == 0) {\n                check_json_value_type(value, json_integer,\n                                      \"invalid config file: option 'mtu' must be an integer\");\n                conf.mtu = value->u.integer;\n            } else if (strcmp(name, \"mptcp\") == 0) {\n                check_json_value_type(value, json_boolean,\n                                      \"invalid config file: option 'mptcp' must be a boolean\");\n                conf.mptcp = get_mptcp(value->u.boolean);\n            } else if (strcmp(name, \"ipv6_first\") == 0) {\n                check_json_value_type(value, json_boolean,\n                                      \"invalid config file: option 'ipv6_first' must be a boolean\");\n                conf.ipv6_first = value->u.boolean;\n#ifdef HAS_SYSLOG\n            } else if (strcmp(name, \"use_syslog\") == 0) {\n                check_json_value_type(value, json_boolean,\n                                      \"invalid config file: option 'use_syslog' must be a boolean\");\n                use_syslog = value->u.boolean;\n#endif\n            } else if (strcmp(name, \"no_delay\") == 0) {\n                check_json_value_type(\n                    value, json_boolean,\n                    \"invalid config file: option 'no_delay' must be a boolean\");\n                conf.no_delay = value->u.boolean;\n            } else if (strcmp(name, \"tcp_tproxy\") == 0) {\n                check_json_value_type(\n                    value, json_boolean,\n                    \"invalid config file: option 'tcp_tproxy' must be a boolean\");\n                conf.tcp_tproxy = value->u.boolean;\n            } else if (strcmp(name, \"workdir\") == 0) {\n                conf.workdir = to_string(value);\n            } else if (strcmp(name, \"acl\") == 0) {\n                conf.acl = to_string(value);\n            } else if (strcmp(name, \"manager_address\") == 0) {\n                conf.manager_address = to_string(value);\n            }\n        }\n    } else {\n        FATAL(\"Invalid config file\");\n    }\n\n    ss_free(buf);\n    json_value_free(obj);\n    return &conf;\n}\n"
  },
  {
    "path": "src/jconf.h",
    "content": "/*\n * jconf.h - Define the config data structure\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _JCONF_H\n#define _JCONF_H\n\n#define MAX_PORT_NUM 1024\n#define MAX_REMOTE_NUM 10\n#define MAX_DSCP_NUM 64\n#define MAX_CONF_SIZE (128 * 1024)\n#define MAX_CONNECT_TIMEOUT 10\n#define MIN_TCP_IDLE_TIMEOUT (24 * 3600)\n#define MIN_UDP_TIMEOUT 10\n\n#define DSCP_EF      0x2E\n#define DSCP_MIN     0x0\n#define DSCP_MAX     0x3F\n#define DSCP_DEFAULT 0x0\n#define DSCP_MIN_LEN 2\n#define DSCP_MAX_LEN 4\n#define DSCP_CS_LEN  3\n#define DSCP_AF_LEN  4\n\n#define TCP_ONLY     0\n#define TCP_AND_UDP  1\n#define UDP_ONLY     3\n\ntypedef struct {\n    char *port;\n    char *password;\n} ss_port_password_t;\n\ntypedef struct {\n    char *port;\n    int dscp;\n} ss_dscp_t;\n\ntypedef struct {\n    int remote_num;\n    ss_addr_t remote_addr[MAX_REMOTE_NUM];\n    int port_password_num;\n    ss_port_password_t port_password[MAX_PORT_NUM];\n    char *remote_port;\n    char *local_addr;\n    char *local_addr_v4;\n    char *local_addr_v6;\n    char *local_port;\n    char *password;\n    char *key;\n    char *method;\n    char *timeout;\n    char *user;\n    char *plugin;\n    char *plugin_opts;\n    int fast_open;\n    int reuse_port;\n    int tcp_incoming_sndbuf;\n    int tcp_incoming_rcvbuf;\n    int tcp_outgoing_sndbuf;\n    int tcp_outgoing_rcvbuf;\n    int nofile;\n    char *nameserver;\n    int dscp_num;\n    ss_dscp_t dscp[MAX_DSCP_NUM];\n    char *tunnel_address;\n    int mode;\n    int mtu;\n    int mptcp;\n    int ipv6_first;\n    int no_delay;\n    int tcp_tproxy;\n    char *workdir;\n    char *acl;\n    char *manager_address;\n} jconf_t;\n\njconf_t *read_jconf(const char *file);\nvoid parse_addr(const char *str, ss_addr_t *addr);\nvoid free_addr(ss_addr_t *addr);\n\n#endif // _JCONF_H\n"
  },
  {
    "path": "src/json.c",
    "content": "/* vim: set et ts=3 sw=3 sts=3 ft=c:\n *\n * Copyright (C) 2012, 2013, 2014 James McLaughlin et al.  All rights reserved.\n * https://github.com/udp/json-parser\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *   notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *   notice, this list of conditions and the following disclaimer in the\n *   documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n#include \"json.h\"\n\n#ifdef _MSC_VER\n   #ifndef _CRT_SECURE_NO_WARNINGS\n      #define _CRT_SECURE_NO_WARNINGS\n   #endif\n#endif\n\n#ifdef __MINGW32__\n#define CONV_PTR (uintptr_t)\n#else\n#define CONV_PTR (unsigned long)\n#endif\n\nconst struct _json_value json_value_none;\n\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n#include <math.h>\n#include <limits.h>\n\ntypedef unsigned int json_uchar;\n\nstatic unsigned char hex_value (json_char c)\n{\n   if (isdigit(c))\n      return c - '0';\n\n   switch (c) {\n      case 'a': case 'A': return 0x0A;\n      case 'b': case 'B': return 0x0B;\n      case 'c': case 'C': return 0x0C;\n      case 'd': case 'D': return 0x0D;\n      case 'e': case 'E': return 0x0E;\n      case 'f': case 'F': return 0x0F;\n      default: return 0xFF;\n   }\n}\n\ntypedef struct\n{\n   unsigned long used_memory;\n\n   unsigned int uint_max;\n   unsigned long ulong_max;\n\n   json_settings settings;\n   int first_pass;\n\n   const json_char * ptr;\n   unsigned int cur_line, cur_col;\n\n} json_state;\n\nstatic void * default_alloc (size_t size, int zero, void * user_data)\n{\n   return zero ? calloc (1, size) : malloc (size);\n}\n\nstatic void default_free (void * ptr, void * user_data)\n{\n   free (ptr);\n}\n\nstatic void * json_alloc (json_state * state, unsigned long size, int zero)\n{\n   if ((state->ulong_max - state->used_memory) < size)\n      return 0;\n\n   if (state->settings.max_memory\n         && (state->used_memory += size) > state->settings.max_memory)\n   {\n      return 0;\n   }\n\n   return state->settings.mem_alloc (size, zero, state->settings.user_data);\n}\n\nstatic int new_value (json_state * state,\n                      json_value ** top, json_value ** root, json_value ** alloc,\n                      json_type type)\n{\n   json_value * value;\n   int values_size;\n\n   if (!state->first_pass)\n   {\n      value = *top = *alloc;\n      *alloc = (*alloc)->_reserved.next_alloc;\n\n      if (!*root)\n         *root = value;\n\n      switch (value->type)\n      {\n         case json_array:\n\n            if (value->u.array.length == 0)\n               break;\n\n            if (! (value->u.array.values = (json_value **) json_alloc\n               (state, value->u.array.length * sizeof (json_value *), 0)) )\n            {\n               return 0;\n            }\n\n            value->u.array.length = 0;\n            break;\n\n         case json_object:\n\n            if (value->u.object.length == 0)\n               break;\n\n            values_size = sizeof (*value->u.object.values) * value->u.object.length;\n\n            if (! (value->u.object.values = (json_object_entry *) json_alloc\n                  (state, values_size + (CONV_PTR value->u.object.values), 0)) )\n            {\n               return 0;\n            }\n\n            value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size;\n\n            value->u.object.length = 0;\n            break;\n\n         case json_string:\n\n            if (! (value->u.string.ptr = (json_char *) json_alloc\n               (state, (value->u.string.length + 1) * sizeof (json_char), 0)) )\n            {\n               return 0;\n            }\n\n            value->u.string.length = 0;\n            break;\n\n         default:\n            break;\n      };\n\n      return 1;\n   }\n\n   if (! (value = (json_value *) json_alloc\n         (state, sizeof (json_value) + state->settings.value_extra, 1)))\n   {\n      return 0;\n   }\n\n   if (!*root)\n      *root = value;\n\n   value->type = type;\n   value->parent = *top;\n\n   #ifdef JSON_TRACK_SOURCE\n      value->line = state->cur_line;\n      value->col = state->cur_col;\n   #endif\n\n   if (*alloc)\n      (*alloc)->_reserved.next_alloc = value;\n\n   *alloc = *top = value;\n\n   return 1;\n}\n\n#define whitespace \\\n   case '\\n': ++ state.cur_line;  state.cur_col = 0; \\\n   case ' ': case '\\t': case '\\r'\n\n#define string_add(b)  \\\n   do { if (!state.first_pass) string [string_length] = b;  ++ string_length; } while (0);\n\n#define line_and_col \\\n   state.cur_line, state.cur_col\n\nstatic const long\n   flag_next             = 1 << 0,\n   flag_reproc           = 1 << 1,\n   flag_need_comma       = 1 << 2,\n   flag_seek_value       = 1 << 3, \n   flag_escaped          = 1 << 4,\n   flag_string           = 1 << 5,\n   flag_need_colon       = 1 << 6,\n   flag_done             = 1 << 7,\n   flag_num_negative     = 1 << 8,\n   flag_num_zero         = 1 << 9,\n   flag_num_e            = 1 << 10,\n   flag_num_e_got_sign   = 1 << 11,\n   flag_num_e_negative   = 1 << 12,\n   flag_line_comment     = 1 << 13,\n   flag_block_comment    = 1 << 14;\n\njson_value * json_parse_ex (json_settings * settings,\n                            const json_char * json,\n                            size_t length,\n                            char * error_buf)\n{\n   json_char error [json_error_max];\n   const json_char * end;\n   json_value * top, * root, * alloc = 0;\n   json_state state = { 0 };\n   long flags;\n   long num_digits = 0, num_e = 0;\n   json_int_t num_fraction = 0;\n\n   /* Skip UTF-8 BOM\n    */\n   if (length >= 3 && ((unsigned char) json [0]) == 0xEF\n                   && ((unsigned char) json [1]) == 0xBB\n                   && ((unsigned char) json [2]) == 0xBF)\n   {\n      json += 3;\n      length -= 3;\n   }\n\n   error[0] = '\\0';\n   end = (json + length);\n\n   memcpy (&state.settings, settings, sizeof (json_settings));\n\n   if (!state.settings.mem_alloc)\n      state.settings.mem_alloc = default_alloc;\n\n   if (!state.settings.mem_free)\n      state.settings.mem_free = default_free;\n\n   memset (&state.uint_max, 0xFF, sizeof (state.uint_max));\n   memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max));\n\n   state.uint_max -= 8; /* limit of how much can be added before next check */\n   state.ulong_max -= 8;\n\n   for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass)\n   {\n      json_uchar uchar;\n      unsigned char uc_b1, uc_b2, uc_b3, uc_b4;\n      json_char * string = 0;\n      unsigned int string_length = 0;\n\n      top = root = 0;\n      flags = flag_seek_value;\n\n      state.cur_line = 1;\n\n      for (state.ptr = json ;; ++ state.ptr)\n      {\n         json_char b = (state.ptr == end ? 0 : *state.ptr);\n         \n         if (flags & flag_string)\n         {\n            if (!b)\n            {  sprintf (error, \"Unexpected EOF in string (at %d:%d)\", line_and_col);\n               goto e_failed;\n            }\n\n            if (string_length > state.uint_max)\n               goto e_overflow;\n\n            if (flags & flag_escaped)\n            {\n               flags &= ~ flag_escaped;\n\n               switch (b)\n               {\n                  case 'b':  string_add ('\\b');  break;\n                  case 'f':  string_add ('\\f');  break;\n                  case 'n':  string_add ('\\n');  break;\n                  case 'r':  string_add ('\\r');  break;\n                  case 't':  string_add ('\\t');  break;\n                  case 'u':\n\n                    if (end - state.ptr < 4 || \n                        (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||\n                        (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||\n                        (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||\n                        (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)\n                    {\n                        sprintf (error, \"Invalid character value `%c` (at %d:%d)\", b, line_and_col);\n                        goto e_failed;\n                    }\n\n                    uc_b1 = (uc_b1 << 4) | uc_b2;\n                    uc_b2 = (uc_b3 << 4) | uc_b4;\n                    uchar = (uc_b1 << 8) | uc_b2;\n\n                    if ((uchar & 0xF800) == 0xD800) {\n                        json_uchar uchar2;\n                        \n                        if (end - state.ptr < 6 || (*++ state.ptr) != '\\\\' || (*++ state.ptr) != 'u' ||\n                            (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||\n                            (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||\n                            (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||\n                            (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)\n                        {\n                            sprintf (error, \"Invalid character value `%c` (at %d:%d)\", b, line_and_col);\n                            goto e_failed;\n                        }\n\n                        uc_b1 = (uc_b1 << 4) | uc_b2;\n                        uc_b2 = (uc_b3 << 4) | uc_b4;\n                        uchar2 = (uc_b1 << 8) | uc_b2;\n                        \n                        uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF);\n                    }\n\n                    if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F))\n                    {\n                       string_add ((json_char) uchar);\n                       break;\n                    }\n\n                    if (uchar <= 0x7FF)\n                    {\n                        if (state.first_pass)\n                           string_length += 2;\n                        else\n                        {  string [string_length ++] = 0xC0 | (uchar >> 6);\n                           string [string_length ++] = 0x80 | (uchar & 0x3F);\n                        }\n\n                        break;\n                    }\n\n                    if (uchar <= 0xFFFF) {\n                        if (state.first_pass)\n                           string_length += 3;\n                        else\n                        {  string [string_length ++] = 0xE0 | (uchar >> 12);\n                           string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);\n                           string [string_length ++] = 0x80 | (uchar & 0x3F);\n                        }\n                        \n                        break;\n                    }\n\n                    if (state.first_pass)\n                       string_length += 4;\n                    else\n                    {  string [string_length ++] = 0xF0 | (uchar >> 18);\n                       string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F);\n                       string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);\n                       string [string_length ++] = 0x80 | (uchar & 0x3F);\n                    }\n\n                    break;\n\n                  default:\n                     string_add (b);\n               };\n\n               continue;\n            }\n\n            if (b == '\\\\')\n            {\n               flags |= flag_escaped;\n               continue;\n            }\n\n            if (b == '\"')\n            {\n               if (!state.first_pass)\n                  string [string_length] = 0;\n\n               flags &= ~ flag_string;\n               string = 0;\n\n               switch (top->type)\n               {\n                  case json_string:\n\n                     top->u.string.length = string_length;\n                     flags |= flag_next;\n\n                     break;\n\n                  case json_object:\n\n                     if (state.first_pass)\n                        (*(json_char **) &top->u.object.values) += string_length + 1;\n                     else\n                     {  \n                        top->u.object.values [top->u.object.length].name\n                           = (json_char *) top->_reserved.object_mem;\n\n                        top->u.object.values [top->u.object.length].name_length\n                           = string_length;\n\n                        (*(json_char **) &top->_reserved.object_mem) += string_length + 1;\n                     }\n\n                     flags |= flag_seek_value | flag_need_colon;\n                     continue;\n\n                  default:\n                     break;\n               };\n            }\n            else\n            {\n               string_add (b);\n               continue;\n            }\n         }\n\n         if (state.settings.settings & json_enable_comments)\n         {\n            if (flags & (flag_line_comment | flag_block_comment))\n            {\n               if (flags & flag_line_comment)\n               {\n                  if (b == '\\r' || b == '\\n' || !b)\n                  {\n                     flags &= ~ flag_line_comment;\n                     -- state.ptr;  /* so null can be reproc'd */\n                  }\n\n                  continue;\n               }\n\n               if (flags & flag_block_comment)\n               {\n                  if (!b)\n                  {  sprintf (error, \"%d:%d: Unexpected EOF in block comment\", line_and_col);\n                     goto e_failed;\n                  }\n\n                  if (b == '*' && state.ptr < (end - 1) && state.ptr [1] == '/')\n                  {\n                     flags &= ~ flag_block_comment;\n                     ++ state.ptr;  /* skip closing sequence */\n                  }\n\n                  continue;\n               }\n            }\n            else if (b == '/')\n            {\n               if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)\n               {  sprintf (error, \"%d:%d: Comment not allowed here\", line_and_col);\n                  goto e_failed;\n               }\n\n               if (++ state.ptr == end)\n               {  sprintf (error, \"%d:%d: EOF unexpected\", line_and_col);\n                  goto e_failed;\n               }\n\n               switch (b = *state.ptr)\n               {\n                  case '/':\n                     flags |= flag_line_comment;\n                     continue;\n\n                  case '*':\n                     flags |= flag_block_comment;\n                     continue;\n\n                  default:\n                     sprintf (error, \"%d:%d: Unexpected `%c` in comment opening sequence\", line_and_col, b);\n                     goto e_failed;\n               };\n            }\n         }\n\n         if (flags & flag_done)\n         {\n            if (!b)\n               break;\n\n            switch (b)\n            {\n               whitespace:\n                  continue;\n\n               default:\n\n                  sprintf (error, \"%d:%d: Trailing garbage: `%c`\",\n                           state.cur_line, state.cur_col, b);\n\n                  goto e_failed;\n            };\n         }\n\n         if (flags & flag_seek_value)\n         {\n            switch (b)\n            {\n               whitespace:\n                  continue;\n\n               case ']':\n\n                  if (top && top->type == json_array)\n                     flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;\n                  else\n                  {  sprintf (error, \"%d:%d: Unexpected ]\", line_and_col);\n                     goto e_failed;\n                  }\n\n                  break;\n\n               default:\n\n                  if (flags & flag_need_comma)\n                  {\n                     if (b == ',')\n                     {  flags &= ~ flag_need_comma;\n                        continue;\n                     }\n                     else\n                     {\n                        sprintf (error, \"%d:%d: Expected , before %c\",\n                                 state.cur_line, state.cur_col, b);\n\n                        goto e_failed;\n                     }\n                  }\n\n                  if (flags & flag_need_colon)\n                  {\n                     if (b == ':')\n                     {  flags &= ~ flag_need_colon;\n                        continue;\n                     }\n                     else\n                     { \n                        sprintf (error, \"%d:%d: Expected : before %c\",\n                                 state.cur_line, state.cur_col, b);\n\n                        goto e_failed;\n                     }\n                  }\n\n                  flags &= ~ flag_seek_value;\n\n                  switch (b)\n                  {\n                     case '{':\n\n                        if (!new_value (&state, &top, &root, &alloc, json_object))\n                           goto e_alloc_failure;\n\n                        continue;\n\n                     case '[':\n\n                        if (!new_value (&state, &top, &root, &alloc, json_array))\n                           goto e_alloc_failure;\n\n                        flags |= flag_seek_value;\n                        continue;\n\n                     case '\"':\n\n                        if (!new_value (&state, &top, &root, &alloc, json_string))\n                           goto e_alloc_failure;\n\n                        flags |= flag_string;\n\n                        string = top->u.string.ptr;\n                        string_length = 0;\n\n                        continue;\n\n                     case 't':\n\n                        if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' ||\n                            *(++ state.ptr) != 'u' || *(++ state.ptr) != 'e')\n                        {\n                           goto e_unknown_value;\n                        }\n\n                        if (!new_value (&state, &top, &root, &alloc, json_boolean))\n                           goto e_alloc_failure;\n\n                        top->u.boolean = 1;\n\n                        flags |= flag_next;\n                        break;\n\n                     case 'f':\n\n                        if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' ||\n                            *(++ state.ptr) != 'l' || *(++ state.ptr) != 's' ||\n                            *(++ state.ptr) != 'e')\n                        {\n                           goto e_unknown_value;\n                        }\n\n                        if (!new_value (&state, &top, &root, &alloc, json_boolean))\n                           goto e_alloc_failure;\n\n                        flags |= flag_next;\n                        break;\n\n                     case 'n':\n\n                        if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' ||\n                            *(++ state.ptr) != 'l' || *(++ state.ptr) != 'l')\n                        {\n                           goto e_unknown_value;\n                        }\n\n                        if (!new_value (&state, &top, &root, &alloc, json_null))\n                           goto e_alloc_failure;\n\n                        flags |= flag_next;\n                        break;\n\n                     default:\n\n                        if (isdigit (b) || b == '-')\n                        {\n                           if (!new_value (&state, &top, &root, &alloc, json_integer))\n                              goto e_alloc_failure;\n\n                           if (!state.first_pass)\n                           {\n                              while (isdigit (b) || b == '+' || b == '-'\n                                        || b == 'e' || b == 'E' || b == '.')\n                              {\n                                 if ( (++ state.ptr) == end)\n                                 {\n                                    b = 0;\n                                    break;\n                                 }\n\n                                 b = *state.ptr;\n                              }\n\n                              flags |= flag_next | flag_reproc;\n                              break;\n                           }\n\n                           flags &= ~ (flag_num_negative | flag_num_e |\n                                        flag_num_e_got_sign | flag_num_e_negative |\n                                           flag_num_zero);\n\n                           num_digits = 0;\n                           num_fraction = 0;\n                           num_e = 0;\n\n                           if (b != '-')\n                           {\n                              flags |= flag_reproc;\n                              break;\n                           }\n\n                           flags |= flag_num_negative;\n                           continue;\n                        }\n                        else\n                        {  sprintf (error, \"%d:%d: Unexpected %c when seeking value\", line_and_col, b);\n                           goto e_failed;\n                        }\n                  };\n            };\n         }\n         else\n         {\n            switch (top->type)\n            {\n            case json_object:\n               \n               switch (b)\n               {\n                  whitespace:\n                     continue;\n\n                  case '\"':\n\n                     if (flags & flag_need_comma)\n                     {  sprintf (error, \"%d:%d: Expected , before \\\"\", line_and_col);\n                        goto e_failed;\n                     }\n\n                     flags |= flag_string;\n\n                     string = (json_char *) top->_reserved.object_mem;\n                     string_length = 0;\n\n                     break;\n                  \n                  case '}':\n\n                     flags = (flags & ~ flag_need_comma) | flag_next;\n                     break;\n\n                  case ',':\n\n                     if (flags & flag_need_comma)\n                     {\n                        flags &= ~ flag_need_comma;\n                        break;\n                     }\n\n                  default:\n                     sprintf (error, \"%d:%d: Unexpected `%c` in object\", line_and_col, b);\n                     goto e_failed;\n               };\n\n               break;\n\n            case json_integer:\n            case json_double:\n\n               if (isdigit (b))\n               {\n                  ++ num_digits;\n\n                  if (top->type == json_integer || flags & flag_num_e)\n                  {\n                     if (! (flags & flag_num_e))\n                     {\n                        if (flags & flag_num_zero)\n                        {  sprintf (error, \"%d:%d: Unexpected `0` before `%c`\", line_and_col, b);\n                           goto e_failed;\n                        }\n\n                        if (num_digits == 1 && b == '0')\n                           flags |= flag_num_zero;\n                     }\n                     else\n                     {\n                        flags |= flag_num_e_got_sign;\n                        /* Overflow check for exponent */\n                        if (num_e > (LONG_MAX / 10) || (num_e == (LONG_MAX / 10) && (b - '0') > (LONG_MAX % 10))) {\n                           sprintf(error, \"%d:%d: Exponent too large (overflow)\", line_and_col);\n                           goto e_failed;\n                        }\n                        num_e = (num_e * 10) + (b - '0');\n                        continue;\n                     }\n\n                     /* Overflow check for integer */\n                     long prev = top->u.integer;\n                     if ((prev > 0 && (prev > (LONG_MAX / 10) || (prev == (LONG_MAX / 10) && (b - '0') > (LONG_MAX % 10)))) ||\n                         (prev < 0 && (prev < (LONG_MIN / 10) || (prev == (LONG_MIN / 10) && -(b - '0') < (LONG_MIN % 10))))) {\n                        sprintf(error, \"%d:%d: Integer too large (overflow)\", line_and_col);\n                        goto e_failed;\n                     }\n                     top->u.integer = (top->u.integer * 10) + (b - '0');\n                     continue;\n                  }\n\n                  /* Overflow check for fraction */\n                  if (num_fraction > (LONG_MAX / 10) || (num_fraction == (LONG_MAX / 10) && (b - '0') > (LONG_MAX % 10))) {\n                     sprintf(error, \"%d:%d: Fraction too large (overflow)\", line_and_col);\n                     goto e_failed;\n                  }\n                  num_fraction = (num_fraction * 10) + (b - '0');\n                  continue;\n               }\n\n               if (b == '+' || b == '-')\n               {\n                  if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign))\n                  {\n                     flags |= flag_num_e_got_sign;\n\n                     if (b == '-')\n                        flags |= flag_num_e_negative;\n\n                     continue;\n                  }\n               }\n               else if (b == '.' && top->type == json_integer)\n               {\n                  if (!num_digits)\n                  {  sprintf (error, \"%d:%d: Expected digit before `.`\", line_and_col);\n                     goto e_failed;\n                  }\n\n                  top->type = json_double;\n                  top->u.dbl = (double) top->u.integer;\n\n                  num_digits = 0;\n                  continue;\n               }\n\n               if (! (flags & flag_num_e))\n               {\n                  if (top->type == json_double)\n                  {\n                     if (!num_digits)\n                     {  sprintf (error, \"%d:%d: Expected digit after `.`\", line_and_col);\n                        goto e_failed;\n                     }\n\n                     top->u.dbl += ((double) num_fraction) / (pow (10.0, (double) num_digits));\n                  }\n\n                  if (b == 'e' || b == 'E')\n                  {\n                     flags |= flag_num_e;\n\n                     if (top->type == json_integer)\n                     {\n                        top->type = json_double;\n                        top->u.dbl = (double) top->u.integer;\n                     }\n\n                     num_digits = 0;\n                     flags &= ~ flag_num_zero;\n\n                     continue;\n                  }\n               }\n               else\n               {\n                  if (!num_digits)\n                  {  sprintf (error, \"%d:%d: Expected digit after `e`\", line_and_col);\n                     goto e_failed;\n                  }\n\n                  top->u.dbl *= pow (10.0, (double)\n                      (flags & flag_num_e_negative ? - num_e : num_e));\n               }\n\n               if (flags & flag_num_negative)\n               {\n                  if (top->type == json_integer)\n                     top->u.integer = - top->u.integer;\n                  else\n                     top->u.dbl = - top->u.dbl;\n               }\n\n               flags |= flag_next | flag_reproc;\n               break;\n\n            default:\n               break;\n            };\n         }\n\n         if (flags & flag_reproc)\n         {\n            flags &= ~ flag_reproc;\n            -- state.ptr;\n         }\n\n         if (flags & flag_next)\n         {\n            flags = (flags & ~ flag_next) | flag_need_comma;\n\n            if (!top->parent)\n            {\n               /* root value done */\n\n               flags |= flag_done;\n               continue;\n            }\n\n            if (top->parent->type == json_array)\n               flags |= flag_seek_value;\n               \n            if (!state.first_pass)\n            {\n               json_value * parent = top->parent;\n\n               switch (parent->type)\n               {\n                  case json_object:\n\n                     parent->u.object.values\n                        [parent->u.object.length].value = top;\n\n                     break;\n\n                  case json_array:\n\n                     parent->u.array.values\n                           [parent->u.array.length] = top;\n\n                     break;\n\n                  default:\n                     break;\n               };\n            }\n\n            if ( (++ top->parent->u.array.length) > state.uint_max)\n               goto e_overflow;\n\n            top = top->parent;\n\n            continue;\n         }\n      }\n\n      alloc = root;\n   }\n\n   return root;\n\ne_unknown_value:\n\n   sprintf (error, \"%d:%d: Unknown value\", line_and_col);\n   goto e_failed;\n\ne_alloc_failure:\n\n   strcpy (error, \"Memory allocation failure\");\n   goto e_failed;\n\ne_overflow:\n\n   sprintf (error, \"%d:%d: Too long (caught overflow)\", line_and_col);\n   goto e_failed;\n\ne_failed:\n\n   if (error_buf)\n   {\n      if (*error)\n         strcpy (error_buf, error);\n      else\n         strcpy (error_buf, \"Unknown error\");\n   }\n\n   if (state.first_pass)\n      alloc = root;\n\n   while (alloc)\n   {\n      top = alloc->_reserved.next_alloc;\n      state.settings.mem_free (alloc, state.settings.user_data);\n      alloc = top;\n   }\n\n   if (!state.first_pass)\n      json_value_free_ex (&state.settings, root);\n\n   return 0;\n}\n\njson_value * json_parse (const json_char * json, size_t length)\n{\n   json_settings settings = { 0 };\n   return json_parse_ex (&settings, json, length, 0);\n}\n\nvoid json_value_free_ex (json_settings * settings, json_value * value)\n{\n   json_value * cur_value;\n\n   if (!value)\n      return;\n\n   value->parent = 0;\n\n   while (value)\n   {\n      switch (value->type)\n      {\n         case json_array:\n\n            if (!value->u.array.length)\n            {\n               settings->mem_free (value->u.array.values, settings->user_data);\n               break;\n            }\n\n            value = value->u.array.values [-- value->u.array.length];\n            continue;\n\n         case json_object:\n\n            if (!value->u.object.length)\n            {\n               settings->mem_free (value->u.object.values, settings->user_data);\n               break;\n            }\n\n            value = value->u.object.values [-- value->u.object.length].value;\n            continue;\n\n         case json_string:\n\n            settings->mem_free (value->u.string.ptr, settings->user_data);\n            break;\n\n         default:\n            break;\n      };\n\n      cur_value = value;\n      value = value->parent;\n      settings->mem_free (cur_value, settings->user_data);\n   }\n}\n\nvoid json_value_free (json_value * value)\n{\n   json_settings settings = { 0 };\n   settings.mem_free = default_free;\n   json_value_free_ex (&settings, value);\n}\n\n"
  },
  {
    "path": "src/json.h",
    "content": "\n/* vim: set et ts=3 sw=3 sts=3 ft=c:\n *\n * Copyright (C) 2012, 2013, 2014 James McLaughlin et al.  All rights reserved.\n * https://github.com/udp/json-parser\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *   notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *   notice, this list of conditions and the following disclaimer in the\n *   documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n#ifndef _JSON_H\n#define _JSON_H\n\n#ifndef json_char\n   #define json_char char\n#endif\n\n#ifndef json_int_t\n   #ifndef _MSC_VER\n      #include <inttypes.h>\n      #define json_int_t int64_t\n   #else\n      #define json_int_t __int64\n   #endif\n#endif\n\n#include <stdlib.h>\n\n#ifdef __cplusplus\n\n   #include <string.h>\n\n   extern \"C\"\n   {\n\n#endif\n\ntypedef struct\n{\n   unsigned long max_memory;\n   int settings;\n\n   /* Custom allocator support (leave null to use malloc/free)\n    */\n\n   void * (* mem_alloc) (size_t, int zero, void * user_data);\n   void (* mem_free) (void *, void * user_data);\n\n   void * user_data;  /* will be passed to mem_alloc and mem_free */\n\n   size_t value_extra;  /* how much extra space to allocate for values? */\n\n} json_settings;\n\n#define json_enable_comments  0x01\n\ntypedef enum\n{\n   json_none,\n   json_object,\n   json_array,\n   json_integer,\n   json_double,\n   json_string,\n   json_boolean,\n   json_null\n\n} json_type;\n\nextern const struct _json_value json_value_none;\n       \ntypedef struct _json_object_entry\n{\n    json_char * name;\n    unsigned int name_length;\n    \n    struct _json_value * value;\n    \n} json_object_entry;\n\ntypedef struct _json_value\n{\n   struct _json_value * parent;\n\n   json_type type;\n\n   union\n   {\n      int boolean;\n      json_int_t integer;\n      double dbl;\n\n      struct\n      {\n         unsigned int length;\n         json_char * ptr; /* null terminated */\n\n      } string;\n\n      struct\n      {\n         unsigned int length;\n\n         json_object_entry * values;\n\n         #if defined(__cplusplus) && __cplusplus >= 201103L\n         decltype(values) begin () const\n         {  return values;\n         }\n         decltype(values) end () const\n         {  return values + length;\n         }\n         #endif\n\n      } object;\n\n      struct\n      {\n         unsigned int length;\n         struct _json_value ** values;\n\n         #if defined(__cplusplus) && __cplusplus >= 201103L\n         decltype(values) begin () const\n         {  return values;\n         }\n         decltype(values) end () const\n         {  return values + length;\n         }\n         #endif\n\n      } array;\n\n   } u;\n\n   union\n   {\n      struct _json_value * next_alloc;\n      void * object_mem;\n\n   } _reserved;\n\n   #ifdef JSON_TRACK_SOURCE\n\n      /* Location of the value in the source JSON\n       */\n      unsigned int line, col;\n\n   #endif\n\n\n   /* Some C++ operator sugar */\n\n   #ifdef __cplusplus\n\n      public:\n\n         inline _json_value ()\n         {  memset (this, 0, sizeof (_json_value));\n         }\n\n         inline const struct _json_value &operator [] (int index) const\n         {\n            if (type != json_array || index < 0\n                     || ((unsigned int) index) >= u.array.length)\n            {\n               return json_value_none;\n            }\n\n            return *u.array.values [index];\n         }\n\n         inline const struct _json_value &operator [] (const char * index) const\n         { \n            if (type != json_object)\n               return json_value_none;\n\n            for (unsigned int i = 0; i < u.object.length; ++ i)\n               if (!strcmp (u.object.values [i].name, index))\n                  return *u.object.values [i].value;\n\n            return json_value_none;\n         }\n\n         inline operator const char * () const\n         {  \n            switch (type)\n            {\n               case json_string:\n                  return u.string.ptr;\n\n               default:\n                  return \"\";\n            };\n         }\n\n         inline operator json_int_t () const\n         {  \n            switch (type)\n            {\n               case json_integer:\n                  return u.integer;\n\n               case json_double:\n                  return (json_int_t) u.dbl;\n\n               default:\n                  return 0;\n            };\n         }\n\n         inline operator bool () const\n         {  \n            if (type != json_boolean)\n               return false;\n\n            return u.boolean != 0;\n         }\n\n         inline operator double () const\n         {  \n            switch (type)\n            {\n               case json_integer:\n                  return (double) u.integer;\n\n               case json_double:\n                  return u.dbl;\n\n               default:\n                  return 0;\n            };\n         }\n\n   #endif\n\n} json_value;\n       \njson_value * json_parse (const json_char * json,\n                         size_t length);\n\n#define json_error_max 128\njson_value * json_parse_ex (json_settings * settings,\n                            const json_char * json,\n                            size_t length,\n                            char * error);\n\nvoid json_value_free (json_value *);\n\n\n/* Not usually necessary, unless you used a custom mem_alloc and now want to\n * use a custom mem_free.\n */\nvoid json_value_free_ex (json_settings * settings,\n                         json_value *);\n\n\n#ifdef __cplusplus\n   } /* extern \"C\" */\n#endif\n\n#endif\n\n\n"
  },
  {
    "path": "src/local.c",
    "content": "/*\n * local.c - Setup a socks5 proxy through remote shadowsocks server\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <fcntl.h>\n#include <locale.h>\n#include <signal.h>\n#include <string.h>\n#include <strings.h>\n#include <unistd.h>\n#include <getopt.h>\n#ifndef __MINGW32__\n#include <errno.h>\n#include <arpa/inet.h>\n#include <netdb.h>\n#include <netinet/in.h>\n#endif\n#ifdef LIB_ONLY\n#include \"shadowsocks.h\"\n#endif\n\n#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__)\n#include <net/if.h>\n#include <sys/ioctl.h>\n#define SET_INTERFACE\n#endif\n\n#include <libcork/core.h>\n\n#include \"netutils.h\"\n#include \"utils.h\"\n#include \"socks5.h\"\n#include \"acl.h\"\n#include \"plugin.h\"\n#include \"local.h\"\n#include \"winsock.h\"\n\n#ifndef LIB_ONLY\n#ifdef __APPLE__\n#include <AvailabilityMacros.h>\n#if defined(MAC_OS_X_VERSION_10_10) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10\n#include <launch.h>\n#define HAVE_LAUNCHD\n#endif\n#endif\n#endif\n\n#ifndef EAGAIN\n#define EAGAIN EWOULDBLOCK\n#endif\n\n#ifndef EWOULDBLOCK\n#define EWOULDBLOCK EAGAIN\n#endif\n\nint verbose    = 0;\nint reuse_port = 0;\nint tcp_incoming_sndbuf = 0;\nint tcp_incoming_rcvbuf = 0;\nint tcp_outgoing_sndbuf = 0;\nint tcp_outgoing_rcvbuf = 0;\n\n#ifdef __ANDROID__\nint vpn        = 0;\nuint64_t tx    = 0;\nuint64_t rx    = 0;\nev_tstamp last = 0;\n\nchar *stat_path   = NULL;\n#endif\n\nstatic crypto_t *crypto;\n\nstatic int acl       = 0;\nstatic int mode      = TCP_ONLY;\nstatic int ipv6first = 0;\nint fast_open        = 0;\nstatic int no_delay  = 0;\nstatic int udp_fd    = 0;\nstatic int ret_val   = 0;\n\nstatic struct ev_signal sigint_watcher;\nstatic struct ev_signal sigterm_watcher;\n#ifndef __MINGW32__\nstatic struct ev_signal sigchld_watcher;\nstatic struct ev_signal sigusr1_watcher;\n#else\n#ifndef LIB_ONLY\nstatic struct plugin_watcher_t {\n    ev_io io;\n    SOCKET fd;\n    uint16_t port;\n    int valid;\n} plugin_watcher;\n#endif\n#endif\n\n#ifdef HAVE_SETRLIMIT\n#ifndef LIB_ONLY\nstatic int nofile = 0;\n#endif\n#endif\n\nstatic void server_recv_cb(EV_P_ ev_io *w, int revents);\nstatic void server_send_cb(EV_P_ ev_io *w, int revents);\nstatic void remote_recv_cb(EV_P_ ev_io *w, int revents);\nstatic void remote_send_cb(EV_P_ ev_io *w, int revents);\nstatic void accept_cb(EV_P_ ev_io *w, int revents);\nstatic void signal_cb(EV_P_ ev_signal *w, int revents);\n#if defined(__MINGW32__) && !defined(LIB_ONLY)\nstatic void plugin_watcher_cb(EV_P_ ev_io *w, int revents);\n#endif\n\nstatic int create_and_bind(const char *addr, const char *port);\n#ifdef HAVE_LAUNCHD\nstatic int launch_or_create(const char *addr, const char *port);\n#endif\nstatic remote_t *create_remote(listen_ctx_t *listener, struct sockaddr *addr, int direct);\nstatic void free_remote(remote_t *remote);\nstatic void close_and_free_remote(EV_P_ remote_t *remote);\nstatic void free_server(server_t *server);\nstatic void close_and_free_server(EV_P_ server_t *server);\n\nstatic remote_t *new_remote(int fd, int timeout);\nstatic server_t *new_server(int fd);\n\nstatic struct cork_dllist connections;\n\n#ifndef __MINGW32__\nint\nsetnonblocking(int fd)\n{\n    int flags;\n    if (-1 == (flags = fcntl(fd, F_GETFL, 0))) {\n        flags = 0;\n    }\n    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);\n}\n\n#endif\n\nint\ncreate_and_bind(const char *addr, const char *port)\n{\n    struct addrinfo hints;\n    struct addrinfo *result, *rp;\n    int s, listen_sock = -1;\n\n    memset(&hints, 0, sizeof(struct addrinfo));\n    hints.ai_family   = AF_UNSPEC;   /* Return IPv4 and IPv6 choices */\n    hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */\n    result            = NULL;\n\n    s = getaddrinfo(addr, port, &hints, &result);\n\n    if (s != 0) {\n        LOGI(\"getaddrinfo: %s\", gai_strerror(s));\n        return -1;\n    }\n\n    if (result == NULL) {\n        LOGE(\"Could not bind\");\n        return -1;\n    }\n\n    for (rp = result; rp != NULL; rp = rp->ai_next) {\n        listen_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);\n        if (listen_sock == -1) {\n            continue;\n        }\n\n        int opt = 1;\n        setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));\n#ifdef SO_NOSIGPIPE\n        setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));\n#endif\n        if (reuse_port) {\n            int err = set_reuseport(listen_sock);\n            if (err == 0) {\n                LOGI(\"tcp port reuse enabled\");\n            }\n        }\n\n        s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);\n        if (s == 0) {\n            /* We managed to bind successfully! */\n            break;\n        } else {\n            ERROR(\"bind\");\n        }\n\n        close(listen_sock);\n        listen_sock = -1;\n    }\n\n    freeaddrinfo(result);\n\n    return listen_sock;\n}\n\n#ifdef HAVE_LAUNCHD\nint\nlaunch_or_create(const char *addr, const char *port)\n{\n    int *fds;\n    size_t cnt;\n    int error = launch_activate_socket(\"Listeners\", &fds, &cnt);\n    if (error == 0) {\n        if (cnt == 1) {\n            return fds[0];\n        } else {\n            FATAL(\"please don't specify multi entry\");\n        }\n    } else if (error == ESRCH || error == ENOENT) {\n        /* ESRCH:  The calling process is not managed by launchd(8).\n         * ENOENT: The socket name specified does not exist\n         *          in the caller's launchd.plist(5).\n         */\n        if (port == NULL) {\n            usage();\n            exit(EXIT_FAILURE);\n        }\n        return create_and_bind(addr, port);\n    } else {\n        FATAL(\"launch_activate_socket() error\");\n    }\n    return -1;\n}\n\n#endif\n\nstatic void\nfree_connections(struct ev_loop *loop)\n{\n    struct cork_dllist_item *curr, *next;\n    cork_dllist_foreach_void(&connections, curr, next) {\n        server_t *server = cork_container_of(curr, server_t, entries);\n        remote_t *remote = server->remote;\n        close_and_free_server(loop, server);\n        close_and_free_remote(loop, remote);\n    }\n}\n\nstatic void\ndelayed_connect_cb(EV_P_ ev_timer *watcher, int revents)\n{\n    server_t *server = cork_container_of(watcher, server_t,\n                                         delayed_connect_watcher);\n\n    server_recv_cb(EV_A_ & server->recv_ctx->io, revents);\n}\n\nstatic int\nserver_handshake_reply(EV_P_ ev_io *w, int udp_assc, struct socks5_response *response)\n{\n    server_ctx_t *server_recv_ctx = (server_ctx_t *)w;\n    server_t *server              = server_recv_ctx->server;\n    remote_t *remote              = server->remote;\n    if (server->stage != STAGE_HANDSHAKE)\n        return 0;\n\n    struct sockaddr_in sock_addr;\n    if (udp_assc) {\n        socklen_t addr_len = sizeof(sock_addr);\n        if (getsockname(server->fd, (struct sockaddr *)&sock_addr, &addr_len) < 0) {\n            LOGE(\"getsockname: %s\", strerror(errno));\n            response->rep = SOCKS5_REP_CONN_REFUSED;\n            send(server->fd, (char *)response, sizeof(struct socks5_response), 0);\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return -1;\n        }\n    } else\n        memset(&sock_addr, 0, sizeof(sock_addr));\n\n    buffer_t resp_to_send;\n    buffer_t *resp_buf = &resp_to_send;\n    balloc(resp_buf, SOCKET_BUF_SIZE);\n\n    memcpy(resp_buf->data, response, sizeof(struct socks5_response));\n    memcpy(resp_buf->data + sizeof(struct socks5_response),\n           &sock_addr.sin_addr, sizeof(sock_addr.sin_addr));\n    memcpy(resp_buf->data + sizeof(struct socks5_response) +\n           sizeof(sock_addr.sin_addr),\n           &sock_addr.sin_port, sizeof(sock_addr.sin_port));\n\n    int reply_size = sizeof(struct socks5_response) +\n                     sizeof(sock_addr.sin_addr) + sizeof(sock_addr.sin_port);\n\n    int s = send(server->fd, resp_buf->data, reply_size, 0);\n\n    bfree(resp_buf);\n\n    if (s < reply_size) {\n        LOGE(\"failed to send fake reply\");\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return -1;\n    }\n    if (udp_assc) {\n        // Wait until client closes the connection\n        return -1;\n    }\n    return 0;\n}\n\nstatic int\nserver_handshake(EV_P_ ev_io *w, buffer_t *buf)\n{\n    server_ctx_t *server_recv_ctx = (server_ctx_t *)w;\n    server_t *server              = server_recv_ctx->server;\n    remote_t *remote              = server->remote;\n\n    struct socks5_request *request = (struct socks5_request *)buf->data;\n    size_t request_len             = sizeof(struct socks5_request);\n\n    if (buf->len < request_len) {\n        return -1;\n    }\n\n    struct socks5_response response;\n    response.ver  = SVERSION;\n    response.rep  = SOCKS5_REP_SUCCEEDED;\n    response.rsv  = 0;\n    response.atyp = SOCKS5_ATYP_IPV4;\n\n    if (request->cmd == SOCKS5_CMD_UDP_ASSOCIATE) {\n        if (verbose) {\n            LOGI(\"udp assc request accepted\");\n        }\n        return server_handshake_reply(EV_A_ w, 1, &response);\n    } else if (request->cmd != SOCKS5_CMD_CONNECT) {\n        LOGE(\"unsupported command: %d\", request->cmd);\n        response.rep = SOCKS5_REP_CMD_NOT_SUPPORTED;\n        char *send_buf = (char *)&response;\n        send(server->fd, send_buf, 4, 0);\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return -1;\n    }\n\n    char host[MAX_HOSTNAME_LEN + 1], ip[INET6_ADDRSTRLEN], port[16];\n\n    buffer_t *abuf = server->abuf;\n    abuf->idx = 0;\n    abuf->len = 0;\n\n    abuf->data[abuf->len++] = request->atyp;\n    int atyp = request->atyp;\n\n    // get remote addr and port\n    if (atyp == SOCKS5_ATYP_IPV4) {\n        size_t in_addr_len = sizeof(struct in_addr);\n        if (buf->len < request_len + in_addr_len + 2) {\n            return -1;\n        }\n        memcpy(abuf->data + abuf->len, buf->data + request_len, in_addr_len + 2);\n        abuf->len += in_addr_len + 2;\n\n        if (acl || verbose) {\n            uint16_t p = load16_be(buf->data + request_len + in_addr_len);\n            if (!inet_ntop(AF_INET, (const void *)(buf->data + request_len),\n                           ip, INET_ADDRSTRLEN)) {\n                LOGI(\"inet_ntop(AF_INET): %s\", strerror(errno));\n                ip[0] = '\\0';\n            }\n            sprintf(port, \"%d\", p);\n        }\n    } else if (atyp == SOCKS5_ATYP_DOMAIN) {\n        uint8_t name_len = *(uint8_t *)(buf->data + request_len);\n        if (buf->len < request_len + 1 + name_len + 2) {\n            return -1;\n        }\n        abuf->data[abuf->len++] = name_len;\n        memcpy(abuf->data + abuf->len, buf->data + request_len + 1, name_len + 2);\n        abuf->len += name_len + 2;\n\n        if (acl || verbose) {\n            uint16_t p = load16_be(buf->data + request_len + 1 + name_len);\n            memcpy(host, buf->data + request_len + 1, name_len);\n            host[name_len] = '\\0';\n            sprintf(port, \"%d\", p);\n        }\n    } else if (atyp == SOCKS5_ATYP_IPV6) {\n        size_t in6_addr_len = sizeof(struct in6_addr);\n        if (buf->len < request_len + in6_addr_len + 2) {\n            return -1;\n        }\n        memcpy(abuf->data + abuf->len, buf->data + request_len, in6_addr_len + 2);\n        abuf->len += in6_addr_len + 2;\n\n        if (acl || verbose) {\n            uint16_t p = load16_be(buf->data + request_len + in6_addr_len);\n            if (!inet_ntop(AF_INET6, (const void *)(buf->data + request_len),\n                           ip, INET6_ADDRSTRLEN)) {\n                LOGI(\"inet_ntop(AF_INET6): %s\", strerror(errno));\n                ip[0] = '\\0';\n            }\n            sprintf(port, \"%d\", p);\n        }\n    } else {\n        LOGE(\"unsupported addrtype: %d\", request->atyp);\n        response.rep = SOCKS5_REP_ADDRTYPE_NOT_SUPPORTED;\n        char *send_buf = (char *)&response;\n        send(server->fd, send_buf, 4, 0);\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return -1;\n    }\n\n    if (server_handshake_reply(EV_A_ w, 0, &response) < 0)\n        return -1;\n    server->stage = STAGE_STREAM;\n\n    buf->len -= (3 + abuf->len);\n    if (buf->len > 0) {\n        memmove(buf->data, buf->data + 3 + abuf->len, buf->len);\n    }\n\n    if (verbose) {\n        if (atyp == SOCKS5_ATYP_DOMAIN)\n            LOGI(\"connect to %s:%s\", host, port);\n        else if (atyp == SOCKS5_ATYP_IPV4)\n            LOGI(\"connect to %s:%s\", ip, port);\n        else if (atyp == SOCKS5_ATYP_IPV6)\n            LOGI(\"connect to [%s]:%s\", ip, port);\n    }\n\n    if (acl\n#ifdef __ANDROID__\n        && !(vpn && strcmp(port, \"53\") == 0)\n#endif\n        ) {\n        int bypass   = 0;\n        int resolved = 0;\n        struct sockaddr_storage storage;\n        memset(&storage, 0, sizeof(struct sockaddr_storage));\n        int err;\n\n        int host_match = 0;\n        if (atyp == SOCKS5_ATYP_DOMAIN)\n            host_match = acl_match_host(host);\n\n        if (host_match > 0)\n            bypass = 1;                             // bypass hostnames in black list\n        else if (host_match < 0)\n            bypass = 0;                             // proxy hostnames in white list\n        else {\n            if (atyp == SOCKS5_ATYP_DOMAIN\n#ifdef __ANDROID__\n                && !vpn\n#endif\n                ) {           // resolve domain so we can bypass domain with geoip\n                if (get_sockaddr(host, port, &storage, 0, ipv6first))\n                    goto not_bypass;\n                resolved = 1;\n                switch (((struct sockaddr *)&storage)->sa_family) {\n                case AF_INET:\n                {\n                    struct sockaddr_in *addr_in = (struct sockaddr_in *)&storage;\n                    if (!inet_ntop(AF_INET, &(addr_in->sin_addr), ip, INET_ADDRSTRLEN))\n                        goto not_bypass;\n                    break;\n                }\n                case AF_INET6:\n                {\n                    struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&storage;\n                    if (!inet_ntop(AF_INET6, &(addr_in6->sin6_addr), ip, INET6_ADDRSTRLEN))\n                        goto not_bypass;\n                    break;\n                }\n                default:\n                    goto not_bypass;\n                }\n            }\n\n            int ip_match = (resolved || atyp == SOCKS5_ATYP_IPV4\n                            || atyp == SOCKS5_ATYP_IPV6) ? acl_match_host(ip) : 0;\n\n            switch (get_acl_mode()) {\n            case BLACK_LIST:\n                if (ip_match > 0)\n                    bypass = 1;                                               // bypass IPs in black list\n                break;\n            case WHITE_LIST:\n                bypass = 1;\n                if (ip_match < 0)\n                    bypass = 0;                                               // proxy IPs in white list\n                break;\n            }\n        }\n\n        if (bypass) {\n            if (verbose) {\n                if (atyp == SOCKS5_ATYP_DOMAIN)\n                    LOGI(\"bypass %s:%s\", host, port);\n                else if (atyp == 1)\n                    LOGI(\"bypass %s:%s\", ip, port);\n                else if (atyp == 4)\n                    LOGI(\"bypass [%s]:%s\", ip, port);\n            }\n            if (atyp == SOCKS5_ATYP_DOMAIN && !resolved)\n#ifdef __ANDROID__\n                if (vpn)\n                    goto not_bypass;\n                else\n#endif\n                err = get_sockaddr(host, port, &storage, 0, ipv6first);\n            else\n                err = get_sockaddr(ip, port, &storage, 0, ipv6first);\n            if (err != -1) {\n                remote = create_remote(server->listener, (struct sockaddr *)&storage, 1);\n            }\n        }\n    }\n\nnot_bypass:\n    // Not bypass\n    if (remote == NULL) {\n        remote = create_remote(server->listener, NULL, 0);\n    }\n\n    if (remote == NULL) {\n        LOGE(\"invalid remote addr\");\n        close_and_free_server(EV_A_ server);\n        return -1;\n    }\n\n    if (!remote->direct) {\n        int err = crypto->encrypt(abuf, server->e_ctx, SOCKET_BUF_SIZE);\n        if (err) {\n            LOGE(\"invalid password or cipher\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return -1;\n        }\n    }\n\n    if (buf->len > 0) {\n        memcpy(remote->buf->data, buf->data, buf->len);\n        remote->buf->len = buf->len;\n    }\n\n    server->remote = remote;\n    remote->server = server;\n\n    if (buf->len > 0) {\n        return 0;\n    } else {\n        ev_timer_start(EV_A_ & server->delayed_connect_watcher);\n    }\n\n    return -1;\n}\n\nstatic void\nserver_stream(EV_P_ ev_io *w, buffer_t *buf)\n{\n    server_ctx_t *server_recv_ctx = (server_ctx_t *)w;\n    server_t *server              = server_recv_ctx->server;\n    remote_t *remote              = server->remote;\n\n    if (remote == NULL) {\n        LOGE(\"invalid remote\");\n        close_and_free_server(EV_A_ server);\n        return;\n    }\n\n    // insert shadowsocks header\n    if (!remote->direct) {\n#ifdef __ANDROID__\n        tx += remote->buf->len;\n#endif\n        int err = crypto->encrypt(remote->buf, server->e_ctx, SOCKET_BUF_SIZE);\n\n        if (err) {\n            LOGE(\"invalid password or cipher\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n\n        if (server->abuf) {\n            bprepend(remote->buf, server->abuf, SOCKET_BUF_SIZE);\n            bfree(server->abuf);\n            ss_free(server->abuf);\n            server->abuf = NULL;\n        }\n    }\n\n    if (!remote->send_ctx->connected) {\n#ifdef __ANDROID__\n        if (vpn) {\n            int not_protect = 0;\n            if (remote->addr.ss_family == AF_INET) {\n                struct sockaddr_in *s = (struct sockaddr_in *)&remote->addr;\n                if (s->sin_addr.s_addr == inet_addr(\"127.0.0.1\"))\n                    not_protect = 1;\n            }\n            if (!not_protect) {\n                if (protect_socket(remote->fd) == -1) {\n                    ERROR(\"protect_socket\");\n                    close_and_free_remote(EV_A_ remote);\n                    close_and_free_server(EV_A_ server);\n                    return;\n                }\n            }\n        }\n#endif\n\n        remote->buf->idx = 0;\n\n        if (!fast_open || remote->direct) {\n            // connecting, wait until connected\n            int r = connect(remote->fd, (struct sockaddr *)&(remote->addr), remote->addr_len);\n\n            if (r == -1 && errno != CONNECT_IN_PROGRESS) {\n                ERROR(\"connect\");\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n                return;\n            }\n\n            // wait on remote connected event\n            ev_io_stop(EV_A_ & server_recv_ctx->io);\n            ev_io_start(EV_A_ & remote->send_ctx->io);\n            ev_timer_start(EV_A_ & remote->send_ctx->watcher);\n        } else {\n#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT)\n            int s = -1;\n            s = sendto(remote->fd, remote->buf->data, remote->buf->len, MSG_FASTOPEN,\n                       (struct sockaddr *)&(remote->addr), remote->addr_len);\n#elif defined(TCP_FASTOPEN_WINSOCK)\n            DWORD s   = -1;\n            DWORD err = 0;\n            do {\n                int optval = 1;\n                // Set fast open option\n                if (setsockopt(remote->fd, IPPROTO_TCP, TCP_FASTOPEN,\n                               &optval, sizeof(optval)) != 0) {\n                    ERROR(\"setsockopt\");\n                    break;\n                }\n                // Load ConnectEx function\n                LPFN_CONNECTEX ConnectEx = winsock_getconnectex();\n                if (ConnectEx == NULL) {\n                    LOGE(\"Cannot load ConnectEx() function\");\n                    err = WSAENOPROTOOPT;\n                    break;\n                }\n                // ConnectEx requires a bound socket\n                if (winsock_dummybind(remote->fd,\n                                      (struct sockaddr *)&(remote->addr)) != 0) {\n                    ERROR(\"bind\");\n                    break;\n                }\n                // Call ConnectEx to send data\n                memset(&remote->olap, 0, sizeof(remote->olap));\n                remote->connect_ex_done = 0;\n                if (ConnectEx(remote->fd, (const struct sockaddr *)&(remote->addr),\n                              remote->addr_len, remote->buf->data, remote->buf->len,\n                              &s, &remote->olap)) {\n                    remote->connect_ex_done = 1;\n                    break;\n                }\n                // XXX: ConnectEx pending, check later in remote_send\n                if (WSAGetLastError() == ERROR_IO_PENDING) {\n                    err = CONNECT_IN_PROGRESS;\n                    break;\n                }\n                ERROR(\"ConnectEx\");\n            } while (0);\n            // Set error number\n            if (err) {\n                SetLastError(err);\n            }\n#else\n            int s = -1;\n#if defined(CONNECT_DATA_IDEMPOTENT)\n            ((struct sockaddr_in *)&(remote->addr))->sin_len = sizeof(struct sockaddr_in);\n            sa_endpoints_t endpoints;\n            memset((char *)&endpoints, 0, sizeof(endpoints));\n            endpoints.sae_dstaddr    = (struct sockaddr *)&(remote->addr);\n            endpoints.sae_dstaddrlen = remote->addr_len;\n\n            s = connectx(remote->fd, &endpoints, SAE_ASSOCID_ANY,\n                         CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,\n                         NULL, 0, NULL, NULL);\n#elif defined(TCP_FASTOPEN_CONNECT)\n            int optval = 1;\n            if (setsockopt(remote->fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,\n                           (void *)&optval, sizeof(optval)) < 0)\n                FATAL(\"failed to set TCP_FASTOPEN_CONNECT\");\n            s = connect(remote->fd, (struct sockaddr *)&(remote->addr), remote->addr_len);\n#else\n            FATAL(\"fast open is not enabled in this build\");\n#endif\n            if (s == 0)\n                s = send(remote->fd, remote->buf->data, remote->buf->len, 0);\n#endif\n            if (s == -1) {\n                if (errno == CONNECT_IN_PROGRESS) {\n                    // in progress, wait until connected\n                    remote->buf->idx = 0;\n                    ev_io_stop(EV_A_ & server_recv_ctx->io);\n                    ev_io_start(EV_A_ & remote->send_ctx->io);\n                    return;\n                } else {\n                    if (errno == EOPNOTSUPP || errno == EPROTONOSUPPORT ||\n                        errno == ENOPROTOOPT) {\n                        LOGE(\"fast open is not supported on this platform\");\n                        // just turn it off\n                        fast_open = 0;\n                    } else {\n                        ERROR(\"fast_open_connect\");\n                    }\n                    close_and_free_remote(EV_A_ remote);\n                    close_and_free_server(EV_A_ server);\n                    return;\n                }\n            } else {\n                remote->buf->len -= s;\n                remote->buf->idx  = s;\n\n                ev_io_stop(EV_A_ & server_recv_ctx->io);\n                ev_io_start(EV_A_ & remote->send_ctx->io);\n                ev_timer_start(EV_A_ & remote->send_ctx->watcher);\n                return;\n            }\n        }\n    } else {\n        int s = send(remote->fd, remote->buf->data, remote->buf->len, 0);\n        if (s == -1) {\n            if (errno == EAGAIN || errno == EWOULDBLOCK) {\n                // no data, wait for send\n                remote->buf->idx = 0;\n                ev_io_stop(EV_A_ & server_recv_ctx->io);\n                ev_io_start(EV_A_ & remote->send_ctx->io);\n                return;\n            } else {\n                ERROR(\"server_recv_cb_send\");\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n                return;\n            }\n        } else if (s < (int)(remote->buf->len)) {\n            remote->buf->len -= s;\n            remote->buf->idx  = s;\n            ev_io_stop(EV_A_ & server_recv_ctx->io);\n            ev_io_start(EV_A_ & remote->send_ctx->io);\n            return;\n        } else {\n            remote->buf->idx = 0;\n            remote->buf->len = 0;\n        }\n    }\n}\n\nstatic void\nserver_recv_cb(EV_P_ ev_io *w, int revents)\n{\n    server_ctx_t *server_recv_ctx = (server_ctx_t *)w;\n    server_t *server              = server_recv_ctx->server;\n    remote_t *remote              = server->remote;\n    buffer_t *buf;\n    ssize_t r;\n\n    ev_timer_stop(EV_A_ & server->delayed_connect_watcher);\n\n    if (remote == NULL) {\n        buf = server->buf;\n    } else {\n        buf = remote->buf;\n    }\n\n    if (revents != EV_TIMER) {\n        r = recv(server->fd, buf->data + buf->len, SOCKET_BUF_SIZE - buf->len, 0);\n\n        if (r == 0) {\n            // connection closed\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        } else if (r == -1) {\n            if (errno == EAGAIN || errno == EWOULDBLOCK) {\n                // no data\n                // continue to wait for recv\n                return;\n            } else {\n                if (verbose)\n                    ERROR(\"server_recv_cb_recv\");\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n                return;\n            }\n        }\n        buf->len += r;\n    }\n\n    while (1) {\n        // local socks5 server\n        if (server->stage == STAGE_STREAM) {\n            server_stream(EV_A_ w, buf);\n\n            // all processed\n            return;\n        } else if (server->stage == STAGE_INIT) {\n            if (verbose) {\n                struct sockaddr_in peer_addr;\n                socklen_t peer_addr_len = sizeof peer_addr;\n                if (getpeername(server->fd, (struct sockaddr *)&peer_addr, &peer_addr_len) == 0) {\n                    LOGI(\"connection from %s:%hu\", inet_ntoa(peer_addr.sin_addr), ntohs(peer_addr.sin_port));\n                }\n            }\n            if (buf->len < 1)\n                return;\n            if (buf->data[0] != SVERSION) {\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n                return;\n            }\n            if (buf->len < sizeof(struct method_select_request)) {\n                return;\n            }\n            struct method_select_request *method = (struct method_select_request *)buf->data;\n            int method_len                       = method->nmethods + sizeof(struct method_select_request);\n            if (buf->len < method_len) {\n                return;\n            }\n\n            struct method_select_response response;\n            response.ver    = SVERSION;\n            response.method = METHOD_UNACCEPTABLE;\n            for (int i = 0; i < method->nmethods; i++)\n                if (method->methods[i] == METHOD_NOAUTH) {\n                    response.method = METHOD_NOAUTH;\n                    break;\n                }\n            char *send_buf = (char *)&response;\n            send(server->fd, send_buf, sizeof(response), 0);\n            if (response.method == METHOD_UNACCEPTABLE) {\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n                return;\n            }\n\n            server->stage = STAGE_HANDSHAKE;\n\n            if (method_len < (int)(buf->len)) {\n                memmove(buf->data, buf->data + method_len, buf->len - method_len);\n                buf->len -= method_len;\n                continue;\n            }\n\n            buf->len = 0;\n            return;\n        } else if (server->stage == STAGE_HANDSHAKE) {\n            int ret = server_handshake(EV_A_ w, buf);\n            if (ret)\n                return;\n        }\n    }\n}\n\nstatic void\nserver_send_cb(EV_P_ ev_io *w, int revents)\n{\n    server_ctx_t *server_send_ctx = (server_ctx_t *)w;\n    server_t *server              = server_send_ctx->server;\n    remote_t *remote              = server->remote;\n    if (server->buf->len == 0) {\n        // close and free\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else {\n        // has data to send\n        ssize_t s = send(server->fd, server->buf->data + server->buf->idx,\n                         server->buf->len, 0);\n        if (s == -1) {\n            if (errno != EAGAIN && errno != EWOULDBLOCK) {\n                ERROR(\"server_send_cb_send\");\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n            }\n            return;\n        } else if (s < (ssize_t)(server->buf->len)) {\n            // partly sent, move memory, wait for the next time to send\n            server->buf->len -= s;\n            server->buf->idx += s;\n            return;\n        } else {\n            // all sent out, wait for reading\n            server->buf->len = 0;\n            server->buf->idx = 0;\n            ev_io_stop(EV_A_ & server_send_ctx->io);\n            ev_io_start(EV_A_ & remote->recv_ctx->io);\n            return;\n        }\n    }\n}\n\n#ifdef __ANDROID__\nvoid\nstat_update_cb()\n{\n    ev_tstamp now = ev_time();\n    if (now - last > 0.5) {\n        send_traffic_stat(tx, rx);\n        last = now;\n    }\n}\n\n#endif\n\nstatic void\nremote_timeout_cb(EV_P_ ev_timer *watcher, int revents)\n{\n    remote_ctx_t *remote_ctx\n        = cork_container_of(watcher, remote_ctx_t, watcher);\n\n    remote_t *remote = remote_ctx->remote;\n    server_t *server = remote->server;\n\n    if (verbose) {\n        LOGI(\"TCP connection timeout\");\n    }\n\n    close_and_free_remote(EV_A_ remote);\n    close_and_free_server(EV_A_ server);\n}\n\nstatic void\nremote_recv_cb(EV_P_ ev_io *w, int revents)\n{\n    remote_ctx_t *remote_recv_ctx = (remote_ctx_t *)w;\n    remote_t *remote              = remote_recv_ctx->remote;\n    server_t *server              = remote->server;\n\n    ssize_t r = recv(remote->fd, server->buf->data, SOCKET_BUF_SIZE, 0);\n\n    if (r == 0) {\n        // connection closed\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else if (r == -1) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) {\n            // no data\n            // continue to wait for recv\n            return;\n        } else {\n            ERROR(\"remote_recv_cb_recv\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    }\n\n    server->buf->len = r;\n\n    if (!remote->direct) {\n#ifdef __ANDROID__\n        rx += server->buf->len;\n        stat_update_cb();\n#endif\n        int err = crypto->decrypt(server->buf, server->d_ctx, SOCKET_BUF_SIZE);\n        if (err == CRYPTO_ERROR) {\n            LOGE(\"invalid password or cipher\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        } else if (err == CRYPTO_NEED_MORE) {\n            return; // Wait for more\n        }\n    }\n\n    int s = send(server->fd, server->buf->data, server->buf->len, 0);\n\n    if (s == -1) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) {\n            // no data, wait for send\n            server->buf->idx = 0;\n            ev_io_stop(EV_A_ & remote_recv_ctx->io);\n            ev_io_start(EV_A_ & server->send_ctx->io);\n        } else {\n            ERROR(\"remote_recv_cb_send\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    } else if (s < (int)(server->buf->len)) {\n        server->buf->len -= s;\n        server->buf->idx  = s;\n        ev_io_stop(EV_A_ & remote_recv_ctx->io);\n        ev_io_start(EV_A_ & server->send_ctx->io);\n    }\n\n    // Disable TCP_NODELAY after the first response are sent\n    if (!remote->recv_ctx->connected && !no_delay) {\n        int opt = 0;\n        setsockopt(server->fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n        setsockopt(remote->fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n    }\n    remote->recv_ctx->connected = 1;\n}\n\nstatic void\nremote_send_cb(EV_P_ ev_io *w, int revents)\n{\n    remote_ctx_t *remote_send_ctx = (remote_ctx_t *)w;\n    remote_t *remote              = remote_send_ctx->remote;\n    server_t *server              = remote->server;\n\n    if (!remote_send_ctx->connected) {\n#ifdef TCP_FASTOPEN_WINSOCK\n        if (fast_open) {\n            // Check if ConnectEx is done\n            if (!remote->connect_ex_done) {\n                DWORD numBytes;\n                DWORD flags;\n                // Non-blocking way to fetch ConnectEx result\n                if (WSAGetOverlappedResult(remote->fd, &remote->olap,\n                                           &numBytes, FALSE, &flags)) {\n                    remote->buf->len       -= numBytes;\n                    remote->buf->idx        = numBytes;\n                    remote->connect_ex_done = 1;\n                } else if (WSAGetLastError() == WSA_IO_INCOMPLETE) {\n                    // XXX: ConnectEx still not connected, wait for next time\n                    return;\n                } else {\n                    ERROR(\"WSAGetOverlappedResult\");\n                    // not connected\n                    close_and_free_remote(EV_A_ remote);\n                    close_and_free_server(EV_A_ server);\n                    return;\n                }\n            }\n\n            // Make getpeername work\n            if (setsockopt(remote->fd, SOL_SOCKET,\n                           SO_UPDATE_CONNECT_CONTEXT, NULL, 0) != 0) {\n                ERROR(\"setsockopt\");\n            }\n        }\n#endif\n        struct sockaddr_storage addr;\n        socklen_t len = sizeof addr;\n        int r         = getpeername(remote->fd, (struct sockaddr *)&addr, &len);\n        if (r == 0) {\n            remote_send_ctx->connected = 1;\n            ev_timer_stop(EV_A_ & remote_send_ctx->watcher);\n            ev_io_start(EV_A_ & remote->recv_ctx->io);\n\n            // no need to send any data\n            if (remote->buf->len == 0) {\n                ev_io_stop(EV_A_ & remote_send_ctx->io);\n                ev_io_start(EV_A_ & server->recv_ctx->io);\n                return;\n            }\n        } else {\n            // not connected\n            ERROR(\"getpeername\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    }\n\n    if (remote->buf->len == 0) {\n        // close and free\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else {\n        // has data to send\n        ssize_t s = send(remote->fd, remote->buf->data + remote->buf->idx,\n                         remote->buf->len, 0);\n        if (s == -1) {\n            if (errno != EAGAIN && errno != EWOULDBLOCK) {\n                ERROR(\"remote_send_cb_send\");\n                // close and free\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n            }\n            return;\n        } else if (s < (ssize_t)(remote->buf->len)) {\n            // partly sent, move memory, wait for the next time to send\n            remote->buf->len -= s;\n            remote->buf->idx += s;\n            return;\n        } else {\n            // all sent out, wait for reading\n            remote->buf->len = 0;\n            remote->buf->idx = 0;\n            ev_io_stop(EV_A_ & remote_send_ctx->io);\n            ev_io_start(EV_A_ & server->recv_ctx->io);\n        }\n    }\n}\n\nstatic remote_t *\nnew_remote(int fd, int timeout)\n{\n    remote_t *remote;\n    remote = ss_malloc(sizeof(remote_t));\n\n    memset(remote, 0, sizeof(remote_t));\n\n    remote->buf      = ss_malloc(sizeof(buffer_t));\n    remote->recv_ctx = ss_malloc(sizeof(remote_ctx_t));\n    remote->send_ctx = ss_malloc(sizeof(remote_ctx_t));\n    balloc(remote->buf, SOCKET_BUF_SIZE);\n    memset(remote->recv_ctx, 0, sizeof(remote_ctx_t));\n    memset(remote->send_ctx, 0, sizeof(remote_ctx_t));\n    remote->recv_ctx->connected = 0;\n    remote->send_ctx->connected = 0;\n    remote->fd                  = fd;\n    remote->recv_ctx->remote    = remote;\n    remote->send_ctx->remote    = remote;\n\n    ev_io_init(&remote->recv_ctx->io, remote_recv_cb, fd, EV_READ);\n    ev_io_init(&remote->send_ctx->io, remote_send_cb, fd, EV_WRITE);\n    ev_timer_init(&remote->send_ctx->watcher, remote_timeout_cb,\n                  min(MAX_CONNECT_TIMEOUT, timeout), 0);\n\n    return remote;\n}\n\nstatic void\nfree_remote(remote_t *remote)\n{\n    if (remote->server != NULL) {\n        remote->server->remote = NULL;\n    }\n    if (remote->buf != NULL) {\n        bfree(remote->buf);\n        ss_free(remote->buf);\n    }\n    ss_free(remote->recv_ctx);\n    ss_free(remote->send_ctx);\n    ss_free(remote);\n}\n\nstatic void\nclose_and_free_remote(EV_P_ remote_t *remote)\n{\n    if (remote != NULL) {\n        ev_timer_stop(EV_A_ & remote->send_ctx->watcher);\n        ev_io_stop(EV_A_ & remote->send_ctx->io);\n        ev_io_stop(EV_A_ & remote->recv_ctx->io);\n        close(remote->fd);\n        free_remote(remote);\n    }\n}\n\nstatic server_t *\nnew_server(int fd)\n{\n    server_t *server;\n    server = ss_malloc(sizeof(server_t));\n\n    memset(server, 0, sizeof(server_t));\n\n    server->recv_ctx = ss_malloc(sizeof(server_ctx_t));\n    server->send_ctx = ss_malloc(sizeof(server_ctx_t));\n    server->buf      = ss_malloc(sizeof(buffer_t));\n    server->abuf     = ss_malloc(sizeof(buffer_t));\n    balloc(server->buf, SOCKET_BUF_SIZE);\n    balloc(server->abuf, SOCKET_BUF_SIZE);\n    memset(server->recv_ctx, 0, sizeof(server_ctx_t));\n    memset(server->send_ctx, 0, sizeof(server_ctx_t));\n    server->stage               = STAGE_INIT;\n    server->recv_ctx->connected = 0;\n    server->send_ctx->connected = 0;\n    server->fd                  = fd;\n    server->recv_ctx->server    = server;\n    server->send_ctx->server    = server;\n\n    server->e_ctx = ss_malloc(sizeof(cipher_ctx_t));\n    server->d_ctx = ss_malloc(sizeof(cipher_ctx_t));\n    crypto->ctx_init(crypto->cipher, server->e_ctx, 1);\n    crypto->ctx_init(crypto->cipher, server->d_ctx, 0);\n\n    ev_io_init(&server->recv_ctx->io, server_recv_cb, fd, EV_READ);\n    ev_io_init(&server->send_ctx->io, server_send_cb, fd, EV_WRITE);\n\n    ev_timer_init(&server->delayed_connect_watcher,\n                  delayed_connect_cb, 0.05, 0);\n\n    cork_dllist_add(&connections, &server->entries);\n\n    return server;\n}\n\nstatic void\nfree_server(server_t *server)\n{\n    cork_dllist_remove(&server->entries);\n\n    if (server->remote != NULL) {\n        server->remote->server = NULL;\n    }\n    if (server->e_ctx != NULL) {\n        crypto->ctx_release(server->e_ctx);\n        ss_free(server->e_ctx);\n    }\n    if (server->d_ctx != NULL) {\n        crypto->ctx_release(server->d_ctx);\n        ss_free(server->d_ctx);\n    }\n    if (server->buf != NULL) {\n        bfree(server->buf);\n        ss_free(server->buf);\n    }\n    if (server->abuf != NULL) {\n        bfree(server->abuf);\n        ss_free(server->abuf);\n    }\n    ss_free(server->recv_ctx);\n    ss_free(server->send_ctx);\n    ss_free(server);\n}\n\nstatic void\nclose_and_free_server(EV_P_ server_t *server)\n{\n    if (server != NULL) {\n        ev_io_stop(EV_A_ & server->send_ctx->io);\n        ev_io_stop(EV_A_ & server->recv_ctx->io);\n        ev_timer_stop(EV_A_ & server->delayed_connect_watcher);\n        close(server->fd);\n        free_server(server);\n    }\n}\n\nstatic remote_t *\ncreate_remote(listen_ctx_t *listener,\n              struct sockaddr *addr,\n              int direct)\n{\n    struct sockaddr *remote_addr;\n\n    int index = rand() % listener->remote_num;\n    if (addr == NULL) {\n        remote_addr = listener->remote_addr[index];\n    } else {\n        remote_addr = addr;\n    }\n\n    int protocol = IPPROTO_TCP;\n    if (listener->mptcp < 0) {\n        protocol = IPPROTO_MPTCP; // Enable upstream MPTCP\n    }\n    int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, protocol);\n    if (remotefd == -1) {\n        ERROR(\"socket\");\n        return NULL;\n    }\n\n    int opt = 1;\n    setsockopt(remotefd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n#ifdef SO_NOSIGPIPE\n    setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));\n#endif\n\n    // Enable out-of-tree MPTCP\n    if (listener->mptcp > 1) {\n        int err = setsockopt(remotefd, SOL_TCP, listener->mptcp, &opt, sizeof(opt));\n        if (err == -1) {\n            ERROR(\"failed to enable out-of-tree multipath TCP\");\n        }\n    } else if (listener->mptcp == 1) {\n        int i = 0;\n        while ((listener->mptcp = mptcp_enabled_values[i]) > 0) {\n            int err = setsockopt(remotefd, SOL_TCP, listener->mptcp, &opt, sizeof(opt));\n            if (err != -1) {\n                break;\n            }\n            i++;\n        }\n        if (listener->mptcp == 0) {\n            ERROR(\"failed to enable out-of-tree multipath TCP\");\n        }\n    }\n\n    if (tcp_outgoing_sndbuf > 0) {\n        setsockopt(remotefd, SOL_SOCKET, SO_SNDBUF, &tcp_outgoing_sndbuf, sizeof(int));\n    }\n\n    if (tcp_outgoing_rcvbuf > 0) {\n        setsockopt(remotefd, SOL_SOCKET, SO_RCVBUF, &tcp_outgoing_rcvbuf, sizeof(int));\n    }\n\n    // Setup\n    setnonblocking(remotefd);\n#ifdef SET_INTERFACE\n    if (listener->iface) {\n        if (setinterface(remotefd, listener->iface) == -1)\n            ERROR(\"setinterface\");\n    }\n#endif\n\n    remote_t *remote = new_remote(remotefd, direct ? MAX_CONNECT_TIMEOUT : listener->timeout);\n    remote->addr_len = get_sockaddr_len(remote_addr);\n    memcpy(&(remote->addr), remote_addr, remote->addr_len);\n    remote->direct = direct;\n\n    if (verbose) {\n        struct sockaddr_in *sockaddr = (struct sockaddr_in *)&remote->addr;\n        LOGI(\"remote: %s:%hu\", inet_ntoa(sockaddr->sin_addr), ntohs(sockaddr->sin_port));\n    }\n\n    return remote;\n}\n\nstatic void\nsignal_cb(EV_P_ ev_signal *w, int revents)\n{\n    if (revents & EV_SIGNAL) {\n        switch (w->signum) {\n#ifndef __MINGW32__\n        case SIGCHLD:\n            if (!is_plugin_running()) {\n                LOGE(\"plugin service exit unexpectedly\");\n                ret_val = -1;\n            } else\n                return;\n        case SIGUSR1:\n#endif\n        case SIGINT:\n        case SIGTERM:\n            ev_signal_stop(EV_DEFAULT, &sigint_watcher);\n            ev_signal_stop(EV_DEFAULT, &sigterm_watcher);\n#ifndef __MINGW32__\n            ev_signal_stop(EV_DEFAULT, &sigchld_watcher);\n            ev_signal_stop(EV_DEFAULT, &sigusr1_watcher);\n#else\n#ifndef LIB_ONLY\n            ev_io_stop(EV_DEFAULT, &plugin_watcher.io);\n#endif\n#endif\n            ev_unloop(EV_A_ EVUNLOOP_ALL);\n        }\n    }\n}\n\n#if defined(__MINGW32__) && !defined(LIB_ONLY)\nstatic void\nplugin_watcher_cb(EV_P_ ev_io *w, int revents)\n{\n    char buf[1];\n    SOCKET fd = accept(plugin_watcher.fd, NULL, NULL);\n    if (fd == INVALID_SOCKET) {\n        return;\n    }\n    recv(fd, buf, 1, 0);\n    closesocket(fd);\n    LOGE(\"plugin service exit unexpectedly\");\n    ret_val = -1;\n    ev_signal_stop(EV_DEFAULT, &sigint_watcher);\n    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);\n    ev_io_stop(EV_DEFAULT, &plugin_watcher.io);\n    ev_unloop(EV_A_ EVUNLOOP_ALL);\n}\n\n#endif\n\nvoid\naccept_cb(EV_P_ ev_io *w, int revents)\n{\n    listen_ctx_t *listener = (listen_ctx_t *)w;\n    int serverfd           = accept(listener->fd, NULL, NULL);\n    if (serverfd == -1) {\n        ERROR(\"accept\");\n        return;\n    }\n    setnonblocking(serverfd);\n    int opt = 1;\n    setsockopt(serverfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n#ifdef SO_NOSIGPIPE\n    setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));\n#endif\n\n    if (tcp_incoming_sndbuf > 0) {\n        setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &tcp_incoming_sndbuf, sizeof(int));\n    }\n\n    if (tcp_incoming_rcvbuf > 0) {\n        setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &tcp_incoming_rcvbuf, sizeof(int));\n    }\n\n    server_t *server = new_server(serverfd);\n    server->listener = listener;\n\n    ev_io_start(EV_A_ & server->recv_ctx->io);\n}\n\n#ifndef LIB_ONLY\nint\nmain(int argc, char **argv)\n{\n    int i, c;\n    int pid_flags    = 0;\n    int mtu          = 0;\n    int mptcp        = 0;\n    char *user       = NULL;\n    char *local_port = NULL;\n    char *local_addr = NULL;\n    char *password   = NULL;\n    char *key        = NULL;\n    char *timeout    = NULL;\n    char *method     = NULL;\n    char *pid_path   = NULL;\n    char *conf_path  = NULL;\n    char *iface      = NULL;\n\n    char *plugin      = NULL;\n    char *plugin_opts = NULL;\n    char *plugin_host = NULL;\n    char *plugin_port = NULL;\n    char tmp_port[8];\n\n    int remote_num = 0;\n    ss_addr_t remote_addr[MAX_REMOTE_NUM];\n    char *remote_port = NULL;\n\n    memset(remote_addr, 0, sizeof(ss_addr_t) * MAX_REMOTE_NUM);\n    srand(time(NULL));\n\n    static struct option long_options[] = {\n        { \"reuse-port\",  no_argument,       NULL, GETOPT_VAL_REUSE_PORT  },\n        { \"tcp-incoming-sndbuf\", required_argument, NULL, GETOPT_VAL_TCP_INCOMING_SNDBUF },\n        { \"tcp-incoming-rcvbuf\", required_argument, NULL, GETOPT_VAL_TCP_INCOMING_RCVBUF },\n        { \"tcp-outgoing-sndbuf\", required_argument, NULL, GETOPT_VAL_TCP_OUTGOING_SNDBUF },\n        { \"tcp-outgoing-rcvbuf\", required_argument, NULL, GETOPT_VAL_TCP_OUTGOING_RCVBUF },\n        { \"fast-open\",   no_argument,       NULL, GETOPT_VAL_FAST_OPEN   },\n        { \"no-delay\",    no_argument,       NULL, GETOPT_VAL_NODELAY     },\n        { \"acl\",         required_argument, NULL, GETOPT_VAL_ACL         },\n        { \"mtu\",         required_argument, NULL, GETOPT_VAL_MTU         },\n        { \"mptcp\",       no_argument,       NULL, GETOPT_VAL_MPTCP       },\n        { \"plugin\",      required_argument, NULL, GETOPT_VAL_PLUGIN      },\n        { \"plugin-opts\", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },\n        { \"password\",    required_argument, NULL, GETOPT_VAL_PASSWORD    },\n        { \"key\",         required_argument, NULL, GETOPT_VAL_KEY         },\n        { \"help\",        no_argument,       NULL, GETOPT_VAL_HELP        },\n        { NULL,          0,                 NULL, 0                      }\n    };\n\n    opterr = 0;\n\n    USE_TTY();\n\n#ifdef __ANDROID__\n    while ((c = getopt_long(argc, argv, \"f:s:p:l:k:t:m:i:c:b:a:n:S:huUvV6A\",\n                            long_options, NULL)) != -1) {\n#else\n    while ((c = getopt_long(argc, argv, \"f:s:p:l:k:t:m:i:c:b:a:n:huUv6A\",\n                            long_options, NULL)) != -1) {\n#endif\n        switch (c) {\n        case GETOPT_VAL_FAST_OPEN:\n            fast_open = 1;\n            break;\n        case GETOPT_VAL_ACL:\n            LOGI(\"initializing acl...\");\n            acl = !init_acl(optarg);\n            break;\n        case GETOPT_VAL_MTU:\n            mtu = atoi(optarg);\n            LOGI(\"set MTU to %d\", mtu);\n            break;\n        case GETOPT_VAL_MPTCP:\n            mptcp = get_mptcp(1);\n            if (mptcp)\n                LOGI(\"enable multipath TCP (%s)\", mptcp > 0 ? \"out-of-tree\" : \"upstream\");\n            break;\n        case GETOPT_VAL_NODELAY:\n            no_delay = 1;\n            LOGI(\"enable TCP no-delay\");\n            break;\n        case GETOPT_VAL_PLUGIN:\n            plugin = optarg;\n            break;\n        case GETOPT_VAL_PLUGIN_OPTS:\n            plugin_opts = optarg;\n            break;\n        case GETOPT_VAL_KEY:\n            key = optarg;\n            break;\n        case GETOPT_VAL_REUSE_PORT:\n            reuse_port = 1;\n            break;\n        case GETOPT_VAL_TCP_INCOMING_SNDBUF:\n            tcp_incoming_sndbuf = atoi(optarg);\n            break;\n        case GETOPT_VAL_TCP_INCOMING_RCVBUF:\n            tcp_incoming_rcvbuf = atoi(optarg);\n            break;\n        case GETOPT_VAL_TCP_OUTGOING_SNDBUF:\n            tcp_outgoing_sndbuf = atoi(optarg);\n            break;\n        case GETOPT_VAL_TCP_OUTGOING_RCVBUF:\n            tcp_outgoing_rcvbuf = atoi(optarg);\n            break;\n        case 's':\n            if (remote_num < MAX_REMOTE_NUM) {\n                parse_addr(optarg, &remote_addr[remote_num++]);\n            }\n            break;\n        case 'p':\n            remote_port = optarg;\n            break;\n        case 'l':\n            local_port = optarg;\n            break;\n        case GETOPT_VAL_PASSWORD:\n        case 'k':\n            password = optarg;\n            break;\n        case 'f':\n            pid_flags = 1;\n            pid_path  = optarg;\n            break;\n        case 't':\n            timeout = optarg;\n            break;\n        case 'm':\n            method = optarg;\n            break;\n        case 'c':\n            conf_path = optarg;\n            break;\n        case 'i':\n            iface = optarg;\n            break;\n        case 'b':\n            local_addr = optarg;\n            break;\n        case 'a':\n            user = optarg;\n            break;\n#ifdef HAVE_SETRLIMIT\n        case 'n':\n            nofile = atoi(optarg);\n            break;\n#endif\n        case 'u':\n            mode = TCP_AND_UDP;\n            break;\n        case 'U':\n            mode = UDP_ONLY;\n            break;\n        case 'v':\n            verbose = 1;\n            break;\n        case 'h':\n        case GETOPT_VAL_HELP:\n            usage();\n            exit(EXIT_SUCCESS);\n        case '6':\n            ipv6first = 1;\n            break;\n#ifdef __ANDROID__\n        case 'S':\n            stat_path = optarg;\n            break;\n        case 'V':\n            vpn = 1;\n            break;\n#endif\n        case 'A':\n            FATAL(\"One time auth has been deprecated. Try AEAD ciphers instead.\");\n            break;\n        case '?':\n            // The option character is not recognized.\n            LOGE(\"Unrecognized option: %s\", optarg);\n            opterr = 1;\n            break;\n        }\n    }\n\n    if (opterr) {\n        usage();\n        exit(EXIT_FAILURE);\n    }\n\n    if (argc == 1) {\n        if (conf_path == NULL) {\n            conf_path = get_default_conf();\n        }\n    }\n    if (conf_path != NULL) {\n        jconf_t *conf = read_jconf(conf_path);\n        if (remote_num == 0) {\n            remote_num = conf->remote_num;\n            for (i = 0; i < remote_num; i++)\n                remote_addr[i] = conf->remote_addr[i];\n        }\n        if (remote_port == NULL) {\n            remote_port = conf->remote_port;\n        }\n        if (local_addr == NULL) {\n            local_addr = conf->local_addr;\n        }\n        if (local_port == NULL) {\n            local_port = conf->local_port;\n        }\n        if (password == NULL) {\n            password = conf->password;\n        }\n        if (key == NULL) {\n            key = conf->key;\n        }\n        if (method == NULL) {\n            method = conf->method;\n        }\n        if (timeout == NULL) {\n            timeout = conf->timeout;\n        }\n        if (user == NULL) {\n            user = conf->user;\n        }\n        if (plugin == NULL) {\n            plugin = conf->plugin;\n        }\n        if (plugin_opts == NULL) {\n            plugin_opts = conf->plugin_opts;\n        }\n        if (reuse_port == 0) {\n            reuse_port = conf->reuse_port;\n        }\n        if (tcp_incoming_sndbuf == 0) {\n            tcp_incoming_sndbuf = conf->tcp_incoming_sndbuf;\n        }\n        if (tcp_incoming_rcvbuf == 0) {\n            tcp_incoming_rcvbuf = conf->tcp_incoming_rcvbuf;\n        }\n        if (tcp_outgoing_sndbuf == 0) {\n            tcp_outgoing_sndbuf = conf->tcp_outgoing_sndbuf;\n        }\n        if (tcp_outgoing_rcvbuf == 0) {\n            tcp_outgoing_rcvbuf = conf->tcp_outgoing_rcvbuf;\n        }\n        if (fast_open == 0) {\n            fast_open = conf->fast_open;\n        }\n        if (mode == TCP_ONLY) {\n            mode = conf->mode;\n        }\n        if (mtu == 0) {\n            mtu = conf->mtu;\n        }\n        if (mptcp == 0) {\n            mptcp = conf->mptcp;\n        }\n        if (no_delay == 0) {\n            no_delay = conf->no_delay;\n        }\n#ifdef HAVE_SETRLIMIT\n        if (nofile == 0) {\n            nofile = conf->nofile;\n        }\n#endif\n        if (ipv6first == 0) {\n            ipv6first = conf->ipv6_first;\n        }\n        if (acl == 0 && conf->acl != NULL) {\n            LOGI(\"initializing acl...\");\n            acl = !init_acl(conf->acl);\n        }\n    }\n\n    if (remote_num == 0) {\n        fprintf(stderr, \"remote_num is 0\\n\");\n        exit(EXIT_FAILURE);\n    }\n    if (!remote_port) {\n        fprintf(stderr, \"remote_port is NULL\\n\");\n        exit(EXIT_FAILURE);\n    }\n#ifndef HAVE_LAUNCHD\n    if (!local_port) {\n        fprintf(stderr, \"local_port is NULL\\n\");\n        exit(EXIT_FAILURE);\n    }\n#endif\n    if (!password && !key) {\n        fprintf(stderr, \"both password and key are NULL\\n\");\n        exit(EXIT_FAILURE);\n    }\n\n#ifdef __MINGW32__\n    winsock_init();\n#endif\n\n    if (tcp_incoming_sndbuf != 0 && tcp_incoming_sndbuf < SOCKET_BUF_SIZE) {\n        tcp_incoming_sndbuf = 0;\n    }\n\n    if (tcp_incoming_sndbuf != 0) {\n        LOGI(\"set TCP incoming connection send buffer size to %d\", tcp_incoming_sndbuf);\n    }\n\n    if (tcp_incoming_rcvbuf != 0 && tcp_incoming_rcvbuf < SOCKET_BUF_SIZE) {\n        tcp_incoming_rcvbuf = 0;\n    }\n\n    if (tcp_incoming_rcvbuf != 0) {\n        LOGI(\"set TCP incoming connection receive buffer size to %d\", tcp_incoming_rcvbuf);\n    }\n\n    if (tcp_outgoing_sndbuf != 0 && tcp_outgoing_sndbuf < SOCKET_BUF_SIZE) {\n        tcp_outgoing_sndbuf = 0;\n    }\n\n    if (tcp_outgoing_sndbuf != 0) {\n        LOGI(\"set TCP outgoing connection send buffer size to %d\", tcp_outgoing_sndbuf);\n    }\n\n    if (tcp_outgoing_rcvbuf != 0 && tcp_outgoing_rcvbuf < SOCKET_BUF_SIZE) {\n        tcp_outgoing_rcvbuf = 0;\n    }\n\n    if (tcp_outgoing_rcvbuf != 0) {\n        LOGI(\"set TCP outgoing connection receive buffer size to %d\", tcp_outgoing_rcvbuf);\n    }\n\n    if (plugin != NULL) {\n        uint16_t port = get_local_port();\n        if (port == 0) {\n            FATAL(\"failed to find a free port\");\n        }\n        snprintf(tmp_port, 8, \"%d\", port);\n        if (is_ipv6only(remote_addr, remote_num, ipv6first)) {\n            plugin_host = \"::1\";\n        } else {\n            plugin_host = \"127.0.0.1\";\n        }\n        plugin_port = tmp_port;\n\n#ifdef __MINGW32__\n        memset(&plugin_watcher, 0, sizeof(plugin_watcher));\n        plugin_watcher.port = get_local_port();\n        if (plugin_watcher.port == 0) {\n            LOGE(\"failed to assign a control port for plugin\");\n        }\n#endif\n\n        LOGI(\"plugin \\\"%s\\\" enabled\", plugin);\n    }\n\n    if (method == NULL) {\n        method = \"chacha20-ietf-poly1305\";\n    }\n\n    if (timeout == NULL) {\n        timeout = \"60\";\n    }\n\n#ifdef HAVE_SETRLIMIT\n    /*\n     * no need to check the return value here since we will show\n     * the user an error message if setrlimit(2) fails\n     */\n    if (nofile > 1024) {\n        if (verbose) {\n            LOGI(\"setting NOFILE to %d\", nofile);\n        }\n        set_nofile(nofile);\n    }\n#endif\n\n    if (local_addr == NULL) {\n        if (is_ipv6only(remote_addr, remote_num, ipv6first)) {\n            local_addr = \"::1\";\n        } else {\n            local_addr = \"127.0.0.1\";\n        }\n    }\n\n    USE_SYSLOG(argv[0], pid_flags);\n    if (pid_flags) {\n        daemonize(pid_path);\n    }\n\n    if (fast_open == 1) {\n#ifdef TCP_FASTOPEN\n        LOGI(\"using tcp fast open\");\n#else\n        LOGE(\"tcp fast open is not supported by this environment\");\n        fast_open = 0;\n#endif\n    }\n\n    if (no_delay) {\n        LOGI(\"enable TCP no-delay\");\n    }\n\n    if (ipv6first) {\n        LOGI(\"resolving hostname to IPv6 address first\");\n    }\n\n#ifdef __MINGW32__\n    // Listen on plugin control port\n    if (plugin != NULL && plugin_watcher.port != 0) {\n        SOCKET fd;\n        fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);\n        if (fd != INVALID_SOCKET) {\n            plugin_watcher.valid = 0;\n            do {\n                struct sockaddr_in addr;\n                memset(&addr, 0, sizeof(addr));\n                addr.sin_family      = AF_INET;\n                addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);\n                addr.sin_port        = htons(plugin_watcher.port);\n                if (bind(fd, (struct sockaddr *)&addr, sizeof(addr))) {\n                    LOGE(\"failed to bind plugin control port\");\n                    break;\n                }\n                if (listen(fd, 1)) {\n                    LOGE(\"failed to listen on plugin control port\");\n                    break;\n                }\n                plugin_watcher.fd = fd;\n                ev_io_init(&plugin_watcher.io, plugin_watcher_cb, fd, EV_READ);\n                ev_io_start(EV_DEFAULT, &plugin_watcher.io);\n                plugin_watcher.valid = 1;\n            } while (0);\n            if (!plugin_watcher.valid) {\n                closesocket(fd);\n                plugin_watcher.port = 0;\n            }\n        }\n    }\n#endif\n\n    if (plugin != NULL) {\n        int len          = 0;\n        size_t buf_size  = 256 * remote_num;\n        char *remote_str = ss_malloc(buf_size);\n\n        snprintf(remote_str, buf_size, \"%s\", remote_addr[0].host);\n        len = strlen(remote_str);\n        for (int i = 1; i < remote_num; i++) {\n            snprintf(remote_str + len, buf_size - len, \"|%s\", remote_addr[i].host);\n            len = strlen(remote_str);\n        }\n        int err = start_plugin(plugin, plugin_opts, remote_str,\n                               remote_port, plugin_host, plugin_port,\n#ifdef __MINGW32__\n                               plugin_watcher.port,\n#endif\n                               MODE_CLIENT);\n        if (err) {\n            ERROR(\"start_plugin\");\n            FATAL(\"failed to start the plugin\");\n        }\n    }\n\n#ifndef __MINGW32__\n    // ignore SIGPIPE\n    signal(SIGPIPE, SIG_IGN);\n    signal(SIGABRT, SIG_IGN);\n#endif\n\n    // Setup keys\n    LOGI(\"initializing ciphers... %s\", method);\n    crypto = crypto_init(password, key, method);\n    if (crypto == NULL)\n        FATAL(\"failed to initialize ciphers\");\n\n    // Setup proxy context\n    listen_ctx_t listen_ctx;\n    listen_ctx.remote_num  = 0;\n    listen_ctx.remote_addr = ss_malloc(sizeof(struct sockaddr *) * remote_num);\n    memset(listen_ctx.remote_addr, 0, sizeof(struct sockaddr *) * remote_num);\n    for (i = 0; i < remote_num; i++) {\n        char *host = remote_addr[i].host;\n        char *port = remote_addr[i].port == NULL ? remote_port :\n                     remote_addr[i].port;\n        if (plugin != NULL) {\n            host = plugin_host;\n            port = plugin_port;\n        }\n        struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage));\n        memset(storage, 0, sizeof(struct sockaddr_storage));\n        if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) {\n            FATAL(\"failed to resolve the provided hostname\");\n        }\n        listen_ctx.remote_addr[i] = (struct sockaddr *)storage;\n        ++listen_ctx.remote_num;\n\n        if (plugin != NULL)\n            break;\n    }\n    listen_ctx.timeout = atoi(timeout);\n    listen_ctx.iface   = iface;\n    listen_ctx.mptcp   = mptcp;\n\n    // Setup signal handler\n    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);\n    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);\n    ev_signal_start(EV_DEFAULT, &sigint_watcher);\n    ev_signal_start(EV_DEFAULT, &sigterm_watcher);\n#ifndef __MINGW32__\n    ev_signal_init(&sigchld_watcher, signal_cb, SIGCHLD);\n    ev_signal_start(EV_DEFAULT, &sigchld_watcher);\n#endif\n\n    if (ss_is_ipv6addr(local_addr))\n        LOGI(\"listening at [%s]:%s\", local_addr, local_port);\n    else\n        LOGI(\"listening at %s:%s\", local_addr, local_port);\n\n    struct ev_loop *loop = EV_DEFAULT;\n\n    if (mode != UDP_ONLY) {\n        // Setup socket\n        int listenfd;\n#ifdef HAVE_LAUNCHD\n        listenfd = launch_or_create(local_addr, local_port);\n#else\n        listenfd = create_and_bind(local_addr, local_port);\n#endif\n        if (listenfd == -1) {\n            FATAL(\"bind() error\");\n        }\n        if (listen(listenfd, SOMAXCONN) == -1) {\n            FATAL(\"listen() error\");\n        }\n        setnonblocking(listenfd);\n\n        listen_ctx.fd = listenfd;\n\n        ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);\n        ev_io_start(loop, &listen_ctx.io);\n    }\n\n    // Setup UDP\n    if (mode != TCP_ONLY) {\n        LOGI(\"udprelay enabled\");\n        char *host                       = remote_addr[0].host;\n        char *port                       = remote_addr[0].port == NULL ? remote_port : remote_addr[0].port;\n        struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage));\n        memset(storage, 0, sizeof(struct sockaddr_storage));\n        if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) {\n            FATAL(\"failed to resolve the provided hostname\");\n        }\n        struct sockaddr *addr = (struct sockaddr *)storage;\n        udp_fd = init_udprelay(local_addr, local_port, addr,\n                               get_sockaddr_len(addr), mtu, crypto, listen_ctx.timeout, iface);\n    }\n\n#ifdef HAVE_LAUNCHD\n    if (local_port == NULL)\n        LOGI(\"listening through launchd\");\n    else\n#endif\n\n#ifndef __MINGW32__\n    // setuid\n    if (user != NULL && !run_as(user)) {\n        FATAL(\"failed to switch user\");\n    }\n\n    if (geteuid() == 0) {\n        LOGI(\"running from root user\");\n    }\n#endif\n\n    // Init connections\n    cork_dllist_init(&connections);\n\n    // Enter the loop\n    ev_run(loop, 0);\n\n    if (verbose) {\n        LOGI(\"closed gracefully\");\n    }\n\n    // Clean up\n    if (plugin != NULL) {\n        stop_plugin();\n    }\n\n    if (mode != UDP_ONLY) {\n        ev_io_stop(loop, &listen_ctx.io);\n        free_connections(loop);\n\n        for (i = 0; i < listen_ctx.remote_num; i++)\n            ss_free(listen_ctx.remote_addr[i]);\n        ss_free(listen_ctx.remote_addr);\n    }\n\n    if (mode != TCP_ONLY) {\n        free_udprelay();\n    }\n\n#ifdef __MINGW32__\n    if (plugin_watcher.valid) {\n        closesocket(plugin_watcher.fd);\n    }\n\n    winsock_cleanup();\n#endif\n\n    return ret_val;\n}\n\n#else\n\nint\n_start_ss_local_server(profile_t profile, ss_local_callback callback, void *udata)\n{\n    srand(time(NULL));\n\n    char *remote_host = profile.remote_host;\n    char *local_addr  = profile.local_addr;\n    char *method      = profile.method;\n    char *password    = profile.password;\n    char *log         = profile.log;\n    int remote_port   = profile.remote_port;\n    int local_port    = profile.local_port;\n    int timeout       = profile.timeout;\n    int mtu           = 0;\n    int mptcp         = 0;\n\n    mode      = profile.mode;\n    fast_open = profile.fast_open;\n    verbose   = profile.verbose;\n    mtu       = profile.mtu;\n    mptcp     = profile.mptcp;\n\n    char local_port_str[16];\n    char remote_port_str[16];\n    sprintf(local_port_str, \"%d\", local_port);\n    sprintf(remote_port_str, \"%d\", remote_port);\n\n#ifdef __MINGW32__\n    winsock_init();\n#endif\n\n    USE_LOGFILE(log);\n\n    if (profile.acl != NULL) {\n        LOGI(\"initializing acl...\");\n        acl = !init_acl(profile.acl);\n    }\n\n    if (local_addr == NULL) {\n        local_addr = \"127.0.0.1\";\n    }\n\n#ifndef __MINGW32__\n    // ignore SIGPIPE\n    signal(SIGPIPE, SIG_IGN);\n    signal(SIGABRT, SIG_IGN);\n#endif\n\n    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);\n    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);\n    ev_signal_start(EV_DEFAULT, &sigint_watcher);\n    ev_signal_start(EV_DEFAULT, &sigterm_watcher);\n#ifndef __MINGW32__\n    ev_signal_init(&sigusr1_watcher, signal_cb, SIGUSR1);\n    ev_signal_start(EV_DEFAULT, &sigusr1_watcher);\n#endif\n\n    // Setup keys\n    LOGI(\"initializing ciphers... %s\", method);\n    crypto = crypto_init(password, NULL, method);\n    if (crypto == NULL)\n        FATAL(\"failed to init ciphers\");\n\n    struct sockaddr_storage storage;\n    memset(&storage, 0, sizeof(struct sockaddr_storage));\n    if (get_sockaddr(remote_host, remote_port_str, &storage, 0, ipv6first) == -1) {\n        return -1;\n    }\n\n    // Setup proxy context\n    struct ev_loop *loop = EV_DEFAULT;\n\n    struct sockaddr *remote_addr_tmp[MAX_REMOTE_NUM];\n    listen_ctx_t listen_ctx;\n    listen_ctx.remote_num     = 1;\n    listen_ctx.remote_addr    = remote_addr_tmp;\n    listen_ctx.remote_addr[0] = (struct sockaddr *)(&storage);\n    listen_ctx.timeout        = timeout;\n    listen_ctx.iface          = NULL;\n    listen_ctx.mptcp          = mptcp;\n\n    if (ss_is_ipv6addr(local_addr))\n        LOGI(\"listening at [%s]:%s\", local_addr, local_port_str);\n    else\n        LOGI(\"listening at %s:%s\", local_addr, local_port_str);\n\n    if (mode != UDP_ONLY) {\n        // Setup socket\n        int listenfd;\n        listenfd = create_and_bind(local_addr, local_port_str);\n        if (listenfd == -1) {\n            ERROR(\"bind()\");\n            return -1;\n        }\n        if (listen(listenfd, SOMAXCONN) == -1) {\n            ERROR(\"listen()\");\n            return -1;\n        }\n        setnonblocking(listenfd);\n\n        listen_ctx.fd = listenfd;\n\n        ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);\n        ev_io_start(loop, &listen_ctx.io);\n    }\n\n    // Setup UDP\n    if (mode != TCP_ONLY) {\n        LOGI(\"udprelay enabled\");\n        struct sockaddr *addr = (struct sockaddr *)(&storage);\n        udp_fd = init_udprelay(local_addr, local_port_str, addr,\n                               get_sockaddr_len(addr), mtu, crypto, timeout, NULL);\n    }\n\n    // Init connections\n    cork_dllist_init(&connections);\n\n    if (callback) {\n        callback(listen_ctx.fd, udp_fd, udata);\n    }\n\n    // Enter the loop\n    ev_run(loop, 0);\n\n    if (verbose) {\n        LOGI(\"closed gracefully\");\n    }\n\n    // Clean up\n    if (mode != UDP_ONLY) {\n        ev_io_stop(loop, &listen_ctx.io);\n        free_connections(loop);\n        close(listen_ctx.fd);\n    }\n\n    if (mode != TCP_ONLY) {\n        free_udprelay();\n    }\n\n#ifdef __MINGW32__\n    winsock_cleanup();\n#endif\n\n    return ret_val;\n}\n\nint\nstart_ss_local_server(profile_t profile)\n{\n    return _start_ss_local_server(profile, NULL, NULL);\n}\n\nint\nstart_ss_local_server_with_callback(profile_t profile, ss_local_callback callback, void *udata)\n{\n    return _start_ss_local_server(profile, callback, udata);\n}\n\n#endif\n"
  },
  {
    "path": "src/local.h",
    "content": "/*\n * local.h - Define the client's buffers and callbacks\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _LOCAL_H\n#define _LOCAL_H\n\n#include <libcork/ds.h>\n\n#ifdef HAVE_LIBEV_EV_H\n#include <libev/ev.h>\n#else\n#include <ev.h>\n#endif\n\n#ifdef __MINGW32__\n#include \"winsock.h\"\n#endif\n\n#include \"crypto.h\"\n#include \"jconf.h\"\n\n#include \"common.h\"\n\ntypedef struct listen_ctx {\n    ev_io io;\n    char *iface;\n    int remote_num;\n    int timeout;\n    int fd;\n    int mptcp;\n    struct sockaddr **remote_addr;\n} listen_ctx_t;\n\ntypedef struct server_ctx {\n    ev_io io;\n    int connected;\n    struct server *server;\n} server_ctx_t;\n\ntypedef struct server {\n    int fd;\n    int stage;\n\n    cipher_ctx_t *e_ctx;\n    cipher_ctx_t *d_ctx;\n    struct server_ctx *recv_ctx;\n    struct server_ctx *send_ctx;\n    struct listen_ctx *listener;\n    struct remote *remote;\n\n    buffer_t *buf;\n    buffer_t *abuf;\n\n    ev_timer delayed_connect_watcher;\n\n    struct cork_dllist_item entries;\n} server_t;\n\ntypedef struct remote_ctx {\n    ev_io io;\n    ev_timer watcher;\n\n    int connected;\n    struct remote *remote;\n} remote_ctx_t;\n\ntypedef struct remote {\n    int fd;\n    int direct;\n    int addr_len;\n    uint32_t counter;\n#ifdef TCP_FASTOPEN_WINSOCK\n    OVERLAPPED olap;\n    int connect_ex_done;\n#endif\n\n    buffer_t *buf;\n\n    struct remote_ctx *recv_ctx;\n    struct remote_ctx *send_ctx;\n    struct server *server;\n    struct sockaddr_storage addr;\n} remote_t;\n\n#endif // _LOCAL_H\n"
  },
  {
    "path": "src/manager.c",
    "content": "/*\n * server.c - Provide shadowsocks service\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <fcntl.h>\n#include <locale.h>\n#include <signal.h>\n#include <string.h>\n#include <strings.h>\n#include <time.h>\n#include <unistd.h>\n#include <getopt.h>\n#include <math.h>\n#include <ctype.h>\n#include <limits.h>\n#include <dirent.h>\n\n#include <netdb.h>\n#include <errno.h>\n#include <arpa/inet.h>\n#include <netdb.h>\n#include <netinet/in.h>\n#include <pthread.h>\n#include <sys/un.h>\n#include <sys/socket.h>\n#include <pwd.h>\n#include <libcork/core.h>\n\n#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__)\n#include <net/if.h>\n#include <sys/ioctl.h>\n#define SET_INTERFACE\n#endif\n\n#include \"json.h\"\n#include \"utils.h\"\n#include \"netutils.h\"\n#include \"manager.h\"\n\n#ifndef BUF_SIZE\n#define BUF_SIZE 65535\n#endif\n\nint verbose          = 0;\nchar *executable     = \"ss-server\";\nchar *working_dir    = NULL;\nint working_dir_size = 0;\n\nstatic struct cork_hash_table *server_table;\n\nstatic int\nsetnonblocking(int fd)\n{\n    int flags;\n    if (-1 == (flags = fcntl(fd, F_GETFL, 0))) {\n        flags = 0;\n    }\n    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);\n}\n\nstatic void\ndestroy_server(struct server *server)\n{\n// function used to free memories alloced in **get_server**\n    if (server->method)\n        ss_free(server->method);\n    if (server->plugin)\n        ss_free(server->plugin);\n    if (server->plugin_opts)\n        ss_free(server->plugin_opts);\n    if (server->mode)\n        ss_free(server->mode);\n}\n\nstatic void\nbuild_config(char *prefix, struct manager_ctx *manager, struct server *server)\n{\n    char *path    = NULL;\n    int path_size = strlen(prefix) + strlen(server->port) + 20;\n\n    path = ss_malloc(path_size);\n    snprintf(path, path_size, \"%s/.shadowsocks_%s.conf\", prefix, server->port);\n    FILE *f = fopen(path, \"w+\");\n    if (f == NULL) {\n        if (verbose) {\n            LOGE(\"unable to open config file\");\n        }\n        ss_free(path);\n        return;\n    }\n    fprintf(f, \"{\\n\");\n    fprintf(f, \"\\\"server_port\\\":%d,\\n\", atoi(server->port));\n    fprintf(f, \"\\\"password\\\":\\\"%s\\\"\", server->password);\n    if (server->method)\n        fprintf(f, \",\\n\\\"method\\\":\\\"%s\\\"\", server->method);\n    else if (manager->method)\n        fprintf(f, \",\\n\\\"method\\\":\\\"%s\\\"\", manager->method);\n    if (server->fast_open[0])\n        fprintf(f, \",\\n\\\"fast_open\\\": %s\", server->fast_open);\n    else if (manager->fast_open)\n        fprintf(f, \",\\n\\\"fast_open\\\": true\");\n    if (server->no_delay[0])\n        fprintf(f, \",\\n\\\"no_delay\\\": %s\", server->no_delay);\n    else if (manager->no_delay)\n        fprintf(f, \",\\n\\\"no_delay\\\": true\");\n    if (manager->reuse_port)\n        fprintf(f, \",\\n\\\"reuse_port\\\": true\");\n    if (server->mode)\n        fprintf(f, \",\\n\\\"mode\\\":\\\"%s\\\"\", server->mode);\n    if (server->plugin)\n        fprintf(f, \",\\n\\\"plugin\\\":\\\"%s\\\"\", server->plugin);\n    if (server->plugin_opts)\n        fprintf(f, \",\\n\\\"plugin_opts\\\":\\\"%s\\\"\", server->plugin_opts);\n    fprintf(f, \"\\n}\\n\");\n    fclose(f);\n    ss_free(path);\n}\n\nstatic char *\nconstruct_command_line(struct manager_ctx *manager, struct server *server)\n{\n    static char cmd[BUF_SIZE];\n    int i;\n    int port;\n\n    port = atoi(server->port);\n\n    build_config(working_dir, manager, server);\n\n    memset(cmd, 0, BUF_SIZE);\n    snprintf(cmd, BUF_SIZE,\n             \"%s --manager-address %s -f %s/.shadowsocks_%d.pid -c %s/.shadowsocks_%d.conf\",\n             executable, manager->manager_address, working_dir, port, working_dir, port);\n\n    if (manager->acl != NULL) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" --acl %s\", manager->acl);\n    }\n    if (manager->timeout != NULL) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" -t %s\", manager->timeout);\n    }\n#ifdef HAVE_SETRLIMIT\n    if (manager->nofile) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" -n %d\", manager->nofile);\n    }\n#endif\n    if (manager->user != NULL) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" -a %s\", manager->user);\n    }\n    if (manager->verbose) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" -v\");\n    }\n    if (server->mode == NULL && manager->mode == UDP_ONLY) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" -U\");\n    }\n    if (server->mode == NULL && manager->mode == TCP_AND_UDP) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" -u\");\n    }\n    if (manager->iface) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" -i \\\"%s\\\"\", manager->iface);\n    }\n    if (server->fast_open[0] == 0 && manager->fast_open) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" --fast-open\");\n    }\n    if (server->no_delay[0] == 0 && manager->no_delay) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" --no-delay\");\n    }\n    if (manager->ipv6first) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" -6\");\n    }\n    if (manager->mtu) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" --mtu %d\", manager->mtu);\n    }\n    if (server->plugin == NULL && manager->plugin) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" --plugin \\\"%s\\\"\", manager->plugin);\n    }\n    if (server->plugin_opts == NULL && manager->plugin_opts) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" --plugin-opts \\\"%s\\\"\", manager->plugin_opts);\n    }\n    if (manager->nameservers) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" -d \\\"%s\\\"\", manager->nameservers);\n    }\n    for (i = 0; i < manager->host_num; i++) {\n        int len = strlen(cmd);\n        snprintf(cmd + len, BUF_SIZE - len, \" -s %s\", manager->hosts[i]);\n    }\n\n    if (verbose) {\n        LOGI(\"cmd: %s\", cmd);\n    }\n\n    return cmd;\n}\n\nstatic char *\nget_data(char *buf, int len)\n{\n    char *data;\n    int pos = 0;\n\n    while (pos < len && buf[pos] != '{')\n        pos++;\n    if (pos == len) {\n        return NULL;\n    }\n    data = buf + pos - 1;\n\n    return data;\n}\n\nstatic char *\nget_action(char *buf, int len)\n{\n    char *action;\n    int pos = 0;\n\n    while (pos < len && isspace((unsigned char)buf[pos]))\n        pos++;\n    if (pos == len) {\n        return NULL;\n    }\n    action = buf + pos;\n\n    while (pos < len && (!isspace((unsigned char)buf[pos]) && buf[pos] != ':'))\n        pos++;\n    buf[pos] = '\\0';\n\n    return action;\n}\n\nstatic struct server *\nget_server(char *buf, int len)\n{\n    char *data = get_data(buf, len);\n    char error_buf[512];\n\n    if (data == NULL) {\n        LOGE(\"No data found\");\n        return NULL;\n    }\n\n    json_settings settings = { 0 };\n    json_value *obj        = json_parse_ex(&settings, data, strlen(data), error_buf);\n\n    if (obj == NULL) {\n        LOGE(\"%s\", error_buf);\n        return NULL;\n    }\n\n    struct server *server = ss_malloc(sizeof(struct server));\n    memset(server, 0, sizeof(struct server));\n    if (obj->type == json_object) {\n        int i = 0;\n        for (i = 0; i < obj->u.object.length; i++) {\n            char *name        = obj->u.object.values[i].name;\n            json_value *value = obj->u.object.values[i].value;\n            if (strcmp(name, \"server_port\") == 0) {\n                if (value->type == json_string) {\n                    strncpy(server->port, value->u.string.ptr, 7);\n                } else if (value->type == json_integer) {\n                    snprintf(server->port, 8, \"%\" PRIu64 \"\", value->u.integer);\n                }\n            } else if (strcmp(name, \"password\") == 0) {\n                if (value->type == json_string) {\n                    strncpy(server->password, value->u.string.ptr, 127);\n                }\n            } else if (strcmp(name, \"method\") == 0) {\n                if (value->type == json_string) {\n                    server->method = strdup(value->u.string.ptr);\n                }\n            } else if (strcmp(name, \"fast_open\") == 0) {\n                if (value->type == json_boolean) {\n                    strncpy(server->fast_open, (value->u.boolean ? \"true\" : \"false\"), 8);\n                }\n            } else if (strcmp(name, \"no_delay\") == 0) {\n                if (value->type == json_boolean) {\n                    strncpy(server->no_delay, (value->u.boolean ? \"true\" : \"false\"), 8);\n                }\n            } else if (strcmp(name, \"plugin\") == 0) {\n                if (value->type == json_string) {\n                    server->plugin = strdup(value->u.string.ptr);\n                }\n            } else if (strcmp(name, \"plugin_opts\") == 0) {\n                if (value->type == json_string) {\n                    server->plugin_opts = strdup(value->u.string.ptr);\n                }\n            } else if (strcmp(name, \"mode\") == 0) {\n                if (value->type == json_string) {\n                    server->mode = strdup(value->u.string.ptr);\n                }\n            } else {\n                LOGE(\"invalid data: %s\", data);\n                break;\n            }\n        }\n    }\n\n    json_value_free(obj);\n    return server;\n}\n\nstatic int\nparse_traffic(char *buf, int len, char *port, uint64_t *traffic)\n{\n    char *data = get_data(buf, len);\n    char error_buf[512];\n    json_settings settings = { 0 };\n\n    if (data == NULL) {\n        LOGE(\"No data found\");\n        return -1;\n    }\n\n    json_value *obj = json_parse_ex(&settings, data, strlen(data), error_buf);\n    if (obj == NULL) {\n        LOGE(\"%s\", error_buf);\n        return -1;\n    }\n\n    if (obj->type == json_object) {\n        int i = 0;\n        for (i = 0; i < obj->u.object.length; i++) {\n            char *name        = obj->u.object.values[i].name;\n            json_value *value = obj->u.object.values[i].value;\n            if (value->type == json_integer) {\n                strncpy(port, name, 7);\n                *traffic = value->u.integer;\n            }\n        }\n    }\n\n    json_value_free(obj);\n    return 0;\n}\n\nstatic int\ncreate_and_bind(const char *host, const char *port, int protocol)\n{\n    struct addrinfo hints;\n    struct addrinfo *result, *rp, *ipv4v6bindall;\n    int s, listen_sock = -1;\n\n    memset(&hints, 0, sizeof(struct addrinfo));\n    hints.ai_family   = AF_UNSPEC;                  /* Return IPv4 and IPv6 choices */\n    hints.ai_socktype = protocol == IPPROTO_TCP ?\n                        SOCK_STREAM : SOCK_DGRAM;   /* We want a TCP or UDP socket */\n    hints.ai_flags    = AI_PASSIVE | AI_ADDRCONFIG; /* For wildcard IP address */\n    hints.ai_protocol = protocol;\n\n    s = getaddrinfo(host, port, &hints, &result);\n\n    if (s != 0) {\n        LOGE(\"getaddrinfo: %s\", gai_strerror(s));\n        return -1;\n    }\n\n    rp = result;\n\n    /*\n     * On Linux, with net.ipv6.bindv6only = 0 (the default), getaddrinfo(NULL) with\n     * AI_PASSIVE returns 0.0.0.0 and :: (in this order). AI_PASSIVE was meant to\n     * return a list of addresses to listen on, but it is impossible to listen on\n     * 0.0.0.0 and :: at the same time, if :: implies dualstack mode.\n     */\n    if (!host) {\n        ipv4v6bindall = result;\n\n        /* Loop over all address infos found until a IPV6 address is found. */\n        while (ipv4v6bindall) {\n            if (ipv4v6bindall->ai_family == AF_INET6) {\n                rp = ipv4v6bindall; /* Take first IPV6 address available */\n                break;\n            }\n            ipv4v6bindall = ipv4v6bindall->ai_next; /* Get next address info, if any */\n        }\n    }\n\n    for (/*rp = result*/; rp != NULL; rp = rp->ai_next) {\n        listen_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);\n        if (listen_sock == -1) {\n            continue;\n        }\n\n        if (rp->ai_family == AF_INET6) {\n            int ipv6only = host ? 1 : 0;\n            setsockopt(listen_sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only));\n        }\n\n        int opt = 1;\n        setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));\n#ifdef SO_NOSIGPIPE\n        setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));\n#endif\n\n        s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);\n        if (s == 0) {\n            /* We managed to bind successfully! */\n\n            close(listen_sock);\n\n            break;\n        } else {\n            ERROR(\"bind\");\n        }\n    }\n\n    if (result != NULL) {\n        freeaddrinfo(result);\n    }\n\n    if (rp == NULL) {\n        LOGE(\"Could not bind\");\n        return -1;\n    }\n\n    return listen_sock;\n}\n\nstatic int\ncheck_port(struct manager_ctx *manager, struct server *server)\n{\n    bool both_tcp_udp = manager->mode == TCP_AND_UDP;\n    int fd_count      = manager->host_num * (both_tcp_udp ? 2 : 1);\n    int bind_err      = 0;\n\n    int *sock_fds = (int *)ss_malloc(fd_count * sizeof(int));\n    memset(sock_fds, 0, fd_count * sizeof(int));\n\n    /* try to bind each interface */\n    for (int i = 0; i < manager->host_num; i++) {\n        LOGI(\"try to bind interface: %s, port: %s\", manager->hosts[i], server->port);\n\n        if (manager->mode == UDP_ONLY) {\n            sock_fds[i] = create_and_bind(manager->hosts[i], server->port, IPPROTO_UDP);\n        } else {\n            sock_fds[i] = create_and_bind(manager->hosts[i], server->port, IPPROTO_TCP);\n        }\n\n        if (both_tcp_udp) {\n            sock_fds[i + manager->host_num] = create_and_bind(manager->hosts[i], server->port, IPPROTO_UDP);\n        }\n\n        if (sock_fds[i] == -1 || (both_tcp_udp && sock_fds[i + manager->host_num] == -1)) {\n            bind_err = -1;\n            break;\n        }\n    }\n\n    /* clean socks */\n    for (int i = 0; i < fd_count; i++)\n        if (sock_fds[i] > 0) {\n            close(sock_fds[i]);\n        }\n\n    ss_free(sock_fds);\n\n    return bind_err == -1 ? -1 : 0;\n}\n\nstatic int\nadd_server(struct manager_ctx *manager, struct server *server)\n{\n    int ret = check_port(manager, server);\n\n    if (ret == -1) {\n        LOGE(\"port is not available, please check.\");\n        return -1;\n    }\n\n    bool new = false;\n    cork_hash_table_put(server_table, (void *)server->port, (void *)server, &new, NULL, NULL);\n\n    char *cmd = construct_command_line(manager, server);\n    if (system(cmd) == -1) {\n        ERROR(\"add_server_system\");\n        return -1;\n    }\n\n    return 0;\n}\n\nstatic void\nkill_server(char *prefix, char *pid_file)\n{\n    char *path = NULL;\n    int pid, path_size = strlen(prefix) + strlen(pid_file) + 2;\n    path = ss_malloc(path_size);\n    snprintf(path, path_size, \"%s/%s\", prefix, pid_file);\n    FILE *f = fopen(path, \"r\");\n    if (f == NULL) {\n        if (verbose) {\n            LOGE(\"unable to open pid file\");\n        }\n        ss_free(path);\n        return;\n    }\n    if (fscanf(f, \"%d\", &pid) != EOF) {\n        kill(pid, SIGTERM);\n    }\n    fclose(f);\n    remove(path);\n    ss_free(path);\n}\n\nstatic void\nstop_server(char *prefix, char *port)\n{\n    char *path = NULL;\n    int pid, path_size = strlen(prefix) + strlen(port) + 20;\n    path = ss_malloc(path_size);\n    snprintf(path, path_size, \"%s/.shadowsocks_%s.pid\", prefix, port);\n    FILE *f = fopen(path, \"r\");\n    if (f == NULL) {\n        if (verbose) {\n            LOGE(\"unable to open pid file\");\n        }\n        ss_free(path);\n        return;\n    }\n    if (fscanf(f, \"%d\", &pid) != EOF) {\n        kill(pid, SIGTERM);\n    }\n    fclose(f);\n    ss_free(path);\n}\n\nstatic void\nremove_server(char *prefix, char *port)\n{\n    char *old_port            = NULL;\n    struct server *old_server = NULL;\n\n    cork_hash_table_delete(server_table, (void *)port, (void **)&old_port, (void **)&old_server);\n\n    if (old_server != NULL) {\n        destroy_server(old_server);\n        ss_free(old_server);\n    }\n\n    stop_server(prefix, port);\n}\n\nstatic void\nupdate_stat(char *port, uint64_t traffic)\n{\n    if (verbose) {\n        LOGI(\"update traffic %\" PRIu64 \" for port %s\", traffic, port);\n    }\n    void *ret = cork_hash_table_get(server_table, (void *)port);\n    if (ret != NULL) {\n        struct server *server = (struct server *)ret;\n        server->traffic = traffic;\n    }\n}\n\nstatic void\nmanager_recv_cb(EV_P_ ev_io *w, int revents)\n{\n    struct manager_ctx *manager = (struct manager_ctx *)w;\n    socklen_t len;\n    ssize_t r;\n    struct sockaddr_un claddr;\n    char buf[BUF_SIZE];\n\n    memset(buf, 0, BUF_SIZE);\n\n    len = sizeof(struct sockaddr_un);\n    r   = recvfrom(manager->fd, buf, BUF_SIZE, 0, (struct sockaddr *)&claddr, &len);\n    if (r == -1) {\n        ERROR(\"manager_recvfrom\");\n        return;\n    }\n\n    if (r > BUF_SIZE / 2) {\n        LOGE(\"too large request: %d\", (int)r);\n        return;\n    }\n\n    // properly terminate string which recvfrom does not do\n    buf[r] = '\\0';\n\n    char *action = get_action(buf, r);\n    if (action == NULL) {\n        return;\n    }\n\n    if (strcmp(action, \"add\") == 0) {\n        struct server *server = get_server(buf, r);\n\n        if (server == NULL || server->port[0] == 0 || server->password[0] == 0) {\n            LOGE(\"invalid command: %s:%s\", buf, get_data(buf, r));\n            if (server != NULL) {\n                destroy_server(server);\n                ss_free(server);\n            }\n            goto ERROR_MSG;\n        }\n\n        remove_server(working_dir, server->port);\n        int ret = add_server(manager, server);\n\n        char *msg;\n        int msg_len;\n\n        if (ret == -1) {\n            msg     = \"port is not available\";\n            msg_len = 21;\n        } else {\n            msg     = \"ok\";\n            msg_len = 2;\n        }\n\n        if (sendto(manager->fd, msg, msg_len, 0, (struct sockaddr *)&claddr, len) != 2) {\n            ERROR(\"add_sendto\");\n        }\n    } else if (strcmp(action, \"list\") == 0) {\n        struct cork_hash_table_iterator iter;\n        struct cork_hash_table_entry  *entry;\n        char buf[BUF_SIZE];\n        memset(buf, 0, BUF_SIZE);\n        sprintf(buf, \"[\");\n\n        cork_hash_table_iterator_init(server_table, &iter);\n        while ((entry = cork_hash_table_iterator_next(&iter)) != NULL) {\n            struct server *server = (struct server *)entry->value;\n            char *method          = server->method ? server->method : manager->method;\n            size_t pos            = strlen(buf);\n            size_t entry_len      = strlen(server->port) + strlen(server->password) + strlen(method);\n            if (pos > BUF_SIZE - entry_len - 50) {\n                if (sendto(manager->fd, buf, pos, 0, (struct sockaddr *)&claddr, len)\n                    != pos) {\n                    ERROR(\"list_sendto\");\n                }\n                memset(buf, 0, BUF_SIZE);\n                pos = 0;\n            }\n            sprintf(buf + pos, \"\\n\\t{\\\"server_port\\\":\\\"%s\\\",\\\"password\\\":\\\"%s\\\",\\\"method\\\":\\\"%s\\\"},\",\n                    server->port, server->password, method);\n        }\n\n        size_t pos = strlen(buf);\n        strcpy(buf + max(pos - 1, 1), \"\\n]\"); // Remove trailing \",\"\n        pos = strlen(buf);\n        if (sendto(manager->fd, buf, pos, 0, (struct sockaddr *)&claddr, len)\n            != pos) {\n            ERROR(\"list_sendto\");\n        }\n    } else if (strcmp(action, \"remove\") == 0) {\n        struct server *server = get_server(buf, r);\n\n        if (server == NULL || server->port[0] == 0) {\n            LOGE(\"invalid command: %s:%s\", buf, get_data(buf, r));\n            if (server != NULL) {\n                destroy_server(server);\n                ss_free(server);\n            }\n            goto ERROR_MSG;\n        }\n\n        remove_server(working_dir, server->port);\n        destroy_server(server);\n        ss_free(server);\n\n        char msg[3] = \"ok\";\n        if (sendto(manager->fd, msg, 2, 0, (struct sockaddr *)&claddr, len) != 2) {\n            ERROR(\"remove_sendto\");\n        }\n    } else if (strcmp(action, \"stat\") == 0) {\n        char port[8];\n        uint64_t traffic = 0;\n\n        if (parse_traffic(buf, r, port, &traffic) == -1) {\n            LOGE(\"invalid command: %s:%s\", buf, get_data(buf, r));\n            return;\n        }\n\n        update_stat(port, traffic);\n\n    } else if (strcmp(action, \"ping\") == 0) {\n        struct cork_hash_table_entry *entry;\n        struct cork_hash_table_iterator server_iter;\n\n        char buf[BUF_SIZE];\n\n        memset(buf, 0, BUF_SIZE);\n        sprintf(buf, \"stat: {\");\n\n        cork_hash_table_iterator_init(server_table, &server_iter);\n\n        while ((entry = cork_hash_table_iterator_next(&server_iter)) != NULL) {\n            struct server *server = (struct server *)entry->value;\n            size_t pos            = strlen(buf);\n            if (pos > BUF_SIZE / 2) {\n                buf[pos - 1] = '}';\n                if (sendto(manager->fd, buf, pos, 0, (struct sockaddr *)&claddr, len)\n                    != pos) {\n                    ERROR(\"ping_sendto\");\n                }\n                memset(buf, 0, BUF_SIZE);\n            } else {\n                sprintf(buf + pos, \"\\\"%s\\\":%\" PRIu64 \",\", server->port, server->traffic);\n            }\n        }\n\n        size_t pos = strlen(buf);\n        if (pos > 7) {\n            buf[pos - 1] = '}';\n        } else {\n            buf[pos] = '}';\n            pos++;\n        }\n\n        if (sendto(manager->fd, buf, pos, 0, (struct sockaddr *)&claddr, len)\n            != pos) {\n            ERROR(\"ping_sendto\");\n        }\n    }\n\n    return;\n\nERROR_MSG:\n    strcpy(buf, \"err\");\n    if (sendto(manager->fd, buf, 3, 0, (struct sockaddr *)&claddr, len) != 3) {\n        ERROR(\"error_sendto\");\n    }\n}\n\nstatic void\nsignal_cb(EV_P_ ev_signal *w, int revents)\n{\n    if (revents & EV_SIGNAL) {\n        switch (w->signum) {\n        case SIGINT:\n        case SIGTERM:\n            ev_unloop(EV_A_ EVUNLOOP_ALL);\n        }\n    }\n}\n\nint\ncreate_server_socket(const char *host, const char *port)\n{\n    struct addrinfo hints;\n    struct addrinfo *result, *rp, *ipv4v6bindall;\n    int s, server_sock;\n\n    memset(&hints, 0, sizeof(struct addrinfo));\n    hints.ai_family   = AF_UNSPEC;               /* Return IPv4 and IPv6 choices */\n    hints.ai_socktype = SOCK_DGRAM;              /* We want a UDP socket */\n    hints.ai_flags    = AI_PASSIVE | AI_ADDRCONFIG; /* For wildcard IP address */\n    hints.ai_protocol = IPPROTO_UDP;\n\n    s = getaddrinfo(host, port, &hints, &result);\n    if (s != 0) {\n        LOGE(\"getaddrinfo: %s\", gai_strerror(s));\n        return -1;\n    }\n\n    rp = result;\n\n    /*\n     * On Linux, with net.ipv6.bindv6only = 0 (the default), getaddrinfo(NULL) with\n     * AI_PASSIVE returns 0.0.0.0 and :: (in this order). AI_PASSIVE was meant to\n     * return a list of addresses to listen on, but it is impossible to listen on\n     * 0.0.0.0 and :: at the same time, if :: implies dualstack mode.\n     */\n    if (!host) {\n        ipv4v6bindall = result;\n\n        /* Loop over all address infos found until a IPV6 address is found. */\n        while (ipv4v6bindall) {\n            if (ipv4v6bindall->ai_family == AF_INET6) {\n                rp = ipv4v6bindall; /* Take first IPV6 address available */\n                break;\n            }\n            ipv4v6bindall = ipv4v6bindall->ai_next; /* Get next address info, if any */\n        }\n    }\n\n    for (/*rp = result*/; rp != NULL; rp = rp->ai_next) {\n        server_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);\n        if (server_sock == -1) {\n            continue;\n        }\n\n        if (rp->ai_family == AF_INET6) {\n            int ipv6only = host ? 1 : 0;\n            setsockopt(server_sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only));\n        }\n\n        int opt = 1;\n        setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));\n\n        s = bind(server_sock, rp->ai_addr, rp->ai_addrlen);\n        if (s == 0) {\n            /* We managed to bind successfully! */\n            break;\n        } else {\n            ERROR(\"bind\");\n        }\n\n        close(server_sock);\n    }\n\n    if (result != NULL) {\n        freeaddrinfo(result);\n    }\n\n    if (rp == NULL) {\n        LOGE(\"cannot bind\");\n        return -1;\n    }\n\n    return server_sock;\n}\n\nint\nmain(int argc, char **argv)\n{\n    int i, c;\n    int pid_flags         = 0;\n    char *acl             = NULL;\n    char *user            = NULL;\n    char *password        = NULL;\n    char *timeout         = NULL;\n    char *method          = NULL;\n    char *pid_path        = NULL;\n    char *conf_path       = NULL;\n    char *iface           = NULL;\n    char *manager_address = NULL;\n    char *plugin          = NULL;\n    char *plugin_opts     = NULL;\n    char *workdir         = NULL;\n\n    int fast_open  = 0;\n    int no_delay   = 0;\n    int reuse_port = 0;\n    int mode       = TCP_ONLY;\n    int mtu        = 0;\n    int ipv6first  = 0;\n\n#ifdef HAVE_SETRLIMIT\n    static int nofile = 0;\n#endif\n\n    int server_num = 0;\n    char *server_host[MAX_REMOTE_NUM];\n\n    char *nameservers = NULL;\n\n    jconf_t *conf = NULL;\n\n    static struct option long_options[] = {\n        { \"fast-open\",       no_argument,       NULL, GETOPT_VAL_FAST_OPEN   },\n        { \"no-delay\",        no_argument,       NULL, GETOPT_VAL_NODELAY     },\n        { \"reuse-port\",      no_argument,       NULL, GETOPT_VAL_REUSE_PORT  },\n        { \"acl\",             required_argument, NULL, GETOPT_VAL_ACL         },\n        { \"manager-address\", required_argument, NULL,\n          GETOPT_VAL_MANAGER_ADDRESS },\n        { \"executable\",      required_argument, NULL,\n          GETOPT_VAL_EXECUTABLE },\n        { \"mtu\",             required_argument, NULL, GETOPT_VAL_MTU         },\n        { \"plugin\",          required_argument, NULL, GETOPT_VAL_PLUGIN      },\n        { \"plugin-opts\",     required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },\n        { \"password\",        required_argument, NULL, GETOPT_VAL_PASSWORD    },\n        { \"workdir\",         required_argument, NULL, GETOPT_VAL_WORKDIR     },\n        { \"help\",            no_argument,       NULL, GETOPT_VAL_HELP        },\n        { NULL,              0,                 NULL, 0                      }\n    };\n\n    opterr = 0;\n\n    USE_TTY();\n\n    while ((c = getopt_long(argc, argv, \"f:s:l:k:t:m:c:i:d:a:n:D:6huUvA\",\n                            long_options, NULL)) != -1)\n        switch (c) {\n        case GETOPT_VAL_REUSE_PORT:\n            reuse_port = 1;\n            break;\n        case GETOPT_VAL_FAST_OPEN:\n            fast_open = 1;\n            break;\n        case GETOPT_VAL_NODELAY:\n            no_delay = 1;\n            break;\n        case GETOPT_VAL_ACL:\n            acl = optarg;\n            break;\n        case GETOPT_VAL_MANAGER_ADDRESS:\n            manager_address = optarg;\n            break;\n        case GETOPT_VAL_EXECUTABLE:\n            executable = optarg;\n            break;\n        case GETOPT_VAL_MTU:\n            mtu = atoi(optarg);\n            break;\n        case GETOPT_VAL_PLUGIN:\n            plugin = optarg;\n            break;\n        case GETOPT_VAL_PLUGIN_OPTS:\n            plugin_opts = optarg;\n            break;\n        case 's':\n            if (server_num < MAX_REMOTE_NUM) {\n                server_host[server_num++] = optarg;\n            }\n            break;\n        case GETOPT_VAL_PASSWORD:\n        case 'k':\n            password = optarg;\n            break;\n        case 'f':\n            pid_flags = 1;\n            pid_path  = optarg;\n            break;\n        case 't':\n            timeout = optarg;\n            break;\n        case 'm':\n            method = optarg;\n            break;\n        case 'c':\n            conf_path = optarg;\n            break;\n        case 'i':\n            iface = optarg;\n            break;\n        case 'd':\n            nameservers = optarg;\n            break;\n        case 'a':\n            user = optarg;\n            break;\n        case 'u':\n            mode = TCP_AND_UDP;\n            break;\n        case 'U':\n            mode = UDP_ONLY;\n            break;\n        case '6':\n            ipv6first = 1;\n            break;\n        case GETOPT_VAL_WORKDIR:\n        case 'D':\n            workdir = optarg;\n            break;\n        case 'v':\n            verbose = 1;\n            break;\n        case GETOPT_VAL_HELP:\n        case 'h':\n            usage();\n            exit(EXIT_SUCCESS);\n#ifdef HAVE_SETRLIMIT\n        case 'n':\n            nofile = atoi(optarg);\n            break;\n#endif\n        case 'A':\n            FATAL(\"One time auth has been deprecated. Try AEAD ciphers instead.\");\n            break;\n        case '?':\n            // The option character is not recognized.\n            LOGE(\"Unrecognized option: %s\", optarg);\n            opterr = 1;\n            break;\n        }\n\n    if (opterr) {\n        usage();\n        exit(EXIT_FAILURE);\n    }\n\n    if (conf_path != NULL) {\n        conf = read_jconf(conf_path);\n        if (server_num == 0) {\n            server_num = conf->remote_num;\n            for (i = 0; i < server_num; i++)\n                server_host[i] = conf->remote_addr[i].host;\n        }\n        if (password == NULL) {\n            password = conf->password;\n        }\n        if (method == NULL) {\n            method = conf->method;\n        }\n        if (timeout == NULL) {\n            timeout = conf->timeout;\n        }\n        if (user == NULL) {\n            user = conf->user;\n        }\n        if (fast_open == 0) {\n            fast_open = conf->fast_open;\n        }\n        if (no_delay == 0) {\n            no_delay = conf->no_delay;\n        }\n        if (reuse_port == 0) {\n            reuse_port = conf->reuse_port;\n        }\n        if (nameservers == NULL) {\n            nameservers = conf->nameserver;\n        }\n        if (mode == TCP_ONLY) {\n            mode = conf->mode;\n        }\n        if (mtu == 0) {\n            mtu = conf->mtu;\n        }\n        if (plugin == NULL) {\n            plugin = conf->plugin;\n        }\n        if (plugin_opts == NULL) {\n            plugin_opts = conf->plugin_opts;\n        }\n        if (ipv6first == 0) {\n            ipv6first = conf->ipv6_first;\n        }\n        if (workdir == NULL) {\n            workdir = conf->workdir;\n        }\n        if (acl == NULL) {\n            acl = conf->acl;\n        }\n        if (manager_address == NULL) {\n            manager_address = conf->manager_address;\n        }\n#ifdef HAVE_SETRLIMIT\n        if (nofile == 0) {\n            nofile = conf->nofile;\n        }\n#endif\n    }\n\n    if (server_num == 0) {\n        server_host[server_num++] = \"0.0.0.0\";\n    }\n\n    if (method == NULL) {\n        method = \"table\";\n    }\n\n    if (timeout == NULL) {\n        timeout = \"60\";\n    }\n\n    USE_SYSLOG(argv[0], pid_flags);\n    if (pid_flags) {\n        daemonize(pid_path);\n    }\n\n    if (server_num == 0) {\n        usage();\n        exit(EXIT_FAILURE);\n    }\n\n    if (fast_open == 1) {\n#ifdef TCP_FASTOPEN\n        LOGI(\"using tcp fast open\");\n#else\n        LOGE(\"tcp fast open is not supported by this environment\");\n#endif\n    }\n\n    if (no_delay == 1) {\n        LOGI(\"using tcp no-delay\");\n    }\n\n#ifndef __MINGW32__\n    // setuid\n    if (user != NULL && !run_as(user)) {\n        FATAL(\"failed to switch user\");\n    }\n\n    if (geteuid() == 0) {\n        LOGI(\"running from root user\");\n    }\n#endif\n\n    struct passwd *pw = getpwuid(getuid());\n\n    if (workdir == NULL || strlen(workdir) == 0) {\n        workdir = pw->pw_dir;\n        // If home dir is still not defined or set to nologin/nonexistent, fall back to /tmp\n        if (workdir == NULL || strlen(workdir) == 0 || strstr(workdir, \"nologin\") || strstr(workdir, \"nonexistent\")) {\n            workdir = \"/tmp\";\n        }\n\n        working_dir_size = strlen(workdir) + 15;\n        working_dir      = ss_malloc(working_dir_size);\n        snprintf(working_dir, working_dir_size, \"%s/.shadowsocks\", workdir);\n    } else {\n        working_dir_size = strlen(workdir) + 2;\n        working_dir      = ss_malloc(working_dir_size);\n        snprintf(working_dir, working_dir_size, \"%s\", workdir);\n    }\n    LOGI(\"working directory points to %s\", working_dir);\n\n    int err = mkdir(working_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);\n    if (err != 0 && errno != EEXIST) {\n        ERROR(\"mkdir\");\n        ss_free(working_dir);\n        FATAL(\"unable to create working directory\");\n    }\n\n    if (manager_address == NULL) {\n        size_t manager_address_size = strlen(workdir) + 20;\n        manager_address = ss_malloc(manager_address_size);\n        snprintf(manager_address, manager_address_size, \"%s/.ss-manager.socks\", workdir);\n        LOGI(\"using the default manager address: %s\", manager_address);\n    }\n\n    // ignore SIGPIPE\n    signal(SIGPIPE, SIG_IGN);\n    signal(SIGCHLD, SIG_IGN);\n    signal(SIGABRT, SIG_IGN);\n\n    struct ev_signal sigint_watcher;\n    struct ev_signal sigterm_watcher;\n    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);\n    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);\n    ev_signal_start(EV_DEFAULT, &sigint_watcher);\n    ev_signal_start(EV_DEFAULT, &sigterm_watcher);\n\n    struct manager_ctx manager;\n    memset(&manager, 0, sizeof(struct manager_ctx));\n\n    manager.reuse_port      = reuse_port;\n    manager.fast_open       = fast_open;\n    manager.no_delay        = no_delay;\n    manager.verbose         = verbose;\n    manager.mode            = mode;\n    manager.password        = password;\n    manager.timeout         = timeout;\n    manager.method          = method;\n    manager.iface           = iface;\n    manager.acl             = acl;\n    manager.user            = user;\n    manager.manager_address = manager_address;\n    manager.hosts           = server_host;\n    manager.host_num        = server_num;\n    manager.nameservers     = nameservers;\n    manager.mtu             = mtu;\n    manager.plugin          = plugin;\n    manager.plugin_opts     = plugin_opts;\n    manager.ipv6first       = ipv6first;\n    manager.workdir         = workdir;\n#ifdef HAVE_SETRLIMIT\n    manager.nofile = nofile;\n#endif\n\n    // initialize ev loop\n    struct ev_loop *loop = EV_DEFAULT;\n\n    // Clean up all existed processes\n    DIR *dp;\n    struct dirent *ep;\n    dp = opendir(working_dir);\n    if (dp != NULL) {\n        while ((ep = readdir(dp)) != NULL) {\n            size_t len = strlen(ep->d_name);\n            if (strcmp(ep->d_name + len - 3, \"pid\") == 0) {\n                kill_server(working_dir, ep->d_name);\n                if (verbose)\n                    LOGI(\"kill %s\", ep->d_name);\n            }\n        }\n        closedir(dp);\n    } else {\n        ss_free(working_dir);\n        FATAL(\"Couldn't open the directory\");\n    }\n\n    server_table = cork_string_hash_table_new(MAX_PORT_NUM, 0);\n\n    if (conf != NULL) {\n        for (i = 0; i < conf->port_password_num; i++) {\n            struct server *server = ss_malloc(sizeof(struct server));\n            memset(server, 0, sizeof(struct server));\n            strncpy(server->port, conf->port_password[i].port, 7);\n            strncpy(server->password, conf->port_password[i].password, 127);\n            add_server(&manager, server);\n        }\n    }\n\n    int sfd;\n    ss_addr_t ip_addr = { .host = NULL, .port = NULL };\n    parse_addr(manager_address, &ip_addr);\n\n    if (ip_addr.host == NULL || ip_addr.port == NULL) {\n        struct sockaddr_un svaddr;\n        sfd = socket(AF_UNIX, SOCK_DGRAM, 0);       /*  Create server socket */\n        if (sfd == -1) {\n            ss_free(working_dir);\n            FATAL(\"socket\");\n        }\n\n        setnonblocking(sfd);\n\n        if (remove(manager_address) == -1 && errno != ENOENT) {\n            ERROR(\"bind\");\n            ss_free(working_dir);\n            exit(EXIT_FAILURE);\n        }\n\n        memset(&svaddr, 0, sizeof(struct sockaddr_un));\n        svaddr.sun_family = AF_UNIX;\n        strncpy(svaddr.sun_path, manager_address, sizeof(svaddr.sun_path) - 1);\n\n        if (bind(sfd, (struct sockaddr *)&svaddr, sizeof(struct sockaddr_un)) == -1) {\n            ERROR(\"bind\");\n            ss_free(working_dir);\n            exit(EXIT_FAILURE);\n        }\n    } else {\n        sfd = create_server_socket(ip_addr.host, ip_addr.port);\n        if (sfd == -1) {\n            ss_free(working_dir);\n            FATAL(\"socket\");\n        }\n    }\n\n    manager.fd = sfd;\n    ev_io_init(&manager.io, manager_recv_cb, manager.fd, EV_READ);\n    ev_io_start(loop, &manager.io);\n\n    // start ev loop\n    ev_run(loop, 0);\n\n    if (verbose) {\n        LOGI(\"closed gracefully\");\n    }\n\n    // Clean up\n    struct cork_hash_table_entry *entry;\n    struct cork_hash_table_iterator server_iter;\n\n    cork_hash_table_iterator_init(server_table, &server_iter);\n\n    while ((entry = cork_hash_table_iterator_next(&server_iter)) != NULL) {\n        struct server *server = (struct server *)entry->value;\n        stop_server(working_dir, server->port);\n    }\n\n    ev_signal_stop(EV_DEFAULT, &sigint_watcher);\n    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);\n    ss_free(working_dir);\n    free_addr(&ip_addr);\n\n    return 0;\n}\n"
  },
  {
    "path": "src/manager.h",
    "content": "/*\n * server.h - Define shadowsocks server's buffers and callbacks\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _MANAGER_H\n#define _MANAGER_H\n\n#include <time.h>\n#include <libcork/ds.h>\n\n#ifdef HAVE_LIBEV_EV_H\n#include <libev/ev.h>\n#else\n#include <ev.h>\n#endif\n\n#include \"jconf.h\"\n\n#include \"common.h\"\n\nstruct manager_ctx {\n    ev_io io;\n    int fd;\n    int fast_open;\n    int no_delay;\n    int reuse_port;\n    int verbose;\n    int mode;\n    char *password;\n    char *key;\n    char *timeout;\n    char *method;\n    char *iface;\n    char *acl;\n    char *user;\n    char *plugin;\n    char *plugin_opts;\n    char *manager_address;\n    char **hosts;\n    int host_num;\n    char *nameservers;\n    int mtu;\n    int ipv6first;\n    char *workdir;\n#ifdef HAVE_SETRLIMIT\n    int nofile;\n#endif\n};\n\nstruct server {\n    char port[8];\n    char password[128];\n    char fast_open[8];\n    char no_delay[8];\n    char *mode;\n    char *method;\n    char *plugin;\n    char *plugin_opts;\n    uint64_t traffic;\n};\n\n#endif // _MANAGER_H\n"
  },
  {
    "path": "src/netutils.c",
    "content": "/*\n * netutils.c - Network utilities\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#include <math.h>\n\n#include <libcork/core.h>\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#ifndef __MINGW32__\n#include <arpa/inet.h>\n#include <netdb.h>\n#include <netinet/in.h>\n#include <unistd.h>\n#endif\n\n#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__)\n#include <net/if.h>\n#include <sys/ioctl.h>\n#define SET_INTERFACE\n#endif\n\n#include \"netutils.h\"\n#include \"utils.h\"\n\n#ifndef SO_REUSEPORT\n#define SO_REUSEPORT 15\n#endif\n\nextern int verbose;\n\nstatic const char valid_label_bytes[] =\n    \"-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz\";\n\nint\nset_reuseport(int socket)\n{\n    int opt = 1;\n    return setsockopt(socket, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));\n}\n\nsize_t\nget_sockaddr_len(struct sockaddr *addr)\n{\n    if (addr->sa_family == AF_INET) {\n        return sizeof(struct sockaddr_in);\n    } else if (addr->sa_family == AF_INET6) {\n        return sizeof(struct sockaddr_in6);\n    }\n    return 0;\n}\n\n#ifdef SET_INTERFACE\nint\nsetinterface(int socket_fd, const char *interface_name)\n{\n    struct ifreq interface;\n    memset(&interface, 0, sizeof(struct ifreq));\n    strncpy(interface.ifr_name, interface_name, IFNAMSIZ - 1);\n    int res = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, &interface,\n                         sizeof(struct ifreq));\n    return res;\n}\n\n#endif\n\nint\nparse_local_addr(struct sockaddr_storage *storage_v4,\n                 struct sockaddr_storage *storage_v6,\n                 const char *host)\n{\n    if (host != NULL) {\n        struct cork_ip ip;\n        if (cork_ip_init(&ip, host) != -1) {\n            if (ip.version == 4) {\n                memset(storage_v4, 0, sizeof(struct sockaddr_storage));\n                struct sockaddr_in *addr = (struct sockaddr_in *)storage_v4;\n                inet_pton(AF_INET, host, &addr->sin_addr);\n                addr->sin_family = AF_INET;\n                LOGI(\"binding to outbound IPv4 addr: %s\", host);\n                return AF_INET;\n            } else if (ip.version == 6) {\n                memset(storage_v6, 0, sizeof(struct sockaddr_storage));\n                struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage_v6;\n                inet_pton(AF_INET6, host, &addr->sin6_addr);\n                addr->sin6_family = AF_INET6;\n                LOGI(\"binding to outbound IPv6 addr: %s\", host);\n                return AF_INET6;\n            }\n        }\n    }\n    return 0;\n}\n\nint\nbind_to_addr(struct sockaddr_storage *storage,\n             int socket_fd)\n{\n    if (storage->ss_family == AF_INET) {\n        return bind(socket_fd, (struct sockaddr *)storage, sizeof(struct sockaddr_in));\n    } else if (storage->ss_family == AF_INET6) {\n        return bind(socket_fd, (struct sockaddr *)storage, sizeof(struct sockaddr_in6));\n    }\n    return -1;\n}\n\nssize_t\nget_sockaddr(char *host, char *port,\n             struct sockaddr_storage *storage, int block,\n             int ipv6first)\n{\n    struct cork_ip ip;\n    if (cork_ip_init(&ip, host) != -1) {\n        if (ip.version == 4) {\n            struct sockaddr_in *addr = (struct sockaddr_in *)storage;\n            addr->sin_family = AF_INET;\n            inet_pton(AF_INET, host, &(addr->sin_addr));\n            if (port != NULL) {\n                addr->sin_port = htons(atoi(port));\n            }\n        } else if (ip.version == 6) {\n            struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage;\n            addr->sin6_family = AF_INET6;\n            inet_pton(AF_INET6, host, &(addr->sin6_addr));\n            if (port != NULL) {\n                addr->sin6_port = htons(atoi(port));\n            }\n        }\n        return 0;\n    } else {\n#ifdef __ANDROID__\n        extern int vpn;\n        assert(!vpn);   // protecting DNS packets isn't supported yet\n#endif\n        struct addrinfo hints;\n        struct addrinfo *result, *rp;\n\n        memset(&hints, 0, sizeof(struct addrinfo));\n        hints.ai_family   = AF_UNSPEC;   /* Return IPv4 and IPv6 choices */\n        hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */\n\n        int err = getaddrinfo(host, port, &hints, &result);\n\n        if (err != 0) {\n            LOGE(\"getaddrinfo: %s\", gai_strerror(err));\n            return -1;\n        }\n\n        int prefer_af = ipv6first ? AF_INET6 : AF_INET;\n        for (rp = result; rp != NULL; rp = rp->ai_next)\n            if (rp->ai_family == prefer_af) {\n                if (rp->ai_family == AF_INET)\n                    memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in));\n                else if (rp->ai_family == AF_INET6)\n                    memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in6));\n                break;\n            }\n\n        if (rp == NULL) {\n            for (rp = result; rp != NULL; rp = rp->ai_next) {\n                if (rp->ai_family == AF_INET)\n                    memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in));\n                else if (rp->ai_family == AF_INET6)\n                    memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in6));\n                break;\n            }\n        }\n\n        if (rp == NULL) {\n            LOGE(\"failed to resolve remote addr\");\n            return -1;\n        }\n\n        freeaddrinfo(result);\n        return 0;\n    }\n\n    return -1;\n}\n\nint\nsockaddr_cmp(struct sockaddr_storage *addr1,\n             struct sockaddr_storage *addr2, socklen_t len)\n{\n    struct sockaddr_in *p1_in   = (struct sockaddr_in *)addr1;\n    struct sockaddr_in *p2_in   = (struct sockaddr_in *)addr2;\n    struct sockaddr_in6 *p1_in6 = (struct sockaddr_in6 *)addr1;\n    struct sockaddr_in6 *p2_in6 = (struct sockaddr_in6 *)addr2;\n    if (p1_in->sin_family < p2_in->sin_family)\n        return -1;\n    if (p1_in->sin_family > p2_in->sin_family)\n        return 1;\n    /* compare ip4 */\n    if (p1_in->sin_family == AF_INET) {\n        /* just order it, ntohs not required */\n        if (p1_in->sin_port < p2_in->sin_port)\n            return -1;\n        if (p1_in->sin_port > p2_in->sin_port)\n            return 1;\n        return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);\n    } else if (p1_in6->sin6_family == AF_INET6) {\n        /* just order it, ntohs not required */\n        if (p1_in6->sin6_port < p2_in6->sin6_port)\n            return -1;\n        if (p1_in6->sin6_port > p2_in6->sin6_port)\n            return 1;\n        return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,\n                      INET6_SIZE);\n    } else {\n        /* eek unknown type, perform this comparison for sanity. */\n        return memcmp(addr1, addr2, len);\n    }\n}\n\nint\nsockaddr_cmp_addr(struct sockaddr_storage *addr1,\n                  struct sockaddr_storage *addr2, socklen_t len)\n{\n    struct sockaddr_in *p1_in   = (struct sockaddr_in *)addr1;\n    struct sockaddr_in *p2_in   = (struct sockaddr_in *)addr2;\n    struct sockaddr_in6 *p1_in6 = (struct sockaddr_in6 *)addr1;\n    struct sockaddr_in6 *p2_in6 = (struct sockaddr_in6 *)addr2;\n    if (p1_in->sin_family < p2_in->sin_family)\n        return -1;\n    if (p1_in->sin_family > p2_in->sin_family)\n        return 1;\n    if (verbose) {\n        LOGI(\"sockaddr_cmp_addr: sin_family equal? %d\", p1_in->sin_family == p2_in->sin_family);\n    }\n    /* compare ip4 */\n    if (p1_in->sin_family == AF_INET) {\n        return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);\n    } else if (p1_in6->sin6_family == AF_INET6) {\n        return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,\n                      INET6_SIZE);\n    } else {\n        /* eek unknown type, perform this comparison for sanity. */\n        return memcmp(addr1, addr2, len);\n    }\n}\n\nint\nvalidate_hostname(const char *hostname, const int hostname_len)\n{\n    if (hostname == NULL)\n        return 0;\n\n    if (hostname_len < 1 || hostname_len > 255)\n        return 0;\n\n    if (hostname[0] == '.')\n        return 0;\n\n    const char *label = hostname;\n    while (label < hostname + hostname_len) {\n        size_t label_len = hostname_len - (label - hostname);\n        char *next_dot   = strchr(label, '.');\n        if (next_dot != NULL)\n            label_len = next_dot - label;\n\n        if (label + label_len > hostname + hostname_len)\n            return 0;\n\n        if (label_len > 63 || label_len < 1)\n            return 0;\n\n        if (label[0] == '-' || label[label_len - 1] == '-')\n            return 0;\n\n        if (strspn(label, valid_label_bytes) < label_len)\n            return 0;\n\n        label += label_len + 1;\n    }\n\n    return 1;\n}\n\nint\nis_ipv6only(ss_addr_t *servers, size_t server_num, int ipv6first)\n{\n    int i;\n    for (i = 0; i < server_num; i++) {\n        struct sockaddr_storage storage;\n        memset(&storage, 0, sizeof(struct sockaddr_storage));\n        if (get_sockaddr(servers[i].host, servers[i].port, &storage, 1, ipv6first) == -1) {\n            FATAL(\"failed to resolve the provided hostname\");\n        }\n        if (storage.ss_family != AF_INET6) {\n            return 0;\n        }\n    }\n    return 1;\n}\n"
  },
  {
    "path": "src/netutils.h",
    "content": "/*\n * netutils.h - Network utilities\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _NETUTILS_H\n#define _NETUTILS_H\n\n#ifdef __MINGW32__\n#include \"winsock.h\"\n#else\n#include <sys/socket.h>\n#endif\n\n#if defined(HAVE_LINUX_TCP_H)\n#include <linux/tcp.h>\n#elif defined(HAVE_NETINET_TCP_H)\n#include <netinet/tcp.h>\n#elif defined(HAVE_NETDB_H)\n#include <netdb.h>\n#endif\n\n/* Hard coded defines for TCP fast open on Android */\n#ifdef __ANDROID__\n#ifndef TCP_FASTOPEN\n#define TCP_FASTOPEN   23\n#endif\n#ifndef MSG_FASTOPEN\n#define MSG_FASTOPEN   0x20000000\n#endif\n#ifdef TCP_FASTOPEN_CONNECT\n#undef TCP_FASTOPEN_CONNECT\n#endif\n#endif\n\n#define MAX_HOSTNAME_LEN 256 // FQCN <= 255 characters\n#define MAX_PORT_STR_LEN 6   // PORT < 65536\n\n#define SOCKET_BUF_SIZE (16 * 1024 - 1) // 16383 Byte, equals to the max chunk size\n\ntypedef struct {\n    char *host;\n    char *port;\n} ss_addr_t;\n\n// Be compatible with older libc.\n#ifndef IPPROTO_MPTCP\n#define IPPROTO_MPTCP 262\n#endif\n\n/* MPTCP_ENABLED setsockopt values for out-of-tree kernel 4 & 3, best behaviour\n * to be independent of kernel version is to test from newest to latest values.\n */\n#ifndef MPTCP_ENABLED\nstatic const char mptcp_enabled_values[] = { 42, 26, 0 };\n#else\nstatic const char mptcp_enabled_values[] = { MPTCP_ENABLED, 0 };\n#endif\n\n#ifndef UPDATE_INTERVAL\n#define UPDATE_INTERVAL 5\n#endif\n\n/** byte size of ip4 address */\n#define INET_SIZE 4\n/** byte size of ip6 address */\n#define INET6_SIZE 16\n\nsize_t get_sockaddr_len(struct sockaddr *addr);\nssize_t get_sockaddr(char *host, char *port,\n                     struct sockaddr_storage *storage, int block,\n                     int ipv6first);\nint set_reuseport(int socket);\n\n#ifdef SET_INTERFACE\nint setinterface(int socket_fd, const char *interface_name);\n#endif\n\nint parse_local_addr(struct sockaddr_storage *storage_v4,\n                     struct sockaddr_storage *storage_v6,\n                     const char *host);\n\nint bind_to_addr(struct sockaddr_storage *storage, int socket_fd);\n\n/**\n * Compare two sockaddrs. Imposes an ordering on the addresses.\n * Compares address and port.\n * @param addr1: address 1.\n * @param addr2: address 2.\n * @param len: lengths of addr.\n * @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger.\n */\nint sockaddr_cmp(struct sockaddr_storage *addr1,\n                 struct sockaddr_storage *addr2, socklen_t len);\n\n/**\n * Compare two sockaddrs. Compares address, not the port.\n * @param addr1: address 1.\n * @param addr2: address 2.\n * @param len: lengths of addr.\n * @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger.\n */\nint sockaddr_cmp_addr(struct sockaddr_storage *addr1,\n                      struct sockaddr_storage *addr2, socklen_t len);\n\nint validate_hostname(const char *hostname, const int hostname_len);\n\nint is_ipv6only(ss_addr_t *servers, size_t server_num, int ipv6first);\n\n#endif\n"
  },
  {
    "path": "src/plugin.c",
    "content": "/*\n * plugin.c - Manage plugins\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n#ifndef __MINGW32__\n#include <unistd.h>\n#include <sys/socket.h>\n#include <sys/wait.h>\n#include <netinet/in.h>\n#endif\n\n#include <libcork/core.h>\n#include <libcork/os.h>\n\n#include \"utils.h\"\n#include \"plugin.h\"\n#include \"winsock.h\"\n\n#define CMD_RESRV_LEN 128\n\n#ifndef __MINGW32__\n#define TEMPDIR \"/tmp/\"\n#else\n#define TEMPDIR\n#endif\n\nstatic int exit_code;\nstatic struct cork_env *env        = NULL;\nstatic struct cork_exec *exec      = NULL;\nstatic struct cork_subprocess *sub = NULL;\n#ifdef __MINGW32__\nstatic uint16_t sub_control_port = 0;\nvoid cork_subprocess_set_control(struct cork_subprocess *self, uint16_t port);\n#endif\n\nstatic int\nplugin_log__data(struct cork_stream_consumer *vself,\n                 const void *buf, size_t size, bool is_first)\n{\n    size_t bytes_written = fwrite(buf, 1, size, stderr);\n    /*  If there was an error writing to the file, then signal this\n     *  to the producer */\n    if (bytes_written == size) {\n        return 0;\n    } else {\n        cork_system_error_set();\n        return -1;\n    }\n}\n\nstatic int\nplugin_log__eof(struct cork_stream_consumer *vself)\n{\n    /*  We don't close the file, so there's nothing special to do at\n     *  end-of-stream. */\n    return 0;\n}\n\nstatic void\nplugin_log__free(struct cork_stream_consumer *vself)\n{\n    return;\n}\n\nstruct cork_stream_consumer plugin_log = {\n    .data = plugin_log__data,\n    .eof  = plugin_log__eof,\n    .free = plugin_log__free,\n};\n\nstatic int\nstart_ss_plugin(const char *plugin,\n                const char *plugin_opts,\n                const char *remote_host,\n                const char *remote_port,\n                const char *local_host,\n                const char *local_port,\n                enum plugin_mode mode)\n{\n    cork_env_add(env, \"SS_REMOTE_HOST\", remote_host);\n    cork_env_add(env, \"SS_REMOTE_PORT\", remote_port);\n\n    cork_env_add(env, \"SS_LOCAL_HOST\", local_host);\n    cork_env_add(env, \"SS_LOCAL_PORT\", local_port);\n\n    if (plugin_opts != NULL)\n        cork_env_add(env, \"SS_PLUGIN_OPTIONS\", plugin_opts);\n\n    exec = cork_exec_new(plugin);\n    cork_exec_add_param(exec, plugin);  // argv[0]\n\n#ifdef __ANDROID__\n    extern int vpn;\n    if (vpn)\n        cork_exec_add_param(exec, \"-V\");\n#endif\n\n    cork_exec_set_env(exec, env);\n\n    sub = cork_subprocess_new_exec(exec, NULL, NULL, &exit_code);\n#ifdef __MINGW32__\n    cork_subprocess_set_control(sub, sub_control_port);\n#endif\n\n    return cork_subprocess_start(sub);\n}\n\n#define OBFSPROXY_OPTS_MAX  4096\n/*\n * For obfsproxy, we use standalone mode for now.\n * Managed mode needs to use SOCKS5 proxy as forwarder, which is not supported\n * yet.\n *\n * The idea of using standalone mode is quite simple, just assemble the\n * internal port into obfsproxy parameters.\n *\n * Using manually ran scramblesuit as an example:\n * obfsproxy \\\n * --data-dir /tmp/ss_libev_plugin_with_suffix \\\n * scramblesuit \\\n * --password SOMEMEANINGLESSPASSWORDASEXAMPLE \\\n * --dest some.server.org:12345 \\\n * client \\\n * 127.0.0.1:54321\n *\n * In above case, @plugin = \"obfsproxy\",\n * @plugin_opts = \"scramblesuit --password SOMEMEANINGLESSPASSWORDASEXAMPLE\"\n * For obfs3, it's even easier, just pass @plugin = \"obfsproxy\"\n * @plugin_opts = \"obfs3\"\n *\n * And the rest parameters are all assembled here.\n * Some old obfsproxy will not be supported as it doesn't even support\n * \"--data-dir\" option\n */\nstatic int\nstart_obfsproxy(const char *plugin,\n                const char *plugin_opts,\n                const char *remote_host,\n                const char *remote_port,\n                const char *local_host,\n                const char *local_port,\n                enum plugin_mode mode)\n{\n    char *pch;\n    char *opts_dump = NULL;\n    char *buf = NULL;\n    int ret, buf_size = 0;\n\n    if (plugin_opts != NULL) {\n        opts_dump = strndup(plugin_opts, OBFSPROXY_OPTS_MAX);\n        if (!opts_dump) {\n            ERROR(\"start_obfsproxy strndup failed\");\n            if (env != NULL) {\n                cork_env_free(env);\n            }\n            return -ENOMEM;\n        }\n    }\n    exec = cork_exec_new(plugin);\n\n    /* The first parameter will be skipped, so pass @plugin again */\n    cork_exec_add_param(exec, plugin);\n\n    cork_exec_add_param(exec, \"--data-dir\");\n    buf_size = 20 + strlen(plugin) + strlen(remote_host)\n               + strlen(remote_port) + strlen(local_host) + strlen(local_port);\n    buf = ss_malloc(buf_size);\n    snprintf(buf, buf_size, TEMPDIR \"%s_%s:%s_%s:%s\", plugin,\n             remote_host, remote_port, local_host, local_port);\n    cork_exec_add_param(exec, buf);\n\n    /*\n     * Iterate @plugin_opts by space\n     */\n    if (opts_dump != NULL) {\n        pch = strtok(opts_dump, \" \");\n        while (pch) {\n            cork_exec_add_param(exec, pch);\n            pch = strtok(NULL, \" \");\n        }\n    }\n\n    /* The rest options */\n    if (mode == MODE_CLIENT) {\n        /* Client mode */\n        cork_exec_add_param(exec, \"--dest\");\n        snprintf(buf, buf_size, \"%s:%s\", remote_host, remote_port);\n        cork_exec_add_param(exec, buf);\n        cork_exec_add_param(exec, \"client\");\n        snprintf(buf, buf_size, \"%s:%s\", local_host, local_port);\n        cork_exec_add_param(exec, buf);\n    } else {\n        /* Server mode */\n        cork_exec_add_param(exec, \"--dest\");\n        snprintf(buf, buf_size, \"%s:%s\", local_host, local_port);\n        cork_exec_add_param(exec, buf);\n        cork_exec_add_param(exec, \"server\");\n        snprintf(buf, buf_size, \"%s:%s\", remote_host, remote_port);\n        cork_exec_add_param(exec, buf);\n    }\n\n    cork_exec_set_env(exec, env);\n    sub = cork_subprocess_new_exec(exec, NULL, NULL, &exit_code);\n#ifdef __MINGW32__\n    cork_subprocess_set_control(sub, sub_control_port);\n#endif\n    ret = cork_subprocess_start(sub);\n    ss_free(opts_dump);\n    free(buf);\n    return ret;\n}\n\nint\nstart_plugin(const char *plugin,\n             const char *plugin_opts,\n             const char *remote_host,\n             const char *remote_port,\n             const char *local_host,\n             const char *local_port,\n#ifdef __MINGW32__\n             uint16_t control_port,\n#endif\n             enum plugin_mode mode)\n{\n#ifndef __MINGW32__\n    char *new_path = NULL;\n    const char *current_path;\n    size_t new_path_len;\n#endif\n    int ret;\n\n    if (plugin == NULL)\n        return -1;\n\n    if (strlen(plugin) == 0)\n        return 0;\n\n#ifndef __MINGW32__\n    /*\n     * Add current dir to PATH, so we can search plugin in current dir\n     */\n    env          = cork_env_clone_current();\n    current_path = cork_env_get(env, \"PATH\");\n    if (current_path != NULL) {\n#ifdef HAVE_GET_CURRENT_DIR_NAME\n        char *cwd = get_current_dir_name();\n        if (cwd) {\n#else\n        char cwd[PATH_MAX];\n        if (getcwd(cwd, PATH_MAX) != NULL) {\n#endif\n            new_path_len = strlen(current_path) + strlen(cwd) + 2;\n            new_path     = ss_malloc(new_path_len);\n            snprintf(new_path, new_path_len, \"%s:%s\", cwd, current_path);\n#ifdef HAVE_GET_CURRENT_DIR_NAME\n            free(cwd);\n#endif\n        }\n    }\n    if (new_path != NULL)\n        cork_env_add(env, \"PATH\", new_path);\n#else\n    sub_control_port = control_port;\n#endif\n\n    if (!strncmp(plugin, \"obfsproxy\", strlen(\"obfsproxy\")))\n        ret = start_obfsproxy(plugin, plugin_opts, remote_host, remote_port,\n                              local_host, local_port, mode);\n    else\n        ret = start_ss_plugin(plugin, plugin_opts, remote_host, remote_port,\n                              local_host, local_port, mode);\n#ifndef __MINGW32__\n    ss_free(new_path);\n#endif\n    env = NULL;\n    return ret;\n}\n\nuint16_t\nget_local_port()\n{\n    int sock = socket(AF_INET, SOCK_STREAM, 0);\n    if (sock < 0) {\n        return 0;\n    }\n\n    struct sockaddr_in serv_addr;\n    memset(&serv_addr, 0, sizeof(serv_addr));\n    serv_addr.sin_family      = AF_INET;\n    serv_addr.sin_addr.s_addr = INADDR_ANY;\n    serv_addr.sin_port        = 0;\n    if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {\n        close(sock);\n        return 0;\n    }\n\n    socklen_t len = sizeof(serv_addr);\n    if (getsockname(sock, (struct sockaddr *)&serv_addr, &len) == -1) {\n        close(sock);\n        return 0;\n    }\n    if (close(sock) < 0) {\n        return 0;\n    }\n\n    return ntohs(serv_addr.sin_port);\n}\n\nvoid\nstop_plugin()\n{\n    if (sub != NULL) {\n        cork_subprocess_abort(sub);\n#ifndef __MINGW32__\n        if (cork_subprocess_wait(sub) == -1) {\n            LOGI(\"error on terminating the plugin.\");\n        }\n#endif\n        cork_subprocess_free(sub);\n    }\n}\n\nint\nis_plugin_running()\n{\n    if (sub != NULL) {\n        return cork_subprocess_is_finished(sub);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "src/plugin.h",
    "content": "/*\n * acl.h - Define the ACL interface\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _PLUGIN_H\n#define _PLUGIN_H\n\n#define PLUGIN_EXIT_ERROR  -2\n#define PLUGIN_EXIT_NORMAL -1\n#define PLUGIN_RUNNING      0\n\nenum plugin_mode {\n    MODE_CLIENT,\n    MODE_SERVER\n};\n\n/*\n * XXX: Since we have SS plugins and obfsproxy support, for now we will\n *      do extra check against the plugin name.\n *      For obfsproxy, we will not follow the SS specified protocol and\n *      do special routine for obfsproxy.\n *      This may change when the protocol is finally settled\n *\n * Main function to start a plugin.\n *\n * @plugin: name of the plugin\n *          search from PATH and current directory.\n * @plugin_opts: Special options for plugin\n * @remote_host:\n *   CLIENT mode:\n *     The remote server address, which also runs corresponding plugin\n *   SERVER mode:\n *     The real listen address, which plugin will listen to\n * @remote_port:\n *   CLIENT mode:\n *     The remote server port, which corresponding plugin is listening to\n *   SERVER mode:\n *     The real listen port, which plugin will listen to\n * @local_host:\n *   Where ss-libev will connect/listen to.\n *   Normally localhost for both modes.\n * @local_port:\n *   Where ss-libev will connect/listen to.\n *   Internal user port.\n * @mode:\n *   Indicates which mode the plugin should run at.\n */\nint start_plugin(const char *plugin,\n                 const char *plugin_opts,\n                 const char *remote_host,\n                 const char *remote_port,\n                 const char *local_host,\n                 const char *local_port,\n#ifdef __MINGW32__\n                 uint16_t control_port,\n#endif\n                 enum plugin_mode mode);\nuint16_t get_local_port();\nvoid stop_plugin();\nint is_plugin_running();\n\n#endif // _PLUGIN_H\n"
  },
  {
    "path": "src/ppbloom.c",
    "content": "/*\n * ppbloom.c - Ping-Pong Bloom Filter for nonce reuse detection\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#include <errno.h>\n#include <stdlib.h>\n\n#include \"bloom.h\"\n#include \"ppbloom.h\"\n#include \"utils.h\"\n\n#define PING 0\n#define PONG 1\n\nstatic struct bloom ppbloom[2];\nstatic int bloom_count[2];\nstatic int current;\nstatic int entries;\nstatic double error;\n\nint\nppbloom_init(int n, double e)\n{\n    int err;\n    entries = n / 2;\n    error   = e;\n\n    err = bloom_init(ppbloom + PING, entries, error);\n    if (err)\n        return err;\n\n    err = bloom_init(ppbloom + PONG, entries, error);\n    if (err)\n        return err;\n\n    bloom_count[PING] = 0;\n    bloom_count[PONG] = 0;\n\n    current = PING;\n\n    return 0;\n}\n\nint\nppbloom_check(const void *buffer, int len)\n{\n    int ret;\n\n    ret = bloom_check(ppbloom + PING, buffer, len);\n    if (ret)\n        return ret;\n\n    ret = bloom_check(ppbloom + PONG, buffer, len);\n    if (ret)\n        return ret;\n\n    return 0;\n}\n\nint\nppbloom_add(const void *buffer, int len)\n{\n    int err;\n    err = bloom_add(ppbloom + current, buffer, len);\n    if (err == -1)\n        return err;\n\n    bloom_count[current]++;\n\n    if (bloom_count[current] >= entries) {\n        bloom_count[current] = 0;\n        current              = current == PING ? PONG : PING;\n        bloom_reset(ppbloom + current);\n    }\n\n    return 0;\n}\n\nvoid\nppbloom_free()\n{\n    bloom_free(ppbloom + PING);\n    bloom_free(ppbloom + PONG);\n}\n"
  },
  {
    "path": "src/ppbloom.h",
    "content": "/*\n * ppbloom.h - Define the Ping-Pong Bloom Filter interface\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _PPBLOOM_\n#define _PPBLOOM_\n\nint ppbloom_init(int entries, double error);\nint ppbloom_check(const void *buffer, int len);\nint ppbloom_add(const void *buffer, int len);\nvoid ppbloom_free(void);\n\n#endif\n"
  },
  {
    "path": "src/redir.c",
    "content": "/*\n * redir.c - Provide a transparent TCP proxy through remote shadowsocks\n *           server\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <arpa/inet.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <locale.h>\n#include <netdb.h>\n#include <netinet/in.h>\n#include <pthread.h>\n#include <signal.h>\n#include <string.h>\n#include <strings.h>\n#include <time.h>\n#include <unistd.h>\n#include <getopt.h>\n#include <limits.h>\n#include <linux/if.h>\n#include <linux/netfilter_ipv4.h>\n#include <linux/netfilter_ipv6/ip6_tables.h>\n\n#include <libcork/core.h>\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include \"plugin.h\"\n#include \"netutils.h\"\n#include \"utils.h\"\n#include \"common.h\"\n#include \"redir.h\"\n\n#ifndef EAGAIN\n#define EAGAIN EWOULDBLOCK\n#endif\n\n#ifndef EWOULDBLOCK\n#define EWOULDBLOCK EAGAIN\n#endif\n\n#ifndef IP6T_SO_ORIGINAL_DST\n#define IP6T_SO_ORIGINAL_DST 80\n#endif\n\n#ifndef IP_TRANSPARENT\n#define IP_TRANSPARENT       19\n#endif\n\n#ifndef IPV6_TRANSPARENT\n#define IPV6_TRANSPARENT     75\n#endif\n\nstatic void accept_cb(EV_P_ ev_io *w, int revents);\nstatic void server_recv_cb(EV_P_ ev_io *w, int revents);\nstatic void server_send_cb(EV_P_ ev_io *w, int revents);\nstatic void remote_recv_cb(EV_P_ ev_io *w, int revents);\nstatic void remote_send_cb(EV_P_ ev_io *w, int revents);\n\nstatic remote_t *new_remote(int fd, int timeout);\nstatic server_t *new_server(int fd);\n\nstatic void free_remote(remote_t *remote);\nstatic void close_and_free_remote(EV_P_ remote_t *remote);\nstatic void free_server(server_t *server);\nstatic void close_and_free_server(EV_P_ server_t *server);\n\nint verbose    = 0;\nint reuse_port = 0;\nint tcp_incoming_sndbuf = 0;\nint tcp_incoming_rcvbuf = 0;\nint tcp_outgoing_sndbuf = 0;\nint tcp_outgoing_rcvbuf = 0;\n\nstatic crypto_t *crypto;\n\nstatic int ipv6first = 0;\nstatic int mode      = TCP_ONLY;\n#ifdef HAVE_SETRLIMIT\nstatic int nofile = 0;\n#endif\nint fast_open       = 0;\nstatic int no_delay = 0;\nstatic int ret_val  = 0;\n\nstatic struct ev_signal sigint_watcher;\nstatic struct ev_signal sigterm_watcher;\nstatic struct ev_signal sigchld_watcher;\n\nstatic int tcp_tproxy = 0; /* use tproxy instead of redirect (for tcp) */\n\nstatic int\ngetdestaddr(int fd, struct sockaddr_storage *destaddr)\n{\n    socklen_t socklen = sizeof(*destaddr);\n    int error         = 0;\n\n    if (tcp_tproxy) {\n        error = getsockname(fd, (void *)destaddr, &socklen);\n    } else {\n        error = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, destaddr, &socklen);\n        if (error) { // Didn't find a proper way to detect IP version.\n            error = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, destaddr, &socklen);\n        }\n    }\n\n    if (error) {\n        return -1;\n    }\n    return 0;\n}\n\nint\nsetnonblocking(int fd)\n{\n    int flags;\n    if (-1 == (flags = fcntl(fd, F_GETFL, 0))) {\n        flags = 0;\n    }\n    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);\n}\n\nint\ncreate_and_bind(const char *addr, const char *port)\n{\n    struct addrinfo hints;\n    struct addrinfo *result, *rp;\n    int s, listen_sock = -1;\n\n    memset(&hints, 0, sizeof(struct addrinfo));\n    hints.ai_family   = AF_UNSPEC;   /* Return IPv4 and IPv6 choices */\n    hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */\n\n    result = NULL;\n\n    s = getaddrinfo(addr, port, &hints, &result);\n    if (s != 0) {\n        LOGI(\"getaddrinfo: %s\", gai_strerror(s));\n        return -1;\n    }\n\n    if (result == NULL) {\n        LOGE(\"Could not bind\");\n        return -1;\n    }\n\n    for (rp = result; rp != NULL; rp = rp->ai_next) {\n        listen_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);\n        if (listen_sock == -1) {\n            continue;\n        }\n\n        int opt = 1;\n        setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));\n#ifdef SO_NOSIGPIPE\n        setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));\n#endif\n        if (reuse_port) {\n            int err = set_reuseport(listen_sock);\n            if (err == 0) {\n                LOGI(\"tcp port reuse enabled\");\n            }\n        }\n\n        if (tcp_tproxy) {\n            int level = 0, optname = 0;\n            if (rp->ai_family == AF_INET) {\n                level = IPPROTO_IP;\n                optname = IP_TRANSPARENT;\n            } else {\n                level = IPPROTO_IPV6;\n                optname = IPV6_TRANSPARENT;\n            }\n\n            if (setsockopt(listen_sock, level, optname, &opt, sizeof(opt)) != 0) {\n                ERROR(\"setsockopt IP_TRANSPARENT\");\n                exit(EXIT_FAILURE);\n            }\n            LOGI(\"tcp tproxy mode enabled\");\n        }\n\n        s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);\n        if (s == 0) {\n            /* We managed to bind successfully! */\n            break;\n        } else {\n            ERROR(\"bind\");\n        }\n\n        close(listen_sock);\n        listen_sock = -1;\n    }\n\n    freeaddrinfo(result);\n\n    return listen_sock;\n}\n\nstatic void\nserver_recv_cb(EV_P_ ev_io *w, int revents)\n{\n    server_ctx_t *server_recv_ctx = (server_ctx_t *)w;\n    server_t *server              = server_recv_ctx->server;\n    remote_t *remote              = server->remote;\n\n    ev_timer_stop(EV_A_ & server->delayed_connect_watcher);\n\n    ssize_t r = recv(server->fd, remote->buf->data + remote->buf->len,\n                     SOCKET_BUF_SIZE - remote->buf->len, 0);\n\n    if (r == 0) {\n        // connection closed\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else if (r == -1) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) {\n            // no data\n            // continue to wait for recv\n            return;\n        } else {\n            ERROR(\"server recv\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    }\n\n    remote->buf->len += r;\n\n    if (verbose) {\n        uint16_t port = 0;\n        char ipstr[INET6_ADDRSTRLEN];\n        memset(&ipstr, 0, INET6_ADDRSTRLEN);\n\n        if (AF_INET == server->destaddr.ss_family) {\n            struct sockaddr_in *sa = (struct sockaddr_in *)&(server->destaddr);\n            inet_ntop(AF_INET, &(sa->sin_addr), ipstr, INET_ADDRSTRLEN);\n            port = ntohs(sa->sin_port);\n        } else {\n            struct sockaddr_in6 *sa = (struct sockaddr_in6 *)&(server->destaddr);\n            inet_ntop(AF_INET6, &(sa->sin6_addr), ipstr, INET6_ADDRSTRLEN);\n            port = ntohs(sa->sin6_port);\n        }\n\n        LOGI(\"redir to %s:%d, len=%zu, recv=%zd\", ipstr, port, remote->buf->len, r);\n    }\n\n    if (!remote->send_ctx->connected) {\n        ev_io_stop(EV_A_ & server_recv_ctx->io);\n        ev_io_start(EV_A_ & remote->send_ctx->io);\n        return;\n    }\n\n    int err = crypto->encrypt(remote->buf, server->e_ctx, SOCKET_BUF_SIZE);\n\n    if (err) {\n        LOGE(\"invalid password or cipher\");\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    }\n\n    int s = send(remote->fd, remote->buf->data, remote->buf->len, 0);\n\n    if (s == -1) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) {\n            // no data, wait for send\n            remote->buf->idx = 0;\n            ev_io_stop(EV_A_ & server_recv_ctx->io);\n            ev_io_start(EV_A_ & remote->send_ctx->io);\n            return;\n        } else {\n            ERROR(\"send\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    } else if (s < remote->buf->len) {\n        remote->buf->len -= s;\n        remote->buf->idx  = s;\n        ev_io_stop(EV_A_ & server_recv_ctx->io);\n        ev_io_start(EV_A_ & remote->send_ctx->io);\n        return;\n    } else {\n        remote->buf->idx = 0;\n        remote->buf->len = 0;\n    }\n}\n\nstatic void\nserver_send_cb(EV_P_ ev_io *w, int revents)\n{\n    server_ctx_t *server_send_ctx = (server_ctx_t *)w;\n    server_t *server              = server_send_ctx->server;\n    remote_t *remote              = server->remote;\n    if (server->buf->len == 0) {\n        // close and free\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else {\n        // has data to send\n        ssize_t s = send(server->fd, server->buf->data + server->buf->idx,\n                         server->buf->len, 0);\n        if (s == -1) {\n            if (errno != EAGAIN && errno != EWOULDBLOCK) {\n                ERROR(\"send\");\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n            }\n            return;\n        } else if (s < server->buf->len) {\n            // partly sent, move memory, wait for the next time to send\n            server->buf->len -= s;\n            server->buf->idx += s;\n            return;\n        } else {\n            // all sent out, wait for reading\n            server->buf->len = 0;\n            server->buf->idx = 0;\n            ev_io_stop(EV_A_ & server_send_ctx->io);\n            ev_io_start(EV_A_ & remote->recv_ctx->io);\n        }\n    }\n}\n\nstatic void\ndelayed_connect_cb(EV_P_ ev_timer *watcher, int revents)\n{\n    server_t *server = cork_container_of(watcher, server_t,\n                                         delayed_connect_watcher);\n    remote_t *remote = server->remote;\n\n    int r = connect(remote->fd, remote->addr,\n                    get_sockaddr_len(remote->addr));\n\n    remote->addr = NULL;\n\n    if (r == -1 && errno != CONNECT_IN_PROGRESS) {\n        ERROR(\"connect\");\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else {\n        // listen to remote connected event\n        ev_io_start(EV_A_ & remote->send_ctx->io);\n        ev_timer_start(EV_A_ & remote->send_ctx->watcher);\n    }\n}\n\nstatic void\nremote_timeout_cb(EV_P_ ev_timer *watcher, int revents)\n{\n    remote_ctx_t *remote_ctx\n        = cork_container_of(watcher, remote_ctx_t, watcher);\n\n    remote_t *remote = remote_ctx->remote;\n    server_t *server = remote->server;\n\n    ev_timer_stop(EV_A_ watcher);\n\n    close_and_free_remote(EV_A_ remote);\n    close_and_free_server(EV_A_ server);\n}\n\nstatic void\nremote_recv_cb(EV_P_ ev_io *w, int revents)\n{\n    remote_ctx_t *remote_recv_ctx = (remote_ctx_t *)w;\n    remote_t *remote              = remote_recv_ctx->remote;\n    server_t *server              = remote->server;\n\n    ssize_t r = recv(remote->fd, server->buf->data, SOCKET_BUF_SIZE, 0);\n\n    if (r == 0) {\n        // connection closed\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else if (r == -1) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) {\n            // no data\n            // continue to wait for recv\n            return;\n        } else {\n            ERROR(\"remote recv\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    }\n\n    server->buf->len = r;\n\n    int err = crypto->decrypt(server->buf, server->d_ctx, SOCKET_BUF_SIZE);\n    if (err == CRYPTO_ERROR) {\n        LOGE(\"invalid password or cipher\");\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else if (err == CRYPTO_NEED_MORE) {\n        return; // Wait for more\n    }\n\n    int s = send(server->fd, server->buf->data, server->buf->len, 0);\n\n    if (s == -1) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) {\n            // no data, wait for send\n            server->buf->idx = 0;\n            ev_io_stop(EV_A_ & remote_recv_ctx->io);\n            ev_io_start(EV_A_ & server->send_ctx->io);\n        } else {\n            ERROR(\"send\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    } else if (s < server->buf->len) {\n        server->buf->len -= s;\n        server->buf->idx  = s;\n        ev_io_stop(EV_A_ & remote_recv_ctx->io);\n        ev_io_start(EV_A_ & server->send_ctx->io);\n    }\n\n    // Disable TCP_NODELAY after the first response are sent\n    if (!remote->recv_ctx->connected && !no_delay) {\n        int opt = 0;\n        setsockopt(server->fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n        setsockopt(remote->fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n    }\n    remote->recv_ctx->connected = 1;\n}\n\nstatic void\nremote_send_cb(EV_P_ ev_io *w, int revents)\n{\n    remote_ctx_t *remote_send_ctx = (remote_ctx_t *)w;\n    remote_t *remote              = remote_send_ctx->remote;\n    server_t *server              = remote->server;\n\n    ev_timer_stop(EV_A_ & remote_send_ctx->watcher);\n\n    if (!remote_send_ctx->connected) {\n        int r = 0;\n        if (remote->addr == NULL) {\n            struct sockaddr_storage addr;\n            memset(&addr, 0, sizeof(struct sockaddr_storage));\n            socklen_t len = sizeof addr;\n            r = getpeername(remote->fd, (struct sockaddr *)&addr, &len);\n        }\n        if (r == 0) {\n            remote_send_ctx->connected = 1;\n\n            ev_io_stop(EV_A_ & remote_send_ctx->io);\n            ev_io_stop(EV_A_ & server->recv_ctx->io);\n            ev_io_start(EV_A_ & remote->recv_ctx->io);\n\n            // send destaddr\n            buffer_t ss_addr_to_send;\n            buffer_t *abuf = &ss_addr_to_send;\n            balloc(abuf, SOCKET_BUF_SIZE);\n\n            if (AF_INET6 == server->destaddr.ss_family) { // IPv6\n                abuf->data[abuf->len++] = 4;          // Type 4 is IPv6 address\n\n                size_t in6_addr_len = sizeof(struct in6_addr);\n                memcpy(abuf->data + abuf->len,\n                       &(((struct sockaddr_in6 *)&(server->destaddr))->sin6_addr),\n                       in6_addr_len);\n                abuf->len += in6_addr_len;\n                memcpy(abuf->data + abuf->len,\n                       &(((struct sockaddr_in6 *)&(server->destaddr))->sin6_port),\n                       2);\n            } else {                             // IPv4\n                abuf->data[abuf->len++] = 1; // Type 1 is IPv4 address\n\n                size_t in_addr_len = sizeof(struct in_addr);\n                memcpy(abuf->data + abuf->len,\n                       &((struct sockaddr_in *)&(server->destaddr))->sin_addr, in_addr_len);\n                abuf->len += in_addr_len;\n                memcpy(abuf->data + abuf->len,\n                       &((struct sockaddr_in *)&(server->destaddr))->sin_port, 2);\n            }\n\n            abuf->len += 2;\n\n            int err = crypto->encrypt(abuf, server->e_ctx, SOCKET_BUF_SIZE);\n            if (err) {\n                LOGE(\"invalid password or cipher\");\n                bfree(abuf);\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n                return;\n            }\n\n            err = crypto->encrypt(remote->buf, server->e_ctx, SOCKET_BUF_SIZE);\n            if (err) {\n                LOGE(\"invalid password or cipher\");\n                bfree(abuf);\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n                return;\n            }\n\n            bprepend(remote->buf, abuf, SOCKET_BUF_SIZE);\n            bfree(abuf);\n        } else {\n            ERROR(\"getpeername\");\n            // not connected\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    }\n\n    if (remote->buf->len == 0) {\n        // close and free\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else {\n        // has data to send\n        int s = -1;\n\n        if (remote->addr != NULL) {\n#if defined(TCP_FASTOPEN_CONNECT)\n            int optval = 1;\n            if (setsockopt(remote->fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,\n                           (void *)&optval, sizeof(optval)) < 0)\n                FATAL(\"failed to set TCP_FASTOPEN_CONNECT\");\n            s = connect(remote->fd, remote->addr, get_sockaddr_len(remote->addr));\n            if (s == 0)\n                s = send(remote->fd, remote->buf->data, remote->buf->len, 0);\n#elif defined(MSG_FASTOPEN)\n            s = sendto(remote->fd, remote->buf->data + remote->buf->idx,\n                       remote->buf->len, MSG_FASTOPEN, remote->addr,\n                       get_sockaddr_len(remote->addr));\n#else\n            FATAL(\"tcp fast open is not supported on this platform\");\n#endif\n\n            remote->addr = NULL;\n\n            if (s == -1) {\n                if (errno == CONNECT_IN_PROGRESS) {\n                    ev_io_start(EV_A_ & remote_send_ctx->io);\n                    ev_timer_start(EV_A_ & remote_send_ctx->watcher);\n                } else {\n                    if (errno == EOPNOTSUPP || errno == EPROTONOSUPPORT ||\n                        errno == ENOPROTOOPT) {\n                        fast_open = 0;\n                        LOGE(\"fast open is not supported on this platform\");\n                    } else {\n                        ERROR(\"fast_open_connect\");\n                    }\n                    close_and_free_remote(EV_A_ remote);\n                    close_and_free_server(EV_A_ server);\n                }\n                return;\n            }\n        } else {\n            s = send(remote->fd, remote->buf->data + remote->buf->idx,\n                     remote->buf->len, 0);\n        }\n\n        if (s == -1) {\n            if (errno != EAGAIN && errno != EWOULDBLOCK) {\n                ERROR(\"send\");\n                // close and free\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n            }\n            return;\n        } else if (s < remote->buf->len) {\n            // partly sent, move memory, wait for the next time to send\n            remote->buf->len -= s;\n            remote->buf->idx += s;\n            ev_io_start(EV_A_ & remote_send_ctx->io);\n            return;\n        } else {\n            // all sent out, wait for reading\n            remote->buf->len = 0;\n            remote->buf->idx = 0;\n            ev_io_stop(EV_A_ & remote_send_ctx->io);\n            ev_io_start(EV_A_ & server->recv_ctx->io);\n        }\n    }\n}\n\nstatic remote_t *\nnew_remote(int fd, int timeout)\n{\n    remote_t *remote = ss_malloc(sizeof(remote_t));\n    memset(remote, 0, sizeof(remote_t));\n\n    remote->recv_ctx = ss_malloc(sizeof(remote_ctx_t));\n    remote->send_ctx = ss_malloc(sizeof(remote_ctx_t));\n    remote->buf      = ss_malloc(sizeof(buffer_t));\n    balloc(remote->buf, SOCKET_BUF_SIZE);\n    memset(remote->recv_ctx, 0, sizeof(remote_ctx_t));\n    memset(remote->send_ctx, 0, sizeof(remote_ctx_t));\n    remote->fd                  = fd;\n    remote->recv_ctx->remote    = remote;\n    remote->recv_ctx->connected = 0;\n    remote->send_ctx->remote    = remote;\n    remote->send_ctx->connected = 0;\n\n    ev_io_init(&remote->recv_ctx->io, remote_recv_cb, fd, EV_READ);\n    ev_io_init(&remote->send_ctx->io, remote_send_cb, fd, EV_WRITE);\n    ev_timer_init(&remote->send_ctx->watcher, remote_timeout_cb,\n                  min(MAX_CONNECT_TIMEOUT, timeout), 0);\n\n    return remote;\n}\n\nstatic void\nfree_remote(remote_t *remote)\n{\n    if (remote->server != NULL) {\n        remote->server->remote = NULL;\n    }\n    if (remote->buf != NULL) {\n        bfree(remote->buf);\n        ss_free(remote->buf);\n    }\n    ss_free(remote->recv_ctx);\n    ss_free(remote->send_ctx);\n    ss_free(remote);\n}\n\nstatic void\nclose_and_free_remote(EV_P_ remote_t *remote)\n{\n    if (remote != NULL) {\n        ev_timer_stop(EV_A_ & remote->send_ctx->watcher);\n        ev_io_stop(EV_A_ & remote->send_ctx->io);\n        ev_io_stop(EV_A_ & remote->recv_ctx->io);\n        close(remote->fd);\n        free_remote(remote);\n    }\n}\n\nstatic server_t *\nnew_server(int fd)\n{\n    server_t *server = ss_malloc(sizeof(server_t));\n    memset(server, 0, sizeof(server_t));\n\n    server->recv_ctx = ss_malloc(sizeof(server_ctx_t));\n    server->send_ctx = ss_malloc(sizeof(server_ctx_t));\n    server->buf      = ss_malloc(sizeof(buffer_t));\n    balloc(server->buf, SOCKET_BUF_SIZE);\n    memset(server->recv_ctx, 0, sizeof(server_ctx_t));\n    memset(server->send_ctx, 0, sizeof(server_ctx_t));\n    server->fd                  = fd;\n    server->recv_ctx->server    = server;\n    server->recv_ctx->connected = 0;\n    server->send_ctx->server    = server;\n    server->send_ctx->connected = 0;\n\n    server->e_ctx = ss_malloc(sizeof(cipher_ctx_t));\n    server->d_ctx = ss_malloc(sizeof(cipher_ctx_t));\n    crypto->ctx_init(crypto->cipher, server->e_ctx, 1);\n    crypto->ctx_init(crypto->cipher, server->d_ctx, 0);\n\n    ev_io_init(&server->recv_ctx->io, server_recv_cb, fd, EV_READ);\n    ev_io_init(&server->send_ctx->io, server_send_cb, fd, EV_WRITE);\n\n    ev_timer_init(&server->delayed_connect_watcher, delayed_connect_cb, 0.05,\n                  0);\n\n    return server;\n}\n\nstatic void\nfree_server(server_t *server)\n{\n    if (server->remote != NULL) {\n        server->remote->server = NULL;\n    }\n    if (server->e_ctx != NULL) {\n        crypto->ctx_release(server->e_ctx);\n        ss_free(server->e_ctx);\n    }\n    if (server->d_ctx != NULL) {\n        crypto->ctx_release(server->d_ctx);\n        ss_free(server->d_ctx);\n    }\n    if (server->buf != NULL) {\n        bfree(server->buf);\n        ss_free(server->buf);\n    }\n    ss_free(server->recv_ctx);\n    ss_free(server->send_ctx);\n    ss_free(server);\n}\n\nstatic void\nclose_and_free_server(EV_P_ server_t *server)\n{\n    if (server != NULL) {\n        ev_io_stop(EV_A_ & server->send_ctx->io);\n        ev_io_stop(EV_A_ & server->recv_ctx->io);\n        ev_timer_stop(EV_A_ & server->delayed_connect_watcher);\n        close(server->fd);\n        free_server(server);\n    }\n}\n\nstatic void\naccept_cb(EV_P_ ev_io *w, int revents)\n{\n    listen_ctx_t *listener = (listen_ctx_t *)w;\n    struct sockaddr_storage destaddr;\n    memset(&destaddr, 0, sizeof(struct sockaddr_storage));\n\n    int err;\n\n    int serverfd = accept(listener->fd, NULL, NULL);\n    if (serverfd == -1) {\n        ERROR(\"accept\");\n        return;\n    }\n\n    err = getdestaddr(serverfd, &destaddr);\n    if (err) {\n        ERROR(\"getdestaddr\");\n        return;\n    }\n\n    setnonblocking(serverfd);\n    int opt = 1;\n    setsockopt(serverfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n#ifdef SO_NOSIGPIPE\n    setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));\n#endif\n\n    if (tcp_incoming_sndbuf > 0) {\n        setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &tcp_incoming_sndbuf, sizeof(int));\n    }\n\n    if (tcp_incoming_rcvbuf > 0) {\n        setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &tcp_incoming_rcvbuf, sizeof(int));\n    }\n\n    int index                    = rand() % listener->remote_num;\n    struct sockaddr *remote_addr = listener->remote_addr[index];\n\n    int protocol = IPPROTO_TCP;\n    if (listener->mptcp < 0) {\n        protocol = IPPROTO_MPTCP; // Enable upstream MPTCP\n    }\n    int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, protocol);\n    if (remotefd == -1) {\n        ERROR(\"socket\");\n        return;\n    }\n\n    // Set flags\n    setsockopt(remotefd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n#ifdef SO_NOSIGPIPE\n    setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));\n#endif\n\n    // Enable TCP keepalive feature\n    int keepAlive    = 1;\n    int keepIdle     = 40;\n    int keepInterval = 20;\n    int keepCount    = 5;\n    setsockopt(remotefd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));\n    setsockopt(remotefd, SOL_TCP, TCP_KEEPIDLE, (void *)&keepIdle, sizeof(keepIdle));\n    setsockopt(remotefd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));\n    setsockopt(remotefd, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));\n\n    // Set non blocking\n    setnonblocking(remotefd);\n\n    if (listener->tos >= 0) {\n        int rc = setsockopt(remotefd, IPPROTO_IP, IP_TOS, &listener->tos, sizeof(listener->tos));\n        if (rc < 0 && errno != ENOPROTOOPT) {\n            LOGE(\"setting ipv4 dscp failed: %d\", errno);\n        }\n#ifdef IPV6_TCLASS\n        rc = setsockopt(remotefd, IPPROTO_IPV6, IPV6_TCLASS, &listener->tos, sizeof(listener->tos));\n        if (rc < 0 && errno != ENOPROTOOPT) {\n            LOGE(\"setting ipv6 dscp failed: %d\", errno);\n        }\n#endif\n    }\n\n    // Enable out-of-tree MPTCP\n    if (listener->mptcp > 1) {\n        int err = setsockopt(remotefd, SOL_TCP, listener->mptcp, &opt, sizeof(opt));\n        if (err == -1) {\n            ERROR(\"failed to enable out-of-tree multipath TCP\");\n        }\n    } else if (listener->mptcp == 1) {\n        int i = 0;\n        while ((listener->mptcp = mptcp_enabled_values[i]) > 0) {\n            int err = setsockopt(remotefd, SOL_TCP, listener->mptcp, &opt, sizeof(opt));\n            if (err != -1) {\n                break;\n            }\n            i++;\n        }\n        if (listener->mptcp == 0) {\n            ERROR(\"failed to enable out-of-tree multipath TCP\");\n        }\n    }\n\n    if (tcp_outgoing_sndbuf > 0) {\n        setsockopt(remotefd, SOL_SOCKET, SO_SNDBUF, &tcp_outgoing_sndbuf, sizeof(int));\n    }\n\n    if (tcp_outgoing_rcvbuf > 0) {\n        setsockopt(remotefd, SOL_SOCKET, SO_RCVBUF, &tcp_outgoing_rcvbuf, sizeof(int));\n    }\n\n    server_t *server = new_server(serverfd);\n    remote_t *remote = new_remote(remotefd, listener->timeout);\n    server->remote   = remote;\n    remote->server   = server;\n    server->destaddr = destaddr;\n\n    if (fast_open) {\n        // save remote addr for fast open\n        remote->addr = remote_addr;\n        ev_timer_start(EV_A_ & server->delayed_connect_watcher);\n    } else {\n        int r = connect(remotefd, remote_addr, get_sockaddr_len(remote_addr));\n\n        if (r == -1 && errno != CONNECT_IN_PROGRESS) {\n            ERROR(\"connect\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n        // listen to remote connected event\n        ev_io_start(EV_A_ & remote->send_ctx->io);\n        ev_timer_start(EV_A_ & remote->send_ctx->watcher);\n    }\n    ev_io_start(EV_A_ & server->recv_ctx->io);\n}\n\nstatic void\nsignal_cb(EV_P_ ev_signal *w, int revents)\n{\n    if (revents & EV_SIGNAL) {\n        switch (w->signum) {\n        case SIGCHLD:\n            if (!is_plugin_running()) {\n                LOGE(\"plugin service exit unexpectedly\");\n                ret_val = -1;\n            } else\n                return;\n        case SIGINT:\n        case SIGTERM:\n            ev_signal_stop(EV_DEFAULT, &sigint_watcher);\n            ev_signal_stop(EV_DEFAULT, &sigterm_watcher);\n            ev_signal_stop(EV_DEFAULT, &sigchld_watcher);\n\n            ev_unloop(EV_A_ EVUNLOOP_ALL);\n        }\n    }\n}\n\nint\nmain(int argc, char **argv)\n{\n    srand(time(NULL));\n\n    int i, c;\n    int pid_flags    = 0;\n    int mptcp        = 0;\n    int mtu          = 0;\n    char *user       = NULL;\n    char *local_port = NULL;\n    char *local_addr = NULL;\n    char *password   = NULL;\n    char *key        = NULL;\n    char *timeout    = NULL;\n    char *method     = NULL;\n    char *pid_path   = NULL;\n    char *conf_path  = NULL;\n\n    char *plugin      = NULL;\n    char *plugin_opts = NULL;\n    char *plugin_host = NULL;\n    char *plugin_port = NULL;\n    char tmp_port[8];\n\n    int dscp_num    = 0;\n    ss_dscp_t *dscp = NULL;\n\n    int remote_num    = 0;\n    char *remote_port = NULL;\n    ss_addr_t remote_addr[MAX_REMOTE_NUM];\n\n    memset(remote_addr, 0, sizeof(ss_addr_t) * MAX_REMOTE_NUM);\n\n    static struct option long_options[] = {\n        { \"fast-open\",   no_argument,       NULL, GETOPT_VAL_FAST_OPEN   },\n        { \"mtu\",         required_argument, NULL, GETOPT_VAL_MTU         },\n        { \"mptcp\",       no_argument,       NULL, GETOPT_VAL_MPTCP       },\n        { \"plugin\",      required_argument, NULL, GETOPT_VAL_PLUGIN      },\n        { \"plugin-opts\", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },\n        { \"reuse-port\",  no_argument,       NULL, GETOPT_VAL_REUSE_PORT  },\n        { \"tcp-incoming-sndbuf\", required_argument, NULL, GETOPT_VAL_TCP_INCOMING_SNDBUF },\n        { \"tcp-incoming-rcvbuf\", required_argument, NULL, GETOPT_VAL_TCP_INCOMING_RCVBUF },\n        { \"tcp-outgoing-sndbuf\", required_argument, NULL, GETOPT_VAL_TCP_OUTGOING_SNDBUF },\n        { \"tcp-outgoing-rcvbuf\", required_argument, NULL, GETOPT_VAL_TCP_OUTGOING_RCVBUF },\n        { \"no-delay\",    no_argument,       NULL, GETOPT_VAL_NODELAY     },\n        { \"password\",    required_argument, NULL, GETOPT_VAL_PASSWORD    },\n        { \"key\",         required_argument, NULL, GETOPT_VAL_KEY         },\n        { \"help\",        no_argument,       NULL, GETOPT_VAL_HELP        },\n        { NULL,          0,                 NULL, 0                      }\n    };\n\n    opterr = 0;\n\n    USE_TTY();\n\n    while ((c = getopt_long(argc, argv, \"f:s:p:l:k:t:m:c:b:a:n:huUTv6A\",\n                            long_options, NULL)) != -1) {\n        switch (c) {\n        case GETOPT_VAL_FAST_OPEN:\n            fast_open = 1;\n            break;\n        case GETOPT_VAL_MTU:\n            mtu = atoi(optarg);\n            LOGI(\"set MTU to %d\", mtu);\n            break;\n        case GETOPT_VAL_MPTCP:\n            mptcp = get_mptcp(1);\n            if (mptcp)\n                LOGI(\"enable multipath TCP (%s)\", mptcp > 0 ? \"out-of-tree\" : \"upstream\");\n            break;\n        case GETOPT_VAL_NODELAY:\n            no_delay = 1;\n            LOGI(\"enable TCP no-delay\");\n            break;\n        case GETOPT_VAL_PLUGIN:\n            plugin = optarg;\n            break;\n        case GETOPT_VAL_PLUGIN_OPTS:\n            plugin_opts = optarg;\n            break;\n        case GETOPT_VAL_KEY:\n            key = optarg;\n            break;\n        case GETOPT_VAL_REUSE_PORT:\n            reuse_port = 1;\n            break;\n        case GETOPT_VAL_TCP_INCOMING_SNDBUF:\n            tcp_incoming_sndbuf = atoi(optarg);\n            break;\n        case GETOPT_VAL_TCP_INCOMING_RCVBUF:\n            tcp_incoming_rcvbuf = atoi(optarg);\n            break;\n        case GETOPT_VAL_TCP_OUTGOING_SNDBUF:\n            tcp_outgoing_sndbuf = atoi(optarg);\n            break;\n        case GETOPT_VAL_TCP_OUTGOING_RCVBUF:\n            tcp_outgoing_rcvbuf = atoi(optarg);\n            break;\n        case 's':\n            if (remote_num < MAX_REMOTE_NUM) {\n                parse_addr(optarg, &remote_addr[remote_num++]);\n            }\n            break;\n        case 'p':\n            remote_port = optarg;\n            break;\n        case 'l':\n            local_port = optarg;\n            break;\n        case GETOPT_VAL_PASSWORD:\n        case 'k':\n            password = optarg;\n            break;\n        case 'f':\n            pid_flags = 1;\n            pid_path  = optarg;\n            break;\n        case 't':\n            timeout = optarg;\n            break;\n        case 'm':\n            method = optarg;\n            break;\n        case 'c':\n            conf_path = optarg;\n            break;\n        case 'b':\n            local_addr = optarg;\n            break;\n        case 'a':\n            user = optarg;\n            break;\n#ifdef HAVE_SETRLIMIT\n        case 'n':\n            nofile = atoi(optarg);\n            break;\n#endif\n        case 'u':\n            mode = TCP_AND_UDP;\n            break;\n        case 'U':\n            mode = UDP_ONLY;\n            break;\n        case 'T':\n            tcp_tproxy = 1;\n            break;\n        case 'v':\n            verbose = 1;\n            break;\n        case GETOPT_VAL_HELP:\n        case 'h':\n            usage();\n            exit(EXIT_SUCCESS);\n        case '6':\n            ipv6first = 1;\n            break;\n        case 'A':\n            FATAL(\"One time auth has been deprecated. Try AEAD ciphers instead.\");\n            break;\n        case '?':\n            // The option character is not recognized.\n            LOGE(\"Unrecognized option: %s\", optarg);\n            opterr = 1;\n            break;\n        }\n    }\n\n    if (opterr) {\n        usage();\n        exit(EXIT_FAILURE);\n    }\n\n    if (argc == 1) {\n        if (conf_path == NULL) {\n            conf_path = get_default_conf();\n        }\n    }\n\n    if (conf_path != NULL) {\n        jconf_t *conf = read_jconf(conf_path);\n        if (remote_num == 0) {\n            remote_num = conf->remote_num;\n            for (i = 0; i < remote_num; i++)\n                remote_addr[i] = conf->remote_addr[i];\n        }\n        if (remote_port == NULL) {\n            remote_port = conf->remote_port;\n        }\n        if (local_addr == NULL) {\n            local_addr = conf->local_addr;\n        }\n        if (local_port == NULL) {\n            local_port = conf->local_port;\n        }\n        if (password == NULL) {\n            password = conf->password;\n        }\n        if (key == NULL) {\n            key = conf->key;\n        }\n        if (method == NULL) {\n            method = conf->method;\n        }\n        if (timeout == NULL) {\n            timeout = conf->timeout;\n        }\n        if (user == NULL) {\n            user = conf->user;\n        }\n        if (plugin == NULL) {\n            plugin = conf->plugin;\n        }\n        if (plugin_opts == NULL) {\n            plugin_opts = conf->plugin_opts;\n        }\n        if (mode == TCP_ONLY) {\n            mode = conf->mode;\n        }\n        if (tcp_tproxy == 0) {\n            tcp_tproxy = conf->tcp_tproxy;\n        }\n        if (mtu == 0) {\n            mtu = conf->mtu;\n        }\n        if (mptcp == 0) {\n            mptcp = conf->mptcp;\n        }\n        if (no_delay == 0) {\n            no_delay = conf->no_delay;\n        }\n        if (reuse_port == 0) {\n            reuse_port = conf->reuse_port;\n        }\n        if (tcp_incoming_sndbuf == 0) {\n            tcp_incoming_sndbuf = conf->tcp_incoming_sndbuf;\n        }\n        if (tcp_incoming_rcvbuf == 0) {\n            tcp_incoming_rcvbuf = conf->tcp_incoming_rcvbuf;\n        }\n        if (tcp_outgoing_sndbuf == 0) {\n            tcp_outgoing_sndbuf = conf->tcp_outgoing_sndbuf;\n        }\n        if (tcp_outgoing_rcvbuf == 0) {\n            tcp_outgoing_rcvbuf = conf->tcp_outgoing_rcvbuf;\n        }\n        if (fast_open == 0) {\n            fast_open = conf->fast_open;\n        }\n#ifdef HAVE_SETRLIMIT\n        if (nofile == 0) {\n            nofile = conf->nofile;\n        }\n#endif\n        if (ipv6first == 0) {\n            ipv6first = conf->ipv6_first;\n        }\n        dscp_num = conf->dscp_num;\n        dscp     = conf->dscp;\n    }\n\n    if (remote_num == 0 || remote_port == NULL || local_port == NULL\n        || (password == NULL && key == NULL)) {\n        usage();\n        exit(EXIT_FAILURE);\n    }\n\n    if (plugin != NULL) {\n        uint16_t port = get_local_port();\n        if (port == 0) {\n            FATAL(\"failed to find a free port\");\n        }\n        snprintf(tmp_port, 8, \"%d\", port);\n        if (is_ipv6only(remote_addr, remote_num, ipv6first)) {\n            plugin_host = \"::1\";\n        } else {\n            plugin_host = \"127.0.0.1\";\n        }\n        plugin_port = tmp_port;\n\n        LOGI(\"plugin \\\"%s\\\" enabled\", plugin);\n    }\n\n    if (method == NULL) {\n        method = \"chacha20-ietf-poly1305\";\n    }\n\n    if (timeout == NULL) {\n        timeout = \"600\";\n    }\n\n#ifdef HAVE_SETRLIMIT\n    /*\n     * no need to check the return value here since we will show\n     * the user an error message if setrlimit(2) fails\n     */\n    if (nofile > 1024) {\n        if (verbose) {\n            LOGI(\"setting NOFILE to %d\", nofile);\n        }\n        set_nofile(nofile);\n    }\n#endif\n\n    if (local_addr == NULL) {\n        if (is_ipv6only(remote_addr, remote_num, ipv6first)) {\n            local_addr = \"::1\";\n        } else {\n            local_addr = \"127.0.0.1\";\n        }\n    }\n\n    if (fast_open == 1) {\n#ifdef TCP_FASTOPEN\n        LOGI(\"using tcp fast open\");\n#else\n        LOGE(\"tcp fast open is not supported by this environment\");\n        fast_open = 0;\n#endif\n    }\n\n    USE_SYSLOG(argv[0], pid_flags);\n    if (pid_flags) {\n        daemonize(pid_path);\n    }\n\n    if (no_delay) {\n        LOGI(\"enable TCP no-delay\");\n    }\n\n    if (ipv6first) {\n        LOGI(\"resolving hostname to IPv6 address first\");\n    }\n\n    if (tcp_incoming_sndbuf != 0 && tcp_incoming_sndbuf < SOCKET_BUF_SIZE) {\n        tcp_incoming_sndbuf = 0;\n    }\n\n    if (tcp_incoming_sndbuf != 0) {\n        LOGI(\"set TCP incoming connection send buffer size to %d\", tcp_incoming_sndbuf);\n    }\n\n    if (tcp_incoming_rcvbuf != 0 && tcp_incoming_rcvbuf < SOCKET_BUF_SIZE) {\n        tcp_incoming_rcvbuf = 0;\n    }\n\n    if (tcp_incoming_rcvbuf != 0) {\n        LOGI(\"set TCP incoming connection receive buffer size to %d\", tcp_incoming_rcvbuf);\n    }\n\n    if (tcp_outgoing_sndbuf != 0 && tcp_outgoing_sndbuf < SOCKET_BUF_SIZE) {\n        tcp_outgoing_sndbuf = 0;\n    }\n\n    if (tcp_outgoing_sndbuf != 0) {\n        LOGI(\"set TCP outgoing connection send buffer size to %d\", tcp_outgoing_sndbuf);\n    }\n\n    if (tcp_outgoing_rcvbuf != 0 && tcp_outgoing_rcvbuf < SOCKET_BUF_SIZE) {\n        tcp_outgoing_rcvbuf = 0;\n    }\n\n    if (tcp_outgoing_rcvbuf != 0) {\n        LOGI(\"set TCP outgoing connection receive buffer size to %d\", tcp_outgoing_rcvbuf);\n    }\n\n    if (plugin != NULL) {\n        int len          = 0;\n        size_t buf_size  = 256 * remote_num;\n        char *remote_str = ss_malloc(buf_size);\n\n        snprintf(remote_str, buf_size, \"%s\", remote_addr[0].host);\n        for (int i = 1; i < remote_num; i++) {\n            snprintf(remote_str + len, buf_size - len, \"|%s\", remote_addr[i].host);\n            len = strlen(remote_str);\n        }\n        int err = start_plugin(plugin, plugin_opts, remote_str,\n                               remote_port, plugin_host, plugin_port, MODE_CLIENT);\n        if (err) {\n            FATAL(\"failed to start the plugin\");\n        }\n    }\n\n    // ignore SIGPIPE\n    signal(SIGPIPE, SIG_IGN);\n    signal(SIGABRT, SIG_IGN);\n\n    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);\n    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);\n    ev_signal_init(&sigchld_watcher, signal_cb, SIGCHLD);\n    ev_signal_start(EV_DEFAULT, &sigint_watcher);\n    ev_signal_start(EV_DEFAULT, &sigterm_watcher);\n    ev_signal_start(EV_DEFAULT, &sigchld_watcher);\n\n    // Setup keys\n    LOGI(\"initializing ciphers... %s\", method);\n    crypto = crypto_init(password, key, method);\n    if (crypto == NULL)\n        FATAL(\"failed to initialize ciphers\");\n\n    // Setup proxy context\n    struct listen_ctx listen_ctx;\n    memset(&listen_ctx, 0, sizeof(struct listen_ctx));\n    listen_ctx.remote_num  = remote_num;\n    listen_ctx.remote_addr = ss_malloc(sizeof(struct sockaddr *) * remote_num);\n    memset(listen_ctx.remote_addr, 0, sizeof(struct sockaddr *) * remote_num);\n    for (i = 0; i < remote_num; i++) {\n        char *host = remote_addr[i].host;\n        char *port = remote_addr[i].port == NULL ? remote_port :\n                     remote_addr[i].port;\n        if (plugin != NULL) {\n            host = plugin_host;\n            port = plugin_port;\n        }\n        struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage));\n        memset(storage, 0, sizeof(struct sockaddr_storage));\n        if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) {\n            FATAL(\"failed to resolve the provided hostname\");\n        }\n        listen_ctx.remote_addr[i] = (struct sockaddr *)storage;\n\n        if (plugin != NULL)\n            break;\n    }\n    listen_ctx.timeout = atoi(timeout);\n    listen_ctx.mptcp   = mptcp;\n\n    struct ev_loop *loop = EV_DEFAULT;\n\n    listen_ctx_t *listen_ctx_current = &listen_ctx;\n    do {\n        if (listen_ctx_current->tos) {\n            LOGI(\"listening at %s:%s (TOS 0x%x)\", local_addr, local_port, listen_ctx_current->tos);\n        } else {\n            LOGI(\"listening at %s:%s\", local_addr, local_port);\n        }\n\n        if (mode != UDP_ONLY) {\n            // Setup socket\n            int listenfd;\n            listenfd = create_and_bind(local_addr, local_port);\n            if (listenfd == -1) {\n                FATAL(\"bind() error\");\n            }\n            if (listen(listenfd, SOMAXCONN) == -1) {\n                FATAL(\"listen() error\");\n            }\n            setnonblocking(listenfd);\n\n            listen_ctx_current->fd = listenfd;\n\n            ev_io_init(&listen_ctx_current->io, accept_cb, listenfd, EV_READ);\n            ev_io_start(loop, &listen_ctx_current->io);\n        }\n\n        // Setup UDP\n        if (mode != TCP_ONLY) {\n            LOGI(\"UDP relay enabled\");\n            char *host                       = remote_addr[0].host;\n            char *port                       = remote_addr[0].port == NULL ? remote_port : remote_addr[0].port;\n            struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage));\n            memset(storage, 0, sizeof(struct sockaddr_storage));\n            if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) {\n                FATAL(\"failed to resolve the provided hostname\");\n            }\n            struct sockaddr *addr = (struct sockaddr *)storage;\n            init_udprelay(local_addr, local_port, addr,\n                          get_sockaddr_len(addr), mtu, crypto, listen_ctx_current->timeout, NULL);\n        }\n\n        if (mode == UDP_ONLY) {\n            LOGI(\"TCP relay disabled\");\n        }\n\n        // Handle additionals TOS/DSCP listening ports\n        if (dscp_num > 0) {\n            listen_ctx_current      = (listen_ctx_t *)ss_malloc(sizeof(listen_ctx_t));\n            listen_ctx_current      = memcpy(listen_ctx_current, &listen_ctx, sizeof(listen_ctx_t));\n            local_port              = dscp[dscp_num - 1].port;\n            listen_ctx_current->tos = dscp[dscp_num - 1].dscp << 2;\n        }\n    } while (dscp_num-- > 0);\n\n    // setuid\n    if (user != NULL && !run_as(user)) {\n        FATAL(\"failed to switch user\");\n    }\n\n    if (geteuid() == 0) {\n        LOGI(\"running from root user\");\n    }\n\n    ev_run(loop, 0);\n\n    if (plugin != NULL) {\n        stop_plugin();\n    }\n\n    for (i = 0; i < remote_num; i++)\n        ss_free(listen_ctx.remote_addr[i]);\n    ss_free(listen_ctx.remote_addr);\n\n    return ret_val;\n}\n"
  },
  {
    "path": "src/redir.h",
    "content": "/* * redir.h - Define the redirector's buffers and callbacks\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _REDIR_H\n#define _REDIR_H\n\n#ifdef HAVE_LIBEV_EV_H\n#include <libev/ev.h>\n#else\n#include <ev.h>\n#endif\n\n#include \"crypto.h\"\n#include \"jconf.h\"\n\ntypedef struct listen_ctx {\n    ev_io io;\n    int remote_num;\n    int timeout;\n    int fd;\n    int mptcp;\n    int tos;\n    struct sockaddr **remote_addr;\n} listen_ctx_t;\n\ntypedef struct server_ctx {\n    ev_io io;\n    int connected;\n    struct server *server;\n} server_ctx_t;\n\ntypedef struct server {\n    int fd;\n\n    buffer_t *buf;\n\n    cipher_ctx_t *e_ctx;\n    cipher_ctx_t *d_ctx;\n    struct server_ctx *recv_ctx;\n    struct server_ctx *send_ctx;\n    struct remote *remote;\n\n    struct sockaddr_storage destaddr;\n    ev_timer delayed_connect_watcher;\n} server_t;\n\ntypedef struct remote_ctx {\n    ev_io io;\n    ev_timer watcher;\n    int connected;\n    struct remote *remote;\n} remote_ctx_t;\n\ntypedef struct remote {\n    int fd;\n    buffer_t *buf;\n    struct remote_ctx *recv_ctx;\n    struct remote_ctx *send_ctx;\n    struct server *server;\n    uint32_t counter;\n    struct sockaddr *addr;\n} remote_t;\n\n#endif // _REDIR_H\n"
  },
  {
    "path": "src/resolv.c",
    "content": "/*\n * Copyright (c) 2014, Dustin Lundquist <dustin@null-ptr.net>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice,\n *    this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <fcntl.h>\n#ifndef __MINGW32__\n#include <netdb.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <errno.h>\n#include <unistd.h>\n#else\n#include \"winsock.h\" // Should be before <ares.h>\n#endif\n#include <ares.h>\n\n#ifdef HAVE_LIBEV_EV_H\n#include <libev/ev.h>\n#else\n#include <ev.h>\n#endif\n\n#include <libcork/core.h>\n\n#include \"resolv.h\"\n#include \"utils.h\"\n#include \"netutils.h\"\n\n#ifdef __MINGW32__\n#define CONV_STATE_CB (ares_sock_state_cb)\n#else\n#define CONV_STATE_CB\n#endif\n\n/*\n * Implement DNS resolution interface using libc-ares\n */\n\n#define SS_NUM_IOS 6\n#define SS_INVALID_FD -1\n#define SS_TIMER_AFTER 1.0\n\nstruct resolv_ctx {\n    struct ev_io ios[SS_NUM_IOS];\n    struct ev_timer timer;\n    ev_tstamp last_tick;\n\n    ares_channel channel;\n    struct ares_options options;\n};\n\nstruct resolv_query {\n    int requests[2];\n    size_t response_count;\n    struct sockaddr **responses;\n\n    void (*client_cb)(struct sockaddr *, void *);\n    void (*free_cb)(void *);\n\n    uint16_t port;\n\n    void *data;\n\n    int is_closed;\n};\n\nextern int verbose;\n\nstatic struct resolv_ctx default_ctx;\nstatic struct ev_loop *default_loop;\n\nenum {\n    MODE_IPV4_FIRST = 0,\n    MODE_IPV6_FIRST = 1\n} RESOLV_MODE;\n\nstatic int resolv_mode = MODE_IPV4_FIRST;\n\nstatic void resolv_sock_cb(struct ev_loop *, struct ev_io *, int);\nstatic void resolv_timer_cb(struct ev_loop *, struct ev_timer *, int);\nstatic void resolv_sock_state_cb(void *, int, int, int);\n\nstatic void dns_query_v4_cb(void *, int, int, struct hostent *);\nstatic void dns_query_v6_cb(void *, int, int, struct hostent *);\n\nstatic void process_client_callback(struct resolv_query *);\nstatic inline int all_requests_are_null(struct resolv_query *);\nstatic struct sockaddr *choose_ipv4_first(struct resolv_query *);\nstatic struct sockaddr *choose_ipv6_first(struct resolv_query *);\nstatic struct sockaddr *choose_any(struct resolv_query *);\n\n/*\n * DNS UDP socket activity callback\n */\nstatic void\nresolv_sock_cb(EV_P_ ev_io *w, int revents)\n{\n    ares_socket_t rfd = ARES_SOCKET_BAD, wfd = ARES_SOCKET_BAD;\n\n    if (revents & EV_READ)\n        rfd = w->fd;\n    if (revents & EV_WRITE)\n        wfd = w->fd;\n\n    default_ctx.last_tick = ev_now(default_loop);\n\n    ares_process_fd(default_ctx.channel, rfd, wfd);\n}\n\nint\nresolv_init(struct ev_loop *loop, char *nameservers, int ipv6first)\n{\n    int status;\n\n    if (ipv6first)\n        resolv_mode = MODE_IPV6_FIRST;\n    else\n        resolv_mode = MODE_IPV4_FIRST;\n\n    default_loop = loop;\n\n    if ((status = ares_library_init(ARES_LIB_INIT_ALL)) != ARES_SUCCESS) {\n        LOGE(\"c-ares error: %s\", ares_strerror(status));\n        FATAL(\"failed to initialize c-ares\");\n    }\n\n    memset(&default_ctx, 0, sizeof(struct resolv_ctx));\n\n    default_ctx.options.sock_state_cb_data = &default_ctx;\n    default_ctx.options.sock_state_cb      = CONV_STATE_CB resolv_sock_state_cb;\n    default_ctx.options.timeout            = 3000;\n    default_ctx.options.tries              = 2;\n\n    status = ares_init_options(&default_ctx.channel, &default_ctx.options,\n#if ARES_VERSION_MAJOR >= 1 && ARES_VERSION_MINOR >= 12\n                               ARES_OPT_NOROTATE |\n#endif\n                               ARES_OPT_TIMEOUTMS | ARES_OPT_TRIES | ARES_OPT_SOCK_STATE_CB);\n\n    if (status != ARES_SUCCESS) {\n        FATAL(\"failed to initialize c-ares\");\n    }\n\n    if (nameservers != NULL) {\n#if ARES_VERSION_MAJOR >= 1 && ARES_VERSION_MINOR >= 11\n        status = ares_set_servers_ports_csv(default_ctx.channel, nameservers);\n#else\n        status = ares_set_servers_csv(default_ctx.channel, nameservers);\n#endif\n    }\n\n    if (status != ARES_SUCCESS) {\n        FATAL(\"failed to set nameservers\");\n    }\n\n    for (int i = 0; i < SS_NUM_IOS; i++)\n        ev_io_init(&default_ctx.ios[i], resolv_sock_cb, SS_INVALID_FD, 0);\n\n    default_ctx.last_tick = ev_now(default_loop);\n    ev_init(&default_ctx.timer, resolv_timer_cb);\n    resolv_timer_cb(default_loop, &default_ctx.timer, 0);\n\n    return 0;\n}\n\nvoid\nresolv_shutdown(struct ev_loop *loop)\n{\n    ev_timer_stop(default_loop, &default_ctx.timer);\n    for (int i = 0; i < SS_NUM_IOS; i++)\n        ev_io_stop(default_loop, &default_ctx.ios[i]);\n\n    ares_cancel(default_ctx.channel);\n    ares_destroy(default_ctx.channel);\n\n    ares_library_cleanup();\n}\n\nvoid\nresolv_start(const char *hostname, uint16_t port,\n             void (*client_cb)(struct sockaddr *, void *),\n             void (*free_cb)(void *), void *data)\n{\n    /*\n     * Wrap c-ares's call back in our own\n     */\n    struct resolv_query *query = ss_malloc(sizeof(struct resolv_query));\n\n    memset(query, 0, sizeof(struct resolv_query));\n\n    query->port           = port;\n    query->client_cb      = client_cb;\n    query->response_count = 0;\n    query->responses      = NULL;\n    query->data           = data;\n    query->free_cb        = free_cb;\n\n    query->requests[0] = AF_INET;\n    query->requests[1] = AF_INET6;\n\n    ares_gethostbyname(default_ctx.channel, hostname, AF_INET, dns_query_v4_cb, query);\n    ares_gethostbyname(default_ctx.channel, hostname, AF_INET6, dns_query_v6_cb, query);\n}\n\n/*\n * Wrapper for client callback we provide to c-ares\n */\nstatic void\ndns_query_v4_cb(void *arg, int status, int timeouts, struct hostent *he)\n{\n    int i, n;\n    struct resolv_query *query = (struct resolv_query *)arg;\n\n    if (status == ARES_EDESTRUCTION) {\n        return;\n    }\n\n    if (!he || status != ARES_SUCCESS) {\n        if (verbose) {\n            LOGI(\"failed to lookup v4 address %s\", ares_strerror(status));\n        }\n        goto CLEANUP;\n    }\n\n    if (verbose) {\n        LOGI(\"found address name v4 address %s\", he->h_name);\n    }\n\n    n = 0;\n    while (he->h_addr_list[n])\n        n++;\n\n    if (n > 0) {\n        struct sockaddr **new_responses = ss_realloc(query->responses,\n                                                     (query->response_count + n)\n                                                     * sizeof(struct sockaddr *));\n\n        if (new_responses == NULL) {\n            LOGE(\"failed to allocate memory for additional DNS responses\");\n        } else {\n            query->responses = new_responses;\n\n            for (i = 0; i < n; i++) {\n                struct sockaddr_in *sa = ss_malloc(sizeof(struct sockaddr_in));\n                memset(sa, 0, sizeof(struct sockaddr_in));\n                sa->sin_family = AF_INET;\n                sa->sin_port   = query->port;\n                memcpy(&sa->sin_addr, he->h_addr_list[i], he->h_length);\n\n                query->responses[query->response_count] = (struct sockaddr *)sa;\n                if (query->responses[query->response_count] == NULL) {\n                    LOGE(\"failed to allocate memory for DNS query result address\");\n                } else {\n                    query->response_count++;\n                }\n            }\n        }\n    }\n\nCLEANUP:\n\n    query->requests[0] = 0; /* mark A query as being completed */\n\n    /* Once all requests have completed, call client callback */\n    if (all_requests_are_null(query)) {\n        return process_client_callback(query);\n    }\n}\n\nstatic void\ndns_query_v6_cb(void *arg, int status, int timeouts, struct hostent *he)\n{\n    int i, n;\n    struct resolv_query *query = (struct resolv_query *)arg;\n\n    if (status == ARES_EDESTRUCTION) {\n        return;\n    }\n\n    if (!he || status != ARES_SUCCESS) {\n        if (verbose) {\n            LOGI(\"failed to lookup v6 address %s\", ares_strerror(status));\n        }\n        goto CLEANUP;\n    }\n\n    if (verbose) {\n        LOGI(\"found address name v6 address %s\", he->h_name);\n    }\n\n    n = 0;\n    while (he->h_addr_list[n])\n        n++;\n\n    if (n > 0) {\n        struct sockaddr **new_responses = ss_realloc(query->responses,\n                                                     (query->response_count + n)\n                                                     * sizeof(struct sockaddr *));\n\n        if (new_responses == NULL) {\n            LOGE(\"failed to allocate memory for additional DNS responses\");\n        } else {\n            query->responses = new_responses;\n\n            for (i = 0; i < n; i++) {\n                struct sockaddr_in6 *sa = ss_malloc(sizeof(struct sockaddr_in6));\n                memset(sa, 0, sizeof(struct sockaddr_in6));\n                sa->sin6_family = AF_INET6;\n                sa->sin6_port   = query->port;\n                memcpy(&sa->sin6_addr, he->h_addr_list[i], he->h_length);\n\n                query->responses[query->response_count] = (struct sockaddr *)sa;\n                if (query->responses[query->response_count] == NULL) {\n                    LOGE(\"failed to allocate memory for DNS query result address\");\n                } else {\n                    query->response_count++;\n                }\n            }\n        }\n    }\n\nCLEANUP:\n\n    query->requests[1] = 0; /* mark A query as being completed */\n\n    /* Once all requests have completed, call client callback */\n    if (all_requests_are_null(query)) {\n        return process_client_callback(query);\n    }\n}\n\n/*\n * Called once all requests have been completed\n */\nstatic void\nprocess_client_callback(struct resolv_query *query)\n{\n    struct sockaddr *best_address = NULL;\n\n    if (resolv_mode == MODE_IPV4_FIRST) {\n        best_address = choose_ipv4_first(query);\n    } else if (resolv_mode == MODE_IPV6_FIRST) {\n        best_address = choose_ipv6_first(query);\n    } else {\n        best_address = choose_any(query);\n    }\n\n    query->client_cb(best_address, query->data);\n\n    for (int i = 0; i < query->response_count; i++)\n        ss_free(query->responses[i]);\n\n    ss_free(query->responses);\n\n    if (query->free_cb != NULL)\n        query->free_cb(query->data);\n    else\n        ss_free(query->data);\n\n    ss_free(query);\n}\n\nstatic struct sockaddr *\nchoose_ipv4_first(struct resolv_query *query)\n{\n    for (int i = 0; i < query->response_count; i++)\n        if (query->responses[i]->sa_family == AF_INET) {\n            return query->responses[i];\n        }\n\n    return choose_any(query);\n}\n\nstatic struct sockaddr *\nchoose_ipv6_first(struct resolv_query *query)\n{\n    for (int i = 0; i < query->response_count; i++)\n        if (query->responses[i]->sa_family == AF_INET6) {\n            return query->responses[i];\n        }\n\n    return choose_any(query);\n}\n\nstatic struct sockaddr *\nchoose_any(struct resolv_query *query)\n{\n    if (query->response_count >= 1) {\n        return query->responses[0];\n    }\n\n    return NULL;\n}\n\nstatic inline int\nall_requests_are_null(struct resolv_query *query)\n{\n    int result = 1;\n\n    for (int i = 0; i < sizeof(query->requests) / sizeof(query->requests[0]);\n         i++)\n        result = result && query->requests[i] == 0;\n\n    return result;\n}\n\n/*\n *  Timer callback\n */\nstatic void\nresolv_timer_cb(struct ev_loop *loop, struct ev_timer *w, int revents)\n{\n    struct resolv_ctx *ctx = cork_container_of(w, struct resolv_ctx, timer);\n\n    ev_tstamp now   = ev_now(default_loop);\n    ev_tstamp after = ctx->last_tick - now + SS_TIMER_AFTER;\n\n    if (after < 0.0) {\n        ctx->last_tick = now;\n        ares_process_fd(ctx->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);\n\n        ev_timer_set(w, SS_TIMER_AFTER, 0.0);\n    } else {\n        ev_timer_set(w, after, 0.0);\n    }\n\n    ev_timer_start(loop, w);\n}\n\n/*\n * Handle c-ares events\n */\nstatic void\nresolv_sock_state_cb(void *data, int s, int read, int write)\n{\n    struct resolv_ctx *ctx = (struct resolv_ctx *)data;\n    int events             = (read ? EV_READ : 0) | (write ? EV_WRITE : 0);\n\n    int i = 0, ffi = -1;\n    for (; i < SS_NUM_IOS; i++) {\n        if (ctx->ios[i].fd == s) {\n            break;\n        }\n\n        if (ffi < 0 && ctx->ios[i].fd == SS_INVALID_FD) {\n            // first free index\n            ffi = i;\n        }\n    }\n\n    if (i < SS_NUM_IOS) {\n        ev_io_stop(default_loop, &ctx->ios[i]);\n    } else if (ffi > -1) {\n        i = ffi;\n    } else {\n        LOGE(\"failed to find free I/O watcher slot for DNS query\");\n        // last resort: stop io and re-use slot, will cause timeout\n        i = 0;\n        ev_io_stop(default_loop, &ctx->ios[i]);\n    }\n\n    if (events) {\n        ev_io_set(&ctx->ios[i], s, events);\n        ev_io_start(default_loop, &ctx->ios[i]);\n    } else {\n        ev_io_set(&ctx->ios[i], SS_INVALID_FD, 0);\n    }\n}\n"
  },
  {
    "path": "src/resolv.h",
    "content": "/*\n * Copyright (c) 2014, Dustin Lundquist <dustin@null-ptr.net>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice,\n *    this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef RESOLV_H\n#define RESOLV_H\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdint.h>\n#ifndef __MINGW32__\n#include <sys/socket.h>\n#endif\n\nstruct resolv_query;\n\nint resolv_init(struct ev_loop *, char *, int);\nvoid resolv_start(const char *hostname, uint16_t port,\n                  void (*client_cb)(struct sockaddr *, void *),\n                  void (*free_cb)(void *), void *data);\nvoid resolv_shutdown(struct ev_loop *);\n\n#endif\n"
  },
  {
    "path": "src/rule.c",
    "content": "/*\n * Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>\n * Copyright (c) 2011 Manuel Kasper <mk@neon1.net>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice,\n *    this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdio.h>\n#include <string.h>\n\n#include \"rule.h\"\n#include \"utils.h\"\n\nstatic void free_rule(rule_t *);\n\nrule_t *\nnew_rule()\n{\n    rule_t *rule;\n\n    rule = calloc(1, sizeof(rule_t));\n    if (rule == NULL) {\n        ERROR(\"malloc\");\n        return NULL;\n    }\n\n    return rule;\n}\n\nint\naccept_rule_arg(rule_t *rule, const char *arg)\n{\n    if (rule->pattern == NULL) {\n        rule->pattern = strdup(arg);\n        if (rule->pattern == NULL) {\n            ERROR(\"strdup failed\");\n            return -1;\n        }\n    } else {\n        LOGE(\"Unexpected table rule argument: %s\", arg);\n        return -1;\n    }\n\n    return 1;\n}\n\nvoid\nadd_rule(struct cork_dllist *rules, rule_t *rule)\n{\n    cork_dllist_add(rules, &rule->entries);\n}\n\nint\ninit_rule(rule_t *rule)\n{\n    if (rule->pattern_re == NULL) {\n        int errcode;\n        PCRE2_SIZE erroffset;\n\n        rule->pattern_re =\n            pcre2_compile((PCRE2_SPTR)rule->pattern, PCRE2_ZERO_TERMINATED,\n                          0, &errcode, &erroffset, NULL);\n        if (rule->pattern_re == NULL) {\n            PCRE2_UCHAR errbuf[256];\n            pcre2_get_error_message(errcode, errbuf, sizeof(errbuf));\n            LOGE(\"Regex compilation of \\\"%s\\\" failed: %s, offset %d\",\n                 rule->pattern, errbuf, (int)erroffset);\n            return 0;\n        }\n        rule->match_data = pcre2_match_data_create_from_pattern(\n            rule->pattern_re, NULL);\n    }\n\n    return 1;\n}\n\nrule_t *\nlookup_rule(const struct cork_dllist *rules, const char *name, size_t name_len)\n{\n    struct cork_dllist_item *curr, *next;\n\n    if (name == NULL) {\n        name     = \"\";\n        name_len = 0;\n    }\n\n    cork_dllist_foreach_void(rules, curr, next) {\n        rule_t *rule = cork_container_of(curr, rule_t, entries);\n        if (pcre2_match(rule->pattern_re, (PCRE2_SPTR)name,\n                        name_len, 0, 0, rule->match_data, NULL) >= 0)\n            return rule;\n    }\n\n    return NULL;\n}\n\nvoid\nremove_rule(rule_t *rule)\n{\n    cork_dllist_remove(&rule->entries);\n    free_rule(rule);\n}\n\nstatic void\nfree_rule(rule_t *rule)\n{\n    if (rule == NULL)\n        return;\n\n    ss_free(rule->pattern);\n    if (rule->match_data != NULL)\n        pcre2_match_data_free(rule->match_data);\n    if (rule->pattern_re != NULL)\n        pcre2_code_free(rule->pattern_re);\n    ss_free(rule);\n}\n"
  },
  {
    "path": "src/rule.h",
    "content": "/*\n * Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>\n * Copyright (c) 2011 Manuel Kasper <mk@neon1.net>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice,\n *    this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef RULE_H\n#define RULE_H\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <libcork/ds.h>\n\n#define PCRE2_CODE_UNIT_WIDTH 8\n#include <pcre2.h>\n\ntypedef struct rule {\n    char *pattern;\n\n    /* Runtime fields */\n    pcre2_code *pattern_re;\n    pcre2_match_data *match_data;\n\n    struct cork_dllist_item entries;\n} rule_t;\n\nvoid add_rule(struct cork_dllist *, rule_t *);\nint init_rule(rule_t *);\nrule_t *lookup_rule(const struct cork_dllist *, const char *, size_t);\nvoid remove_rule(rule_t *);\nrule_t *new_rule();\nint accept_rule_arg(rule_t *, const char *);\n\n#endif\n"
  },
  {
    "path": "src/server.c",
    "content": "/*\n * server.c - Provide shadowsocks service\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <fcntl.h>\n#include <locale.h>\n#include <signal.h>\n#include <string.h>\n#include <strings.h>\n#include <time.h>\n#include <unistd.h>\n#include <getopt.h>\n#include <math.h>\n#ifndef __MINGW32__\n#include <netdb.h>\n#include <errno.h>\n#include <arpa/inet.h>\n#include <netinet/in.h>\n#include <pthread.h>\n#include <sys/un.h>\n#endif\n#include <libcork/core.h>\n\n#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__)\n#include <net/if.h>\n#include <sys/ioctl.h>\n#define SET_INTERFACE\n#endif\n\n#ifdef USE_NFTABLES\n#include <ctype.h>\n#include <linux/netfilter.h>\n#include <linux/netfilter/nf_tables.h>\n#include <libmnl/libmnl.h>\n#include <libnftnl/set.h>\n/* the datatypes enum is picked from libnftables/datatype.h\n   to avoid to depend libnftables */\nenum datatypes {\n    TYPE_IPADDR = 7,\n    TYPE_IP6ADDR\n};\n#endif\n\n#include \"netutils.h\"\n#include \"utils.h\"\n#include \"acl.h\"\n#include \"plugin.h\"\n#include \"server.h\"\n#include \"winsock.h\"\n#include \"resolv.h\"\n\n#ifndef EAGAIN\n#define EAGAIN EWOULDBLOCK\n#endif\n\n#ifndef EWOULDBLOCK\n#define EWOULDBLOCK EAGAIN\n#endif\n\n#ifndef SSMAXCONN\n#define SSMAXCONN 1024\n#endif\n\n#ifdef USE_NFCONNTRACK_TOS\n\n#ifndef MARK_MAX_PACKET\n#define MARK_MAX_PACKET 10\n#endif\n\n#ifndef MARK_MASK_PREFIX\n#define MARK_MASK_PREFIX 0xDC00\n#endif\n\n#endif\n\nstatic void signal_cb(EV_P_ ev_signal *w, int revents);\nstatic void accept_cb(EV_P_ ev_io *w, int revents);\nstatic void server_send_cb(EV_P_ ev_io *w, int revents);\nstatic void server_recv_cb(EV_P_ ev_io *w, int revents);\nstatic void remote_recv_cb(EV_P_ ev_io *w, int revents);\nstatic void remote_send_cb(EV_P_ ev_io *w, int revents);\nstatic void server_timeout_cb(EV_P_ ev_timer *watcher, int revents);\n\nstatic remote_t *new_remote(int fd);\nstatic server_t *new_server(int fd, listen_ctx_t *listener);\nstatic remote_t *connect_to_remote(EV_P_ struct addrinfo *res,\n                                   server_t *server);\n\nstatic void free_remote(remote_t *remote);\nstatic void close_and_free_remote(EV_P_ remote_t *remote);\nstatic void free_server(server_t *server);\nstatic void close_and_free_server(EV_P_ server_t *server);\nstatic void resolv_cb(struct sockaddr *addr, void *data);\nstatic void resolv_free_cb(void *data);\n\nint verbose    = 0;\nint reuse_port = 0;\nint tcp_incoming_sndbuf = 0;\nint tcp_incoming_rcvbuf = 0;\nint tcp_outgoing_sndbuf = 0;\nint tcp_outgoing_rcvbuf = 0;\n\nint is_bind_local_addr = 0;\nstruct sockaddr_storage local_addr_v4;\nstruct sockaddr_storage local_addr_v6;\n\nstatic crypto_t *crypto;\n\nstatic int acl       = 0;\nstatic int mode      = TCP_ONLY;\nstatic int ipv6first = 0;\nint fast_open        = 0;\nstatic int no_delay  = 0;\nstatic int ret_val   = 0;\n\n#ifdef HAVE_SETRLIMIT\nstatic int nofile = 0;\n#endif\nstatic int remote_conn = 0;\nstatic int server_conn = 0;\n\nstatic char *plugin       = NULL;\nstatic char *remote_port  = NULL;\nstatic char *manager_addr = NULL;\nuint64_t tx               = 0;\nuint64_t rx               = 0;\n\n#ifndef __MINGW32__\nev_timer stat_update_watcher;\n#endif\n\nstatic struct ev_signal sigint_watcher;\nstatic struct ev_signal sigterm_watcher;\n#ifndef __MINGW32__\nstatic struct ev_signal sigchld_watcher;\n#else\nstatic struct plugin_watcher_t {\n    ev_io io;\n    SOCKET fd;\n    uint16_t port;\n    int valid;\n} plugin_watcher;\n#endif\n\nstatic struct cork_dllist connections;\n\n#ifndef __MINGW32__\nstatic void\nstat_update_cb(EV_P_ ev_timer *watcher, int revents)\n{\n    struct sockaddr_un svaddr, claddr;\n    int sfd = -1;\n    size_t msgLen;\n    char resp[SOCKET_BUF_SIZE];\n\n    if (verbose) {\n        LOGI(\"update traffic stat: tx: %\" PRIu64 \" rx: %\" PRIu64 \"\", tx, rx);\n    }\n\n    snprintf(resp, SOCKET_BUF_SIZE, \"stat: {\\\"%s\\\":%\" PRIu64 \"}\", remote_port, tx + rx);\n    msgLen = strlen(resp) + 1;\n\n    ss_addr_t ip_addr = { .host = NULL, .port = NULL };\n    parse_addr(manager_addr, &ip_addr);\n\n    if (ip_addr.host == NULL || ip_addr.port == NULL) {\n        sfd = socket(AF_UNIX, SOCK_DGRAM, 0);\n        if (sfd == -1) {\n            ERROR(\"stat_socket\");\n            return;\n        }\n\n        memset(&claddr, 0, sizeof(struct sockaddr_un));\n        claddr.sun_family = AF_UNIX;\n        snprintf(claddr.sun_path, sizeof(claddr.sun_path), \"/tmp/shadowsocks.%s\", remote_port);\n\n        unlink(claddr.sun_path);\n\n        if (bind(sfd, (struct sockaddr *)&claddr, sizeof(struct sockaddr_un)) == -1) {\n            ERROR(\"stat_bind\");\n            close(sfd);\n            return;\n        }\n\n        memset(&svaddr, 0, sizeof(struct sockaddr_un));\n        svaddr.sun_family = AF_UNIX;\n        strncpy(svaddr.sun_path, manager_addr, sizeof(svaddr.sun_path) - 1);\n\n        if (sendto(sfd, resp, strlen(resp) + 1, 0, (struct sockaddr *)&svaddr,\n                   sizeof(struct sockaddr_un)) != msgLen) {\n            ERROR(\"stat_sendto\");\n            close(sfd);\n            return;\n        }\n\n        unlink(claddr.sun_path);\n    } else {\n        struct sockaddr_storage storage;\n        memset(&storage, 0, sizeof(struct sockaddr_storage));\n        if (get_sockaddr(ip_addr.host, ip_addr.port, &storage, 0, ipv6first) == -1) {\n            ERROR(\"failed to parse the manager addr\");\n            return;\n        }\n\n        sfd = socket(storage.ss_family, SOCK_DGRAM, 0);\n\n        if (sfd == -1) {\n            ERROR(\"stat_socket\");\n            return;\n        }\n\n        size_t addr_len = get_sockaddr_len((struct sockaddr *)&storage);\n        if (sendto(sfd, resp, strlen(resp) + 1, 0, (struct sockaddr *)&storage,\n                   addr_len) != msgLen) {\n            ERROR(\"stat_sendto\");\n            close(sfd);\n            return;\n        }\n    }\n\n    close(sfd);\n}\n\n#endif\n\nstatic void\nfree_connections(struct ev_loop *loop)\n{\n    struct cork_dllist_item *curr, *next;\n    cork_dllist_foreach_void(&connections, curr, next) {\n        server_t *server = cork_container_of(curr, server_t, entries);\n        remote_t *remote = server->remote;\n        close_and_free_server(loop, server);\n        close_and_free_remote(loop, remote);\n    }\n}\n\nstatic char *\nget_peer_name(int fd)\n{\n    static char peer_name[INET6_ADDRSTRLEN] = { 0 };\n    struct sockaddr_storage addr;\n    socklen_t len = sizeof(struct sockaddr_storage);\n    memset(&addr, 0, len);\n    memset(peer_name, 0, INET6_ADDRSTRLEN);\n    int err = getpeername(fd, (struct sockaddr *)&addr, &len);\n    if (err == 0) {\n        if (addr.ss_family == AF_INET) {\n            struct sockaddr_in *s = (struct sockaddr_in *)&addr;\n            inet_ntop(AF_INET, &s->sin_addr, peer_name, INET_ADDRSTRLEN);\n        } else if (addr.ss_family == AF_INET6) {\n            struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;\n            inet_ntop(AF_INET6, &s->sin6_addr, peer_name, INET6_ADDRSTRLEN);\n        }\n    } else {\n        return NULL;\n    }\n    return peer_name;\n}\n\nstatic void\nstop_server(EV_P_ server_t *server)\n{\n    server->stage = STAGE_STOP;\n}\n\n#ifdef USE_NFTABLES\nstruct nftbl_set_info {\n    uint32_t family;\n    char *table;\n    char *name;\n    uint32_t type;\n}* nftbl_badip_sets[16];\n\nstatic struct nftnl_set *\nnftbl_build_set(const char* table, const char* name, void* addr, size_t len)\n{\n    struct nftnl_set *set = nftnl_set_alloc();\n    if (set == NULL) return NULL;\n    nftnl_set_set_str(set, NFTNL_SET_TABLE, table);\n    nftnl_set_set_str(set, NFTNL_SET_NAME, name);\n\n    struct nftnl_set_elem *elem = nftnl_set_elem_alloc();\n    if (elem == NULL) {\n        nftnl_set_free(set);\n        return NULL;\n    }\n    nftnl_set_elem_set(elem, NFTNL_SET_ELEM_KEY, addr, len);\n    nftnl_set_elem_add(set, elem);\n    return set;\n}\n\nstatic uint32_t\nnftbl_build_nlmsg(void* buf, size_t *len, uint32_t family,\n                  struct nftnl_set *set)\n{\n    uint32_t seq = time(NULL);\n    struct nlmsghdr *nlh;\n    struct mnl_nlmsg_batch *batch = mnl_nlmsg_batch_start(buf, *len);\n    nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq);\n    mnl_nlmsg_batch_next(batch);\n    nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),\n                                NFT_MSG_NEWSETELEM, family,\n                                NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK,\n                                ++seq);\n    nftnl_set_elems_nlmsg_build_payload(nlh, set);\n    mnl_nlmsg_batch_next(batch);\n    nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq + 1);\n    mnl_nlmsg_batch_next(batch);\n    *len = mnl_nlmsg_batch_size(batch);\n    mnl_nlmsg_batch_stop(batch);\n    return seq;\n}\n\nstatic int\nnftbl_send_request(void *request, size_t len, uint32_t seq,\n                   mnl_cb_t cb, void *data)\n{\n    struct mnl_socket *nl = mnl_socket_open(NETLINK_NETFILTER);\n    if (nl == NULL) return -1;\n\n    int ret = -1;\n    uint8_t buf[MNL_SOCKET_BUFFER_SIZE];\n    if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) == 0 &&\n        mnl_socket_sendto(nl, request, len) >= 0) {\n        uint32_t portid = mnl_socket_get_portid(nl);\n        while ((ret = mnl_socket_recvfrom(nl, buf, sizeof(buf))) > 0) {\n            ret = mnl_cb_run(buf, ret, seq, portid, cb, data);\n            if (ret != MNL_CB_OK)\n                break;\n        }\n        mnl_socket_close(nl);\n    }\n    return ret;\n}\n\nstatic void\nnftbl_report_addr(const struct sockaddr* addr)\n{\n    uint32_t type;\n    void* data;\n    size_t size;\n    if (addr->sa_family == AF_INET) {\n        type = TYPE_IPADDR;\n        data = &((struct sockaddr_in*)addr)->sin_addr;\n        size = sizeof(struct in_addr);\n    } else if (addr->sa_family == AF_INET6) {\n        type = TYPE_IP6ADDR;\n        data = &((struct sockaddr_in6*)addr)->sin6_addr;\n        size = sizeof(struct in6_addr);\n    } else {\n        return;\n    }\n\n    char buf[MNL_SOCKET_BUFFER_SIZE];\n    for (int i = 0; nftbl_badip_sets[i]; ++i) {\n        struct nftbl_set_info* si = nftbl_badip_sets[i];\n        struct nftnl_set *set;\n        if (si->type == type &&\n            (set = nftbl_build_set(si->table, si->name, data, size))) {\n            size_t len = sizeof(buf);\n            uint32_t seq = nftbl_build_nlmsg(buf, &len, si->family, set);\n            nftnl_set_free(set);\n            if (nftbl_send_request(buf, len, seq, NULL, NULL) < 0 &&\n                errno != EEXIST)\n                ERROR(\"nftbl_report_addr\");\n        }\n    }\n}\n\nstatic int\nnftbl_check_cb(const struct nlmsghdr *nlh, void *data)\n{\n    struct nftnl_set *set = (struct nftnl_set*)data;\n    if (nftnl_set_nlmsg_parse(nlh, set) < 0)\n        return MNL_CB_ERROR;\n\n    uint32_t type = nftnl_set_get_u32(set, NFTNL_SET_KEY_TYPE);\n    if (type != TYPE_IPADDR && type != TYPE_IP6ADDR)\n        return MNL_CB_OK;\n\n    uint32_t len;\n    const char *name = nftnl_set_get_data(set, NFTNL_SET_NAME, &len);\n    for (int i = 0; nftbl_badip_sets[i]; ++i) {\n        struct nftbl_set_info* si = nftbl_badip_sets[i];\n        if (!memcmp(name, si->name, len)) {\n            name = nftnl_set_get_data(set, NFTNL_SET_TABLE, &len);\n            if (!si->table) {\n                size_t l = strlen(si->name) + 1;\n                si = realloc(si, sizeof(*si) + l + len);\n                si->name = (char*)(si + 1);\n                si->table = memcpy(si->name + l, name, len);\n                nftbl_badip_sets[i] = si;\n            } else if (memcmp(name, si->table, len)) {\n                continue;  /* table name not match */\n            }\n            si->family = nftnl_set_get_u32(set, NFTNL_SET_FAMILY);\n            si->type = type;\n        }\n    }\n    return MNL_CB_OK;\n}\n\nstatic int\nnftbl_check(void)\n{\n    struct nftnl_set *set = nftnl_set_alloc();\n    if (!set) return -1;\n\n    int ret;\n    char buf[MNL_SOCKET_BUFFER_SIZE];\n    uint32_t seq = time(NULL);\n    struct nlmsghdr *nlh;\n    nlh = nftnl_set_nlmsg_build_hdr(buf, NFT_MSG_GETSET, NFPROTO_UNSPEC,\n                                    NLM_F_DUMP|NLM_F_ACK, seq);\n    nftnl_set_nlmsg_build_payload(nlh, set);\n    ret = nftbl_send_request(nlh, nlh->nlmsg_len, seq, nftbl_check_cb, set);\n    nftnl_set_free(set);\n    if (ret < 0) return ret;\n\n    for (int i = 0; nftbl_badip_sets[i]; ++i) {\n        struct nftbl_set_info* si = nftbl_badip_sets[i];\n        if (si->family == NFPROTO_UNSPEC) {\n            if (si->table)\n                LOGE(\"set '%s' not found in table '%s'\", si->name, si->table);\n            else\n                LOGE(\"set '%s' not found\", si->name);\n            ret = -1;\n        }\n    }\n    if (ret < 0)\n        FATAL(\"Check nftables configuration.\");\n    return ret;\n}\n\nstatic int\nnftbl_init(const char* set_str)\n{\n    struct nftbl_set_info* si;\n    const char *p0 = set_str, *p = p0, *d = NULL;\n    int i = 0;\n    do {\n        if (*p == ':') {\n            d = p;\n        } else if (*p == ',' || *p == '\\0') {\n            size_t l = p - p0 + 1;\n            si = malloc(sizeof(*si) + l);\n            memset(si, 0, sizeof(*si));\n            si->name = memcpy(si + 1, p0, l);\n            si->name[l - 1] = '\\0';\n            if (d) {\n                si->table = si->name;\n                si->name = si->table + (d - p0);\n                *(si->name++) = '\\0';\n                d = NULL;\n            }\n            nftbl_badip_sets[i++] = si;\n            if (i == sizeof(nftbl_badip_sets) / sizeof(*si) - 1)\n                break;\n            while (*p && isspace(*(++p)));\n            p0 = p;\n        }\n    } while (*(p++));\n    return nftbl_check();\n}\n#endif\n\nstatic void\nreport_addr(int fd, const char *info)\n{\n    char *peer_name;\n    peer_name = get_peer_name(fd);\n    if (peer_name != NULL) {\n        LOGE(\"failed to handshake with %s: %s\", peer_name, info);\n    }\n\n#ifdef USE_NFTABLES\n    struct sockaddr_in6 addr;\n    socklen_t len = sizeof(struct sockaddr_in6);\n    if (!getpeername(fd, (struct sockaddr *)&addr, &len))\n        nftbl_report_addr((struct sockaddr *)&addr);\n#endif\n}\n\nint\nsetfastopen(int fd)\n{\n    int s = 0;\n#ifdef TCP_FASTOPEN\n    if (fast_open) {\n#if defined(__APPLE__) || defined(__MINGW32__)\n        int opt = 1;\n#else\n        int opt = 5;\n#endif\n        s = setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &opt, sizeof(opt));\n\n        if (s == -1) {\n            if (errno == EPROTONOSUPPORT || errno == ENOPROTOOPT) {\n                LOGE(\"fast open is not supported on this platform\");\n                fast_open = 0;\n            } else {\n                ERROR(\"setsockopt\");\n            }\n        }\n    }\n#endif\n    return s;\n}\n\n#ifndef __MINGW32__\nint\nsetnonblocking(int fd)\n{\n    int flags;\n    if (-1 == (flags = fcntl(fd, F_GETFL, 0))) {\n        flags = 0;\n    }\n    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);\n}\n\n#endif\n\nint\ncreate_and_bind(const char *host, const char *port, int mptcp)\n{\n    struct addrinfo hints;\n    struct addrinfo *result, *rp, *ipv4v6bindall;\n    int s, listen_sock = -1;\n\n    memset(&hints, 0, sizeof(struct addrinfo));\n    hints.ai_family   = AF_UNSPEC;               /* Return IPv4 and IPv6 choices */\n    hints.ai_socktype = SOCK_STREAM;             /* We want a TCP socket */\n    hints.ai_flags    = AI_PASSIVE | AI_ADDRCONFIG; /* For wildcard IP address */\n    hints.ai_protocol = IPPROTO_TCP;\n\n    result = NULL;\n\n    s = getaddrinfo(host, port, &hints, &result);\n\n    if (s != 0) {\n        LOGE(\"failed to resolve server name %s\", host);\n        return -1;\n    }\n\n    if (result == NULL) {\n        LOGE(\"Cannot bind\");\n        return -1;\n    }\n\n    rp = result;\n\n    /*\n     * On Linux, with net.ipv6.bindv6only = 0 (the default), getaddrinfo(NULL) with\n     * AI_PASSIVE returns 0.0.0.0 and :: (in this order). AI_PASSIVE was meant to\n     * return a list of addresses to listen on, but it is impossible to listen on\n     * 0.0.0.0 and :: at the same time, if :: implies dualstack mode.\n     */\n    if (!host) {\n        ipv4v6bindall = result;\n\n        /* Loop over all address infos found until a IPV6 address is found. */\n        while (ipv4v6bindall) {\n            if (ipv4v6bindall->ai_family == AF_INET6) {\n                rp = ipv4v6bindall; /* Take first IPV6 address available */\n                break;\n            }\n            ipv4v6bindall = ipv4v6bindall->ai_next; /* Get next address info, if any */\n        }\n    }\n\n    for (/*rp = result*/; rp != NULL; rp = rp->ai_next) {\n        int protocol = rp->ai_protocol;\n        if (mptcp < 0) {\n            protocol = IPPROTO_MPTCP; // Enable upstream MPTCP\n        }\n        listen_sock = socket(rp->ai_family, rp->ai_socktype, protocol);\n        if (listen_sock == -1) {\n            continue;\n        }\n\n        if (rp->ai_family == AF_INET6) {\n            int opt = host ? 1 : 0;\n            setsockopt(listen_sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));\n        }\n\n        int opt = 1;\n        setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));\n#ifdef SO_NOSIGPIPE\n        setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));\n#endif\n        if (reuse_port) {\n            int err = set_reuseport(listen_sock);\n            if (err == 0) {\n                LOGI(\"tcp port reuse enabled\");\n            }\n        }\n\n        // Enable out-of-tree mptcp\n        if (mptcp == 1) {\n            int i = 0;\n            while ((mptcp = mptcp_enabled_values[i]) > 0) {\n                int err = setsockopt(listen_sock, IPPROTO_TCP, mptcp, &opt, sizeof(opt));\n                if (err != -1) {\n                    break;\n                }\n                i++;\n            }\n            if (mptcp == 0) {\n                ERROR(\"failed to enable out-of-tree multipath TCP\");\n            }\n        }\n\n        s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);\n        if (s == 0) {\n            /* We managed to bind successfully! */\n            break;\n        } else {\n            ERROR(\"bind\");\n            FATAL(\"failed to bind address\");\n        }\n\n        close(listen_sock);\n        listen_sock = -1;\n    }\n\n    freeaddrinfo(result);\n\n    return listen_sock;\n}\n\nstatic remote_t *\nconnect_to_remote(EV_P_ struct addrinfo *res,\n                  server_t *server)\n{\n    int sockfd;\n#ifdef SET_INTERFACE\n    const char *iface = server->listen_ctx->iface;\n#endif\n\n    if (acl) {\n        char ipstr[INET6_ADDRSTRLEN];\n        memset(ipstr, 0, INET6_ADDRSTRLEN);\n\n        if (res->ai_addr->sa_family == AF_INET) {\n            struct sockaddr_in s;\n            memcpy(&s, res->ai_addr, sizeof(struct sockaddr_in));\n            inet_ntop(AF_INET, &s.sin_addr, ipstr, INET_ADDRSTRLEN);\n        } else if (res->ai_addr->sa_family == AF_INET6) {\n            struct sockaddr_in6 s;\n            memcpy(&s, res->ai_addr, sizeof(struct sockaddr_in6));\n            inet_ntop(AF_INET6, &s.sin6_addr, ipstr, INET6_ADDRSTRLEN);\n        }\n\n        if (outbound_block_match_host(ipstr) == 1) {\n            if (verbose)\n                LOGI(\"outbound blocked %s\", ipstr);\n            return NULL;\n        }\n    }\n\n    // initialize remote socks\n    sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);\n    if (sockfd == -1) {\n        ERROR(\"socket\");\n        close(sockfd);\n        return NULL;\n    }\n\n    int opt = 1;\n    setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n#ifdef SO_NOSIGPIPE\n    setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));\n#endif\n    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));\n\n    if (tcp_outgoing_sndbuf > 0) {\n        setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &tcp_outgoing_sndbuf, sizeof(int));\n    }\n\n    if (tcp_outgoing_rcvbuf > 0) {\n        setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &tcp_outgoing_rcvbuf, sizeof(int));\n    }\n\n    // setup remote socks\n\n    if (setnonblocking(sockfd) == -1)\n        ERROR(\"setnonblocking\");\n\n    if (is_bind_local_addr) {\n        struct sockaddr_storage *local_addr =\n            res->ai_family == AF_INET ? &local_addr_v4 : &local_addr_v6;\n        if (res->ai_family == local_addr->ss_family) {\n            if (bind_to_addr(local_addr, sockfd) == -1) {\n                ERROR(\"bind_to_addr\");\n                FATAL(\"cannot bind socket\");\n                return NULL;\n            }\n        }\n    }\n\n#ifdef SET_INTERFACE\n    if (iface) {\n        if (setinterface(sockfd, iface) == -1) {\n            ERROR(\"setinterface\");\n            close(sockfd);\n            return NULL;\n        }\n    }\n#endif\n\n    remote_t *remote = new_remote(sockfd);\n\n    if (fast_open) {\n#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT)\n        int s = -1;\n        s = sendto(sockfd, server->buf->data + server->buf->idx, server->buf->len,\n                   MSG_FASTOPEN, res->ai_addr, res->ai_addrlen);\n#elif defined(TCP_FASTOPEN_WINSOCK)\n        DWORD s   = -1;\n        DWORD err = 0;\n        do {\n            int optval = 1;\n            // Set fast open option\n            if (setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN,\n                           &optval, sizeof(optval)) != 0) {\n                ERROR(\"setsockopt\");\n                break;\n            }\n            // Load ConnectEx function\n            LPFN_CONNECTEX ConnectEx = winsock_getconnectex();\n            if (ConnectEx == NULL) {\n                LOGE(\"Cannot load ConnectEx() function\");\n                err = WSAENOPROTOOPT;\n                break;\n            }\n            // ConnectEx requires a bound socket\n            if (winsock_dummybind(sockfd, res->ai_addr) != 0) {\n                ERROR(\"bind\");\n                break;\n            }\n            // Call ConnectEx to send data\n            memset(&remote->olap, 0, sizeof(remote->olap));\n            remote->connect_ex_done = 0;\n            if (ConnectEx(sockfd, res->ai_addr, res->ai_addrlen,\n                          server->buf->data + server->buf->idx,\n                          server->buf->len, &s, &remote->olap)) {\n                remote->connect_ex_done = 1;\n                break;\n            }\n            // XXX: ConnectEx pending, check later in remote_send\n            if (WSAGetLastError() == ERROR_IO_PENDING) {\n                err = CONNECT_IN_PROGRESS;\n                break;\n            }\n            ERROR(\"ConnectEx\");\n        } while (0);\n        // Set error number\n        if (err) {\n            SetLastError(err);\n        }\n#else\n        int s = -1;\n#if defined(TCP_FASTOPEN_CONNECT)\n        int optval = 1;\n        if (setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,\n                       (void *)&optval, sizeof(optval)) < 0)\n            FATAL(\"failed to set TCP_FASTOPEN_CONNECT\");\n        s = connect(sockfd, res->ai_addr, res->ai_addrlen);\n#elif defined(CONNECT_DATA_IDEMPOTENT)\n        struct sockaddr_in sa;\n        memcpy(&sa, res->ai_addr, sizeof(struct sockaddr_in));\n        sa.sin_len = sizeof(struct sockaddr_in);\n        sa_endpoints_t endpoints;\n        memset((char *)&endpoints, 0, sizeof(endpoints));\n        endpoints.sae_dstaddr    = (struct sockaddr *)&sa;\n        endpoints.sae_dstaddrlen = res->ai_addrlen;\n\n        s = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY, CONNECT_DATA_IDEMPOTENT,\n                     NULL, 0, NULL, NULL);\n#else\n        FATAL(\"fast open is not enabled in this build\");\n#endif\n        if (s == 0)\n            s = send(sockfd, server->buf->data + server->buf->idx, server->buf->len, 0);\n#endif\n        if (s == -1) {\n            if (errno == CONNECT_IN_PROGRESS) {\n                // The remote server doesn't support tfo or it's the first connection to the server.\n                // It will automatically fall back to conventional TCP.\n            } else if (errno == EOPNOTSUPP || errno == EPROTONOSUPPORT ||\n                       errno == ENOPROTOOPT) {\n                // Disable fast open as it's not supported\n                fast_open = 0;\n                LOGE(\"fast open is not supported on this platform\");\n            } else {\n                ERROR(\"fast_open_connect\");\n            }\n        } else {\n            server->buf->idx += s;\n            server->buf->len -= s;\n        }\n    }\n\n    if (!fast_open) {\n        int r = connect(sockfd, res->ai_addr, res->ai_addrlen);\n\n        if (r == -1 && errno != CONNECT_IN_PROGRESS) {\n            ERROR(\"connect\");\n            close_and_free_remote(EV_A_ remote);\n            return NULL;\n        }\n    }\n\n    return remote;\n}\n\n#ifdef USE_NFCONNTRACK_TOS\nint\nsetMarkDscpCallback(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data)\n{\n    server_t *server            = (server_t *)data;\n    struct dscptracker *tracker = server->tracker;\n\n    tracker->mark = nfct_get_attr_u32(ct, ATTR_MARK);\n    if ((tracker->mark & 0xff00) == MARK_MASK_PREFIX) {\n        // Extract DSCP value from mark value\n        tracker->dscp = tracker->mark & 0x00ff;\n        int tos = (tracker->dscp) << 2;\n        if (setsockopt(server->fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) != 0) {\n            ERROR(\"iptable setsockopt IP_TOS\");\n        }\n    }\n    return NFCT_CB_CONTINUE;\n}\n\nvoid\nconntrackQuery(server_t *server)\n{\n    struct dscptracker *tracker = server->tracker;\n    if (tracker && tracker->ct) {\n        // Trying query mark from nf conntrack\n        struct nfct_handle *h = nfct_open(CONNTRACK, 0);\n        if (h) {\n            nfct_callback_register(h, NFCT_T_ALL, setMarkDscpCallback, (void *)server);\n            int x = nfct_query(h, NFCT_Q_GET, tracker->ct);\n            if (x == -1) {\n                LOGE(\"QOS: Failed to retrieve connection mark %s\", strerror(errno));\n            }\n            nfct_close(h);\n        } else {\n            LOGE(\"QOS: Failed to open conntrack handle for upstream netfilter mark retrieval.\");\n        }\n    }\n}\n\nvoid\nsetTosFromConnmark(remote_t *remote, server_t *server)\n{\n    if (server->tracker && server->tracker->ct) {\n        if (server->tracker->mark == 0 && server->tracker->packet_count < MARK_MAX_PACKET) {\n            server->tracker->packet_count++;\n            conntrackQuery(server);\n        }\n    } else {\n        socklen_t len;\n        struct sockaddr_storage sin;\n        len = sizeof(sin);\n        if (getpeername(remote->fd, (struct sockaddr *)&sin, &len) == 0) {\n            struct sockaddr_storage from_addr;\n            len = sizeof from_addr;\n            if (getsockname(remote->fd, (struct sockaddr *)&from_addr, &len) == 0) {\n                if ((server->tracker = (struct dscptracker *)ss_malloc(sizeof(struct dscptracker)))) {\n                    if ((server->tracker->ct = nfct_new())) {\n                        // Build conntrack query SELECT\n                        if (from_addr.ss_family == AF_INET) {\n                            struct sockaddr_in *src = (struct sockaddr_in *)&from_addr;\n                            struct sockaddr_in *dst = (struct sockaddr_in *)&sin;\n\n                            nfct_set_attr_u8(server->tracker->ct, ATTR_L3PROTO, AF_INET);\n                            nfct_set_attr_u32(server->tracker->ct, ATTR_IPV4_DST, dst->sin_addr.s_addr);\n                            nfct_set_attr_u32(server->tracker->ct, ATTR_IPV4_SRC, src->sin_addr.s_addr);\n                            nfct_set_attr_u16(server->tracker->ct, ATTR_PORT_DST, dst->sin_port);\n                            nfct_set_attr_u16(server->tracker->ct, ATTR_PORT_SRC, src->sin_port);\n                        } else if (from_addr.ss_family == AF_INET6) {\n                            struct sockaddr_in6 *src = (struct sockaddr_in6 *)&from_addr;\n                            struct sockaddr_in6 *dst = (struct sockaddr_in6 *)&sin;\n\n                            nfct_set_attr_u8(server->tracker->ct, ATTR_L3PROTO, AF_INET6);\n                            nfct_set_attr(server->tracker->ct, ATTR_IPV6_DST, dst->sin6_addr.s6_addr);\n                            nfct_set_attr(server->tracker->ct, ATTR_IPV6_SRC, src->sin6_addr.s6_addr);\n                            nfct_set_attr_u16(server->tracker->ct, ATTR_PORT_DST, dst->sin6_port);\n                            nfct_set_attr_u16(server->tracker->ct, ATTR_PORT_SRC, src->sin6_port);\n                        }\n                        nfct_set_attr_u8(server->tracker->ct, ATTR_L4PROTO, IPPROTO_TCP);\n                        conntrackQuery(server);\n                    } else {\n                        LOGE(\"Failed to allocate new conntrack for upstream netfilter mark retrieval.\");\n                        server->tracker->ct = NULL;\n                    }\n                }\n            }\n        }\n    }\n}\n\n#endif\n\nstatic void\nserver_recv_cb(EV_P_ ev_io *w, int revents)\n{\n    server_ctx_t *server_recv_ctx = (server_ctx_t *)w;\n    server_t *server              = server_recv_ctx->server;\n    remote_t *remote              = NULL;\n\n    buffer_t *buf = server->buf;\n\n    if (server->stage == STAGE_STREAM) {\n        remote = server->remote;\n        buf    = remote->buf;\n\n        // Only timer the watcher if a valid connection is established\n        ev_timer_again(EV_A_ & server->recv_ctx->watcher);\n    }\n\n    ssize_t r = recv(server->fd, buf->data, SOCKET_BUF_SIZE, 0);\n\n    if (r == 0) {\n        // connection closed\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else if (r == -1) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) {\n            // no data\n            // continue to wait for recv\n            return;\n        } else {\n            ERROR(\"server recv\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    }\n\n    // Ignore any new packet if the server is stopped\n    if (server->stage == STAGE_STOP) {\n        return;\n    }\n\n    tx      += r;\n    buf->len = r;\n\n    int err = crypto->decrypt(buf, server->d_ctx, SOCKET_BUF_SIZE);\n\n    if (err == CRYPTO_ERROR) {\n        report_addr(server->fd, \"authentication error\");\n        stop_server(EV_A_ server);\n        return;\n    } else if (err == CRYPTO_NEED_MORE) {\n        if (server->stage != STAGE_STREAM) {\n            server->frag++;\n        }\n        return;\n    }\n\n    // handshake and transmit data\n    if (server->stage == STAGE_STREAM) {\n        int s = send(remote->fd, remote->buf->data, remote->buf->len, 0);\n        if (s == -1) {\n            if (errno == EAGAIN || errno == EWOULDBLOCK) {\n                // no data, wait for send\n                remote->buf->idx = 0;\n                ev_io_stop(EV_A_ & server_recv_ctx->io);\n                ev_io_start(EV_A_ & remote->send_ctx->io);\n            } else {\n                ERROR(\"server_recv_send\");\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n            }\n        } else if (s < remote->buf->len) {\n            remote->buf->len -= s;\n            remote->buf->idx  = s;\n            ev_io_stop(EV_A_ & server_recv_ctx->io);\n            ev_io_start(EV_A_ & remote->send_ctx->io);\n        }\n        return;\n    } else if (server->stage == STAGE_INIT) {\n        /*\n         * Shadowsocks TCP Relay Header:\n         *\n         *    +------+----------+----------+\n         *    | ATYP | DST.ADDR | DST.PORT |\n         *    +------+----------+----------+\n         *    |  1   | Variable |    2     |\n         *    +------+----------+----------+\n         *\n         */\n\n        int offset     = 0;\n        int need_query = 0;\n        char atyp      = server->buf->data[offset++];\n        char host[255] = { 0 };\n        uint16_t port  = 0;\n        struct addrinfo info;\n        struct sockaddr_storage storage;\n        memset(&info, 0, sizeof(struct addrinfo));\n        memset(&storage, 0, sizeof(struct sockaddr_storage));\n\n        // get remote addr and port\n        if ((atyp & ADDRTYPE_MASK) == 1) {\n            // IP V4\n            struct sockaddr_in *addr = (struct sockaddr_in *)&storage;\n            size_t in_addr_len       = sizeof(struct in_addr);\n            addr->sin_family = AF_INET;\n            if (server->buf->len >= in_addr_len + 3) {\n                memcpy(&addr->sin_addr, server->buf->data + offset, in_addr_len);\n                inet_ntop(AF_INET, (const void *)(server->buf->data + offset),\n                          host, INET_ADDRSTRLEN);\n                offset += in_addr_len;\n            } else {\n                report_addr(server->fd, \"invalid length for ipv4 address\");\n                stop_server(EV_A_ server);\n                return;\n            }\n            memcpy(&addr->sin_port, server->buf->data + offset, sizeof(uint16_t));\n            info.ai_family   = AF_INET;\n            info.ai_socktype = SOCK_STREAM;\n            info.ai_protocol = IPPROTO_TCP;\n            info.ai_addrlen  = sizeof(struct sockaddr_in);\n            info.ai_addr     = (struct sockaddr *)addr;\n        } else if ((atyp & ADDRTYPE_MASK) == 3) {\n            // Domain name\n            uint8_t name_len = *(uint8_t *)(server->buf->data + offset);\n            if (name_len + 4 <= server->buf->len) {\n                memcpy(host, server->buf->data + offset + 1, name_len);\n                offset += name_len + 1;\n            } else {\n                report_addr(server->fd, \"invalid host name length\");\n                stop_server(EV_A_ server);\n                return;\n            }\n            if (acl && outbound_block_match_host(host) == 1) {\n                if (verbose)\n                    LOGI(\"outbound blocked %s\", host);\n                close_and_free_server(EV_A_ server);\n                return;\n            }\n            struct cork_ip ip;\n            if (cork_ip_init(&ip, host) != -1) {\n                info.ai_socktype = SOCK_STREAM;\n                info.ai_protocol = IPPROTO_TCP;\n                if (ip.version == 4) {\n                    struct sockaddr_in *addr = (struct sockaddr_in *)&storage;\n                    inet_pton(AF_INET, host, &(addr->sin_addr));\n                    memcpy(&addr->sin_port, server->buf->data + offset, sizeof(uint16_t));\n                    addr->sin_family = AF_INET;\n                    info.ai_family   = AF_INET;\n                    info.ai_addrlen  = sizeof(struct sockaddr_in);\n                    info.ai_addr     = (struct sockaddr *)addr;\n                } else if (ip.version == 6) {\n                    struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&storage;\n                    inet_pton(AF_INET6, host, &(addr->sin6_addr));\n                    memcpy(&addr->sin6_port, server->buf->data + offset, sizeof(uint16_t));\n                    addr->sin6_family = AF_INET6;\n                    info.ai_family    = AF_INET6;\n                    info.ai_addrlen   = sizeof(struct sockaddr_in6);\n                    info.ai_addr      = (struct sockaddr *)addr;\n                }\n            } else {\n                if (!validate_hostname(host, name_len)) {\n                    report_addr(server->fd, \"invalid host name\");\n                    stop_server(EV_A_ server);\n                    return;\n                }\n                need_query = 1;\n            }\n        } else if ((atyp & ADDRTYPE_MASK) == 4) {\n            // IP V6\n            struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&storage;\n            size_t in6_addr_len       = sizeof(struct in6_addr);\n            addr->sin6_family = AF_INET6;\n            if (server->buf->len >= in6_addr_len + 3) {\n                memcpy(&addr->sin6_addr, server->buf->data + offset, in6_addr_len);\n                inet_ntop(AF_INET6, (const void *)(server->buf->data + offset),\n                          host, INET6_ADDRSTRLEN);\n                offset += in6_addr_len;\n            } else {\n                LOGE(\"invalid header with addr type %d\", atyp);\n                report_addr(server->fd, \"invalid length for ipv6 address\");\n                stop_server(EV_A_ server);\n                return;\n            }\n            memcpy(&addr->sin6_port, server->buf->data + offset, sizeof(uint16_t));\n            info.ai_family   = AF_INET6;\n            info.ai_socktype = SOCK_STREAM;\n            info.ai_protocol = IPPROTO_TCP;\n            info.ai_addrlen  = sizeof(struct sockaddr_in6);\n            info.ai_addr     = (struct sockaddr *)addr;\n        }\n\n        if (offset == 1) {\n            report_addr(server->fd, \"invalid address type\");\n            stop_server(EV_A_ server);\n            return;\n        }\n\n        port = ntohs(load16_be(server->buf->data + offset));\n\n        offset += 2;\n\n        if (server->buf->len < offset) {\n            report_addr(server->fd, \"invalid request length\");\n            stop_server(EV_A_ server);\n            return;\n        } else {\n            server->buf->len -= offset;\n            server->buf->idx = offset;\n        }\n\n        if (verbose) {\n            if ((atyp & ADDRTYPE_MASK) == 4)\n                LOGI(\"[%s] connect to [%s]:%d\", remote_port, host, ntohs(port));\n            else\n                LOGI(\"[%s] connect to %s:%d\", remote_port, host, ntohs(port));\n        }\n\n        if (!need_query) {\n            remote_t *remote = connect_to_remote(EV_A_ & info, server);\n\n            if (remote == NULL) {\n                LOGE(\"connect error\");\n                close_and_free_server(EV_A_ server);\n                return;\n            } else {\n                server->remote = remote;\n                remote->server = server;\n\n                // XXX: should handle buffer carefully\n                if (server->buf->len > 0) {\n                    brealloc(remote->buf, server->buf->len, SOCKET_BUF_SIZE);\n                    memcpy(remote->buf->data, server->buf->data + server->buf->idx,\n                           server->buf->len);\n                    remote->buf->len = server->buf->len;\n                    remote->buf->idx = 0;\n                    server->buf->len = 0;\n                    server->buf->idx = 0;\n                }\n\n                // waiting on remote connected event\n                ev_io_stop(EV_A_ & server_recv_ctx->io);\n                ev_io_start(EV_A_ & remote->send_ctx->io);\n            }\n        } else {\n            ev_io_stop(EV_A_ & server_recv_ctx->io);\n\n            query_t *query = ss_malloc(sizeof(query_t));\n            memset(query, 0, sizeof(query_t));\n            query->server = server;\n            server->query = query;\n            snprintf(query->hostname, MAX_HOSTNAME_LEN, \"%s\", host);\n\n            server->stage = STAGE_RESOLVE;\n            resolv_start(host, port, resolv_cb, resolv_free_cb, query);\n        }\n\n        return;\n    }\n    // should not reach here\n    FATAL(\"server context error\");\n}\n\nstatic void\nserver_send_cb(EV_P_ ev_io *w, int revents)\n{\n    server_ctx_t *server_send_ctx = (server_ctx_t *)w;\n    server_t *server              = server_send_ctx->server;\n    remote_t *remote              = server->remote;\n\n    if (remote == NULL) {\n        LOGE(\"invalid server\");\n        close_and_free_server(EV_A_ server);\n        return;\n    }\n\n    if (server->buf->len == 0) {\n        // close and free\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else {\n        // has data to send\n        ssize_t s = send(server->fd, server->buf->data + server->buf->idx,\n                         server->buf->len, 0);\n        if (s == -1) {\n            if (errno != EAGAIN && errno != EWOULDBLOCK) {\n                ERROR(\"server_send_send\");\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n            }\n            return;\n        } else if (s < server->buf->len) {\n            // partly sent, move memory, wait for the next time to send\n            server->buf->len -= s;\n            server->buf->idx += s;\n            return;\n        } else {\n            // all sent out, wait for reading\n            server->buf->len = 0;\n            server->buf->idx = 0;\n            ev_io_stop(EV_A_ & server_send_ctx->io);\n            if (remote != NULL) {\n                ev_io_start(EV_A_ & remote->recv_ctx->io);\n                return;\n            } else {\n                LOGE(\"invalid remote\");\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n                return;\n            }\n        }\n    }\n}\n\nstatic void\nserver_timeout_cb(EV_P_ ev_timer *watcher, int revents)\n{\n    server_ctx_t *server_ctx\n        = cork_container_of(watcher, server_ctx_t, watcher);\n    server_t *server = server_ctx->server;\n    remote_t *remote = server->remote;\n\n    if (verbose) {\n        LOGI(\"TCP connection timeout\");\n    }\n\n    close_and_free_remote(EV_A_ remote);\n    close_and_free_server(EV_A_ server);\n}\n\nstatic void\nresolv_free_cb(void *data)\n{\n    query_t *query = (query_t *)data;\n\n    if (query != NULL) {\n        if (query->server != NULL)\n            query->server->query = NULL;\n        ss_free(query);\n    }\n}\n\nstatic void\nresolv_cb(struct sockaddr *addr, void *data)\n{\n    query_t *query   = (query_t *)data;\n    server_t *server = query->server;\n\n    if (server == NULL)\n        return;\n\n    struct ev_loop *loop = server->listen_ctx->loop;\n\n    if (addr == NULL) {\n        LOGE(\"unable to resolve %s\", query->hostname);\n        close_and_free_server(EV_A_ server);\n    } else {\n        if (verbose) {\n            LOGI(\"successfully resolved %s\", query->hostname);\n        }\n\n        struct addrinfo info;\n        memset(&info, 0, sizeof(struct addrinfo));\n        info.ai_socktype = SOCK_STREAM;\n        info.ai_protocol = IPPROTO_TCP;\n        info.ai_addr     = addr;\n\n        if (addr->sa_family == AF_INET) {\n            info.ai_family  = AF_INET;\n            info.ai_addrlen = sizeof(struct sockaddr_in);\n        } else if (addr->sa_family == AF_INET6) {\n            info.ai_family  = AF_INET6;\n            info.ai_addrlen = sizeof(struct sockaddr_in6);\n        }\n\n        remote_t *remote = connect_to_remote(EV_A_ & info, server);\n\n        if (remote == NULL) {\n            close_and_free_server(EV_A_ server);\n        } else {\n            server->remote = remote;\n            remote->server = server;\n\n            // XXX: should handle buffer carefully\n            if (server->buf->len > 0) {\n                brealloc(remote->buf, server->buf->len, SOCKET_BUF_SIZE);\n                memcpy(remote->buf->data, server->buf->data + server->buf->idx,\n                       server->buf->len);\n                remote->buf->len = server->buf->len;\n                remote->buf->idx = 0;\n                server->buf->len = 0;\n                server->buf->idx = 0;\n            }\n\n            // listen to remote connected event\n            ev_io_start(EV_A_ & remote->send_ctx->io);\n        }\n    }\n}\n\nstatic void\nremote_recv_cb(EV_P_ ev_io *w, int revents)\n{\n    remote_ctx_t *remote_recv_ctx = (remote_ctx_t *)w;\n    remote_t *remote              = remote_recv_ctx->remote;\n    server_t *server              = remote->server;\n\n    if (server == NULL) {\n        LOGE(\"invalid server\");\n        close_and_free_remote(EV_A_ remote);\n        return;\n    }\n\n    ev_timer_again(EV_A_ & server->recv_ctx->watcher);\n\n    ssize_t r = recv(remote->fd, server->buf->data, SOCKET_BUF_SIZE, 0);\n\n    if (r == 0) {\n        // connection closed\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else if (r == -1) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) {\n            // no data\n            // continue to wait for recv\n            return;\n        } else {\n            ERROR(\"remote recv\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    }\n\n    rx += r;\n\n    // Ignore any new packet if the server is stopped\n    if (server->stage == STAGE_STOP) {\n        return;\n    }\n\n    server->buf->len = r;\n    int err = crypto->encrypt(server->buf, server->e_ctx, SOCKET_BUF_SIZE);\n\n    if (err) {\n        LOGE(\"invalid password or cipher\");\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    }\n\n#ifdef USE_NFCONNTRACK_TOS\n    setTosFromConnmark(remote, server);\n#endif\n    int s = send(server->fd, server->buf->data, server->buf->len, 0);\n\n    if (s == -1) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) {\n            // no data, wait for send\n            server->buf->idx = 0;\n            ev_io_stop(EV_A_ & remote_recv_ctx->io);\n            ev_io_start(EV_A_ & server->send_ctx->io);\n        } else {\n            ERROR(\"remote_recv_send\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    } else if (s < server->buf->len) {\n        server->buf->len -= s;\n        server->buf->idx  = s;\n        ev_io_stop(EV_A_ & remote_recv_ctx->io);\n        ev_io_start(EV_A_ & server->send_ctx->io);\n    }\n\n    // Disable TCP_NODELAY after the first response are sent\n    if (!remote->recv_ctx->connected && !no_delay) {\n        int opt = 0;\n        setsockopt(server->fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n        setsockopt(remote->fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n    }\n    remote->recv_ctx->connected = 1;\n}\n\nstatic void\nremote_send_cb(EV_P_ ev_io *w, int revents)\n{\n    remote_ctx_t *remote_send_ctx = (remote_ctx_t *)w;\n    remote_t *remote              = remote_send_ctx->remote;\n    server_t *server              = remote->server;\n\n    if (server == NULL) {\n        LOGE(\"invalid server\");\n        close_and_free_remote(EV_A_ remote);\n        return;\n    }\n\n    if (!remote_send_ctx->connected) {\n#ifdef TCP_FASTOPEN_WINSOCK\n        if (fast_open) {\n            // Check if ConnectEx is done\n            if (!remote->connect_ex_done) {\n                DWORD numBytes;\n                DWORD flags;\n                // Non-blocking way to fetch ConnectEx result\n                if (WSAGetOverlappedResult(remote->fd, &remote->olap,\n                                           &numBytes, FALSE, &flags)) {\n                    remote->buf->len       -= numBytes;\n                    remote->buf->idx        = numBytes;\n                    remote->connect_ex_done = 1;\n                } else if (WSAGetLastError() == WSA_IO_INCOMPLETE) {\n                    // XXX: ConnectEx still not connected, wait for next time\n                    return;\n                } else {\n                    ERROR(\"WSAGetOverlappedResult\");\n                    // not connected\n                    close_and_free_remote(EV_A_ remote);\n                    close_and_free_server(EV_A_ server);\n                    return;\n                }\n            }\n\n            // Make getpeername work\n            if (setsockopt(remote->fd, SOL_SOCKET,\n                           SO_UPDATE_CONNECT_CONTEXT, NULL, 0) != 0) {\n                ERROR(\"setsockopt\");\n            }\n        }\n#endif\n        struct sockaddr_storage addr;\n        socklen_t len = sizeof(struct sockaddr_storage);\n        memset(&addr, 0, len);\n\n        int r = getpeername(remote->fd, (struct sockaddr *)&addr, &len);\n\n        if (r == 0) {\n            remote_send_ctx->connected = 1;\n\n            if (remote->buf->len == 0) {\n                server->stage = STAGE_STREAM;\n                ev_io_stop(EV_A_ & remote_send_ctx->io);\n                ev_io_start(EV_A_ & server->recv_ctx->io);\n                ev_io_start(EV_A_ & remote->recv_ctx->io);\n                return;\n            }\n        } else {\n            ERROR(\"getpeername\");\n            // not connected\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    }\n\n    if (remote->buf->len == 0) {\n        // close and free\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else {\n        // has data to send\n        ssize_t s = send(remote->fd, remote->buf->data + remote->buf->idx,\n                         remote->buf->len, 0);\n        if (s == -1) {\n            if (errno != EAGAIN && errno != EWOULDBLOCK) {\n                ERROR(\"remote_send_send\");\n                // close and free\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n            }\n            return;\n        } else if (s < remote->buf->len) {\n            // partly sent, move memory, wait for the next time to send\n            remote->buf->len -= s;\n            remote->buf->idx += s;\n            return;\n        } else {\n            // all sent out, wait for reading\n            remote->buf->len = 0;\n            remote->buf->idx = 0;\n            ev_io_stop(EV_A_ & remote_send_ctx->io);\n            if (server != NULL) {\n                ev_io_start(EV_A_ & server->recv_ctx->io);\n                if (server->stage != STAGE_STREAM) {\n                    server->stage = STAGE_STREAM;\n                    ev_io_start(EV_A_ & remote->recv_ctx->io);\n                }\n            } else {\n                LOGE(\"invalid server\");\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n            }\n            return;\n        }\n    }\n}\n\nstatic remote_t *\nnew_remote(int fd)\n{\n    if (verbose) {\n        remote_conn++;\n        LOGI(\"new connection to remote, %d opened remote connections\", remote_conn);\n    }\n\n    remote_t *remote = ss_malloc(sizeof(remote_t));\n    memset(remote, 0, sizeof(remote_t));\n\n    remote->recv_ctx = ss_malloc(sizeof(remote_ctx_t));\n    remote->send_ctx = ss_malloc(sizeof(remote_ctx_t));\n    remote->buf      = ss_malloc(sizeof(buffer_t));\n    balloc(remote->buf, SOCKET_BUF_SIZE);\n    memset(remote->recv_ctx, 0, sizeof(remote_ctx_t));\n    memset(remote->send_ctx, 0, sizeof(remote_ctx_t));\n    remote->fd                  = fd;\n    remote->recv_ctx->remote    = remote;\n    remote->recv_ctx->connected = 0;\n    remote->send_ctx->remote    = remote;\n    remote->send_ctx->connected = 0;\n    remote->server              = NULL;\n\n    ev_io_init(&remote->recv_ctx->io, remote_recv_cb, fd, EV_READ);\n    ev_io_init(&remote->send_ctx->io, remote_send_cb, fd, EV_WRITE);\n\n    return remote;\n}\n\nstatic void\nfree_remote(remote_t *remote)\n{\n    if (remote->server != NULL) {\n        remote->server->remote = NULL;\n    }\n    if (remote->buf != NULL) {\n        bfree(remote->buf);\n        ss_free(remote->buf);\n    }\n    ss_free(remote->recv_ctx);\n    ss_free(remote->send_ctx);\n    ss_free(remote);\n}\n\nstatic void\nclose_and_free_remote(EV_P_ remote_t *remote)\n{\n    if (remote != NULL) {\n        ev_io_stop(EV_A_ & remote->send_ctx->io);\n        ev_io_stop(EV_A_ & remote->recv_ctx->io);\n        close(remote->fd);\n        free_remote(remote);\n        if (verbose) {\n            remote_conn--;\n            LOGI(\"close a connection to remote, %d opened remote connections\", remote_conn);\n        }\n    }\n}\n\nstatic server_t *\nnew_server(int fd, listen_ctx_t *listener)\n{\n    if (verbose) {\n        server_conn++;\n        LOGI(\"new connection from client, %d opened client connections\", server_conn);\n    }\n\n    server_t *server;\n    server = ss_malloc(sizeof(server_t));\n\n    memset(server, 0, sizeof(server_t));\n\n    server->recv_ctx = ss_malloc(sizeof(server_ctx_t));\n    server->send_ctx = ss_malloc(sizeof(server_ctx_t));\n    server->buf      = ss_malloc(sizeof(buffer_t));\n    memset(server->recv_ctx, 0, sizeof(server_ctx_t));\n    memset(server->send_ctx, 0, sizeof(server_ctx_t));\n    balloc(server->buf, SOCKET_BUF_SIZE);\n    server->fd                  = fd;\n    server->recv_ctx->server    = server;\n    server->recv_ctx->connected = 0;\n    server->send_ctx->server    = server;\n    server->send_ctx->connected = 0;\n    server->stage               = STAGE_INIT;\n    server->frag                = 0;\n    server->query               = NULL;\n    server->listen_ctx          = listener;\n    server->remote              = NULL;\n\n    server->e_ctx = ss_malloc(sizeof(cipher_ctx_t));\n    server->d_ctx = ss_malloc(sizeof(cipher_ctx_t));\n    crypto->ctx_init(crypto->cipher, server->e_ctx, 1);\n    crypto->ctx_init(crypto->cipher, server->d_ctx, 0);\n\n    int timeout = max(MIN_TCP_IDLE_TIMEOUT, server->listen_ctx->timeout);\n    ev_io_init(&server->recv_ctx->io, server_recv_cb, fd, EV_READ);\n    ev_io_init(&server->send_ctx->io, server_send_cb, fd, EV_WRITE);\n    ev_timer_init(&server->recv_ctx->watcher, server_timeout_cb,\n                  timeout, timeout);\n\n    cork_dllist_add(&connections, &server->entries);\n\n    return server;\n}\n\nstatic void\nfree_server(server_t *server)\n{\n#ifdef USE_NFCONNTRACK_TOS\n    if (server->tracker) {\n        struct dscptracker *tracker = server->tracker;\n        struct nf_conntrack *ct     = server->tracker->ct;\n        server->tracker = NULL;\n        if (ct) {\n            nfct_destroy(ct);\n        }\n        free(tracker);\n    }\n#endif\n    cork_dllist_remove(&server->entries);\n\n    if (server->remote != NULL) {\n        server->remote->server = NULL;\n    }\n    if (server->e_ctx != NULL) {\n        crypto->ctx_release(server->e_ctx);\n        ss_free(server->e_ctx);\n    }\n    if (server->d_ctx != NULL) {\n        crypto->ctx_release(server->d_ctx);\n        ss_free(server->d_ctx);\n    }\n    if (server->buf != NULL) {\n        bfree(server->buf);\n        ss_free(server->buf);\n    }\n\n    ss_free(server->recv_ctx);\n    ss_free(server->send_ctx);\n    ss_free(server);\n}\n\nstatic void\nclose_and_free_server(EV_P_ server_t *server)\n{\n    if (server != NULL) {\n        if (server->query != NULL) {\n            server->query->server = NULL;\n            server->query         = NULL;\n        }\n        ev_io_stop(EV_A_ & server->send_ctx->io);\n        ev_io_stop(EV_A_ & server->recv_ctx->io);\n        ev_timer_stop(EV_A_ & server->recv_ctx->watcher);\n        close(server->fd);\n        free_server(server);\n        if (verbose) {\n            server_conn--;\n            LOGI(\"close a connection from client, %d opened client connections\", server_conn);\n        }\n    }\n}\n\nstatic void\nsignal_cb(EV_P_ ev_signal *w, int revents)\n{\n    if (revents & EV_SIGNAL) {\n        switch (w->signum) {\n#ifndef __MINGW32__\n        case SIGCHLD:\n            if (!is_plugin_running()) {\n                LOGE(\"plugin service exit unexpectedly\");\n                ret_val = -1;\n            } else\n                return;\n#endif\n        case SIGINT:\n        case SIGTERM:\n            ev_signal_stop(EV_DEFAULT, &sigint_watcher);\n            ev_signal_stop(EV_DEFAULT, &sigterm_watcher);\n#ifndef __MINGW32__\n            ev_signal_stop(EV_DEFAULT, &sigchld_watcher);\n#else\n            ev_io_stop(EV_DEFAULT, &plugin_watcher.io);\n#endif\n            ev_unloop(EV_A_ EVUNLOOP_ALL);\n        }\n    }\n}\n\n#ifdef __MINGW32__\nstatic void\nplugin_watcher_cb(EV_P_ ev_io *w, int revents)\n{\n    char buf[1];\n    SOCKET fd = accept(plugin_watcher.fd, NULL, NULL);\n    if (fd == INVALID_SOCKET) {\n        return;\n    }\n    recv(fd, buf, 1, 0);\n    closesocket(fd);\n    LOGE(\"plugin service exit unexpectedly\");\n    ret_val = -1;\n    ev_signal_stop(EV_DEFAULT, &sigint_watcher);\n    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);\n    ev_io_stop(EV_DEFAULT, &plugin_watcher.io);\n    ev_unloop(EV_A_ EVUNLOOP_ALL);\n}\n\n#endif\n\nstatic void\naccept_cb(EV_P_ ev_io *w, int revents)\n{\n    listen_ctx_t *listener = (listen_ctx_t *)w;\n    int serverfd           = accept(listener->fd, NULL, NULL);\n    if (serverfd == -1) {\n        ERROR(\"accept\");\n        return;\n    }\n\n    char *peer_name = get_peer_name(serverfd);\n    if (peer_name != NULL) {\n        if (acl) {\n            if ((get_acl_mode() == BLACK_LIST && acl_match_host(peer_name) == 1)\n                || (get_acl_mode() == WHITE_LIST && acl_match_host(peer_name) >= 0)) {\n                LOGE(\"Access denied from %s\", peer_name);\n                close(serverfd);\n                return;\n            }\n        }\n    }\n\n    int opt = 1;\n    setsockopt(serverfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n#ifdef SO_NOSIGPIPE\n    setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));\n#endif\n\n    if (tcp_incoming_sndbuf > 0) {\n        setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &tcp_incoming_sndbuf, sizeof(int));\n    }\n\n    if (tcp_incoming_rcvbuf > 0) {\n        setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &tcp_incoming_rcvbuf, sizeof(int));\n    }\n\n    setnonblocking(serverfd);\n\n    server_t *server = new_server(serverfd, listener);\n    ev_io_start(EV_A_ & server->recv_ctx->io);\n    ev_timer_start(EV_A_ & server->recv_ctx->watcher);\n}\n\nint\nmain(int argc, char **argv)\n{\n    int i, c;\n    int pid_flags   = 0;\n    int mptcp       = 0;\n    int mtu         = 0;\n    char *user      = NULL;\n    char *password  = NULL;\n    char *key       = NULL;\n    char *timeout   = NULL;\n    char *method    = NULL;\n    char *pid_path  = NULL;\n    char *conf_path = NULL;\n    char *iface     = NULL;\n\n    char *server_port = NULL;\n    char *plugin_opts = NULL;\n    char *plugin_host = NULL;\n    char *plugin_port = NULL;\n    char tmp_port[8];\n    char *nameservers = NULL;\n\n    int server_num = 0;\n    ss_addr_t server_addr[MAX_REMOTE_NUM];\n    memset(server_addr, 0, sizeof(ss_addr_t) * MAX_REMOTE_NUM);\n    memset(&local_addr_v4, 0, sizeof(struct sockaddr_storage));\n    memset(&local_addr_v6, 0, sizeof(struct sockaddr_storage));\n\n    static struct option long_options[] = {\n        { \"fast-open\",       no_argument,       NULL, GETOPT_VAL_FAST_OPEN   },\n        { \"reuse-port\",      no_argument,       NULL, GETOPT_VAL_REUSE_PORT  },\n        { \"tcp-incoming-sndbuf\", required_argument, NULL, GETOPT_VAL_TCP_INCOMING_SNDBUF },\n        { \"tcp-incoming-rcvbuf\", required_argument, NULL, GETOPT_VAL_TCP_INCOMING_RCVBUF },\n        { \"tcp-outgoing-sndbuf\", required_argument, NULL, GETOPT_VAL_TCP_OUTGOING_SNDBUF },\n        { \"tcp-outgoing-rcvbuf\", required_argument, NULL, GETOPT_VAL_TCP_OUTGOING_RCVBUF },\n        { \"no-delay\",        no_argument,       NULL, GETOPT_VAL_NODELAY     },\n        { \"acl\",             required_argument, NULL, GETOPT_VAL_ACL         },\n        { \"manager-address\", required_argument, NULL,\n          GETOPT_VAL_MANAGER_ADDRESS },\n        { \"mtu\",             required_argument, NULL, GETOPT_VAL_MTU         },\n        { \"help\",            no_argument,       NULL, GETOPT_VAL_HELP        },\n        { \"plugin\",          required_argument, NULL, GETOPT_VAL_PLUGIN      },\n        { \"plugin-opts\",     required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },\n        { \"password\",        required_argument, NULL, GETOPT_VAL_PASSWORD    },\n        { \"key\",             required_argument, NULL, GETOPT_VAL_KEY         },\n#ifdef __linux__\n        { \"mptcp\",           no_argument,       NULL, GETOPT_VAL_MPTCP       },\n#ifdef USE_NFTABLES\n        { \"nftables-sets\",   required_argument, NULL, GETOPT_VAL_NFTABLES_SETS },\n#endif\n#endif\n        { NULL,              0,                 NULL, 0                      }\n    };\n\n    opterr = 0;\n\n    USE_TTY();\n\n    while ((c = getopt_long(argc, argv, \"f:s:p:l:k:t:m:b:c:i:d:a:n:huUv6A\",\n                            long_options, NULL)) != -1) {\n        switch (c) {\n        case GETOPT_VAL_FAST_OPEN:\n            fast_open = 1;\n            break;\n        case GETOPT_VAL_NODELAY:\n            no_delay = 1;\n            LOGI(\"enable TCP no-delay\");\n            break;\n        case GETOPT_VAL_ACL:\n            LOGI(\"initializing acl...\");\n            acl = !init_acl(optarg);\n            break;\n        case GETOPT_VAL_MANAGER_ADDRESS:\n            manager_addr = optarg;\n            break;\n        case GETOPT_VAL_MTU:\n            mtu = atoi(optarg);\n            LOGI(\"set MTU to %d\", mtu);\n            break;\n        case GETOPT_VAL_PLUGIN:\n            plugin = optarg;\n            break;\n        case GETOPT_VAL_PLUGIN_OPTS:\n            plugin_opts = optarg;\n            break;\n        case GETOPT_VAL_MPTCP:\n            mptcp = get_mptcp(1);\n            if (mptcp)\n                LOGI(\"enable multipath TCP (%s)\", mptcp > 0 ? \"out-of-tree\" : \"upstream\");\n            break;\n        case GETOPT_VAL_KEY:\n            key = optarg;\n            break;\n        case GETOPT_VAL_REUSE_PORT:\n            reuse_port = 1;\n            break;\n        case GETOPT_VAL_TCP_INCOMING_SNDBUF:\n            tcp_incoming_sndbuf = atoi(optarg);\n            break;\n        case GETOPT_VAL_TCP_INCOMING_RCVBUF:\n            tcp_incoming_rcvbuf = atoi(optarg);\n            break;\n        case GETOPT_VAL_TCP_OUTGOING_SNDBUF:\n            tcp_outgoing_sndbuf = atoi(optarg);\n            break;\n        case GETOPT_VAL_TCP_OUTGOING_RCVBUF:\n            tcp_outgoing_rcvbuf = atoi(optarg);\n            break;\n#ifdef USE_NFTABLES\n        case GETOPT_VAL_NFTABLES_SETS:\n            nftbl_init(optarg);\n            break;\n#endif\n        case 's':\n            if (server_num < MAX_REMOTE_NUM) {\n                parse_addr(optarg, &server_addr[server_num++]);\n            }\n            break;\n        case 'b':\n            is_bind_local_addr += parse_local_addr(&local_addr_v4, &local_addr_v6, optarg);\n            break;\n        case 'p':\n            server_port = optarg;\n            break;\n        case GETOPT_VAL_PASSWORD:\n        case 'k':\n            password = optarg;\n            break;\n        case 'f':\n            pid_flags = 1;\n            pid_path  = optarg;\n            break;\n        case 't':\n            timeout = optarg;\n            break;\n        case 'm':\n            method = optarg;\n            break;\n        case 'c':\n            conf_path = optarg;\n            break;\n        case 'i':\n            iface = optarg;\n            break;\n        case 'd':\n            nameservers = optarg;\n            break;\n        case 'a':\n            user = optarg;\n            break;\n#ifdef HAVE_SETRLIMIT\n        case 'n':\n            nofile = atoi(optarg);\n            break;\n#endif\n        case 'u':\n            mode = TCP_AND_UDP;\n            break;\n        case 'U':\n            mode = UDP_ONLY;\n            break;\n        case 'v':\n            verbose = 1;\n            break;\n        case GETOPT_VAL_HELP:\n        case 'h':\n            usage();\n            exit(EXIT_SUCCESS);\n        case '6':\n            ipv6first = 1;\n            break;\n        case 'A':\n            FATAL(\"One time auth has been deprecated. Try AEAD ciphers instead.\");\n            break;\n        case '?':\n            // The option character is not recognized.\n            LOGE(\"Unrecognized option: %s\", optarg);\n            opterr = 1;\n            break;\n        }\n    }\n\n    if (opterr) {\n        usage();\n        exit(EXIT_FAILURE);\n    }\n\n    if (argc == 1) {\n        if (conf_path == NULL) {\n            conf_path = get_default_conf();\n        }\n    }\n\n    if (conf_path != NULL) {\n        jconf_t *conf = read_jconf(conf_path);\n        if (server_num == 0) {\n            server_num = conf->remote_num;\n            for (i = 0; i < server_num; i++)\n                server_addr[i] = conf->remote_addr[i];\n        }\n        if (server_port == NULL) {\n            server_port = conf->remote_port;\n        }\n        if (password == NULL) {\n            password = conf->password;\n        }\n        if (key == NULL) {\n            key = conf->key;\n        }\n        if (method == NULL) {\n            method = conf->method;\n        }\n        if (timeout == NULL) {\n            timeout = conf->timeout;\n        }\n        if (user == NULL) {\n            user = conf->user;\n        }\n        if (plugin == NULL) {\n            plugin = conf->plugin;\n        }\n        if (plugin_opts == NULL) {\n            plugin_opts = conf->plugin_opts;\n        }\n        if (mode == TCP_ONLY) {\n            mode = conf->mode;\n        }\n        if (mtu == 0) {\n            mtu = conf->mtu;\n        }\n        if (mptcp == 0) {\n            mptcp = conf->mptcp;\n        }\n        if (no_delay == 0) {\n            no_delay = conf->no_delay;\n        }\n        if (reuse_port == 0) {\n            reuse_port = conf->reuse_port;\n        }\n        if (tcp_incoming_sndbuf == 0) {\n            tcp_incoming_sndbuf = conf->tcp_incoming_sndbuf;\n        }\n        if (tcp_incoming_rcvbuf == 0) {\n            tcp_incoming_rcvbuf = conf->tcp_incoming_rcvbuf;\n        }\n        if (tcp_outgoing_sndbuf == 0) {\n            tcp_outgoing_sndbuf = conf->tcp_outgoing_sndbuf;\n        }\n        if (tcp_outgoing_rcvbuf == 0) {\n            tcp_outgoing_rcvbuf = conf->tcp_outgoing_rcvbuf;\n        }\n        if (fast_open == 0) {\n            fast_open = conf->fast_open;\n        }\n        if (is_bind_local_addr == 0) {\n            is_bind_local_addr += parse_local_addr(&local_addr_v4, &local_addr_v6, conf->local_addr);\n        }\n        if (is_bind_local_addr == 0) {\n            is_bind_local_addr += parse_local_addr(&local_addr_v4, &local_addr_v6, conf->local_addr_v4);\n            is_bind_local_addr += parse_local_addr(&local_addr_v4, &local_addr_v6, conf->local_addr_v6);\n        }\n#ifdef HAVE_SETRLIMIT\n        if (nofile == 0) {\n            nofile = conf->nofile;\n        }\n#endif\n        if (nameservers == NULL) {\n            nameservers = conf->nameserver;\n        }\n        if (ipv6first == 0) {\n            ipv6first = conf->ipv6_first;\n        }\n        if (acl == 0 && conf->acl != NULL) {\n            LOGI(\"initializing acl...\");\n            acl = !init_acl(conf->acl);\n        }\n    }\n\n    if (tcp_incoming_sndbuf != 0 && tcp_incoming_sndbuf < SOCKET_BUF_SIZE) {\n        tcp_incoming_sndbuf = 0;\n    }\n\n    if (tcp_incoming_sndbuf != 0) {\n        LOGI(\"set TCP incoming connection send buffer size to %d\", tcp_incoming_sndbuf);\n    }\n\n    if (tcp_incoming_rcvbuf != 0 && tcp_incoming_rcvbuf < SOCKET_BUF_SIZE) {\n        tcp_incoming_rcvbuf = 0;\n    }\n\n    if (tcp_incoming_rcvbuf != 0) {\n        LOGI(\"set TCP incoming connection receive buffer size to %d\", tcp_incoming_rcvbuf);\n    }\n\n    if (tcp_outgoing_sndbuf != 0 && tcp_outgoing_sndbuf < SOCKET_BUF_SIZE) {\n        tcp_outgoing_sndbuf = 0;\n    }\n\n    if (tcp_outgoing_sndbuf != 0) {\n        LOGI(\"set TCP outgoing connection send buffer size to %d\", tcp_outgoing_sndbuf);\n    }\n\n    if (tcp_outgoing_rcvbuf != 0 && tcp_outgoing_rcvbuf < SOCKET_BUF_SIZE) {\n        tcp_outgoing_rcvbuf = 0;\n    }\n\n    if (tcp_outgoing_rcvbuf != 0) {\n        LOGI(\"set TCP outgoing connection receive buffer size to %d\", tcp_outgoing_rcvbuf);\n    }\n\n    if (server_num == 0) {\n        server_addr[server_num++].host = \"0.0.0.0\";\n    }\n\n    if (server_num == 0 || server_port == NULL\n        || (password == NULL && key == NULL)) {\n        usage();\n        exit(EXIT_FAILURE);\n    }\n\n    if (is_ipv6only(server_addr, server_num, ipv6first)) {\n        plugin_host = \"::1\";\n    } else {\n        plugin_host = \"127.0.0.1\";\n    }\n\n    remote_port = server_port;\n\n#ifdef __MINGW32__\n    winsock_init();\n#endif\n\n    if (plugin != NULL) {\n        uint16_t port = get_local_port();\n        if (port == 0) {\n            FATAL(\"failed to find a free port\");\n        }\n        snprintf(tmp_port, 8, \"%d\", port);\n        plugin_port = server_port;\n        server_port = tmp_port;\n\n#ifdef __MINGW32__\n        memset(&plugin_watcher, 0, sizeof(plugin_watcher));\n        plugin_watcher.port = get_local_port();\n        if (plugin_watcher.port == 0) {\n            LOGE(\"failed to assign a control port for plugin\");\n        }\n#endif\n    }\n\n    if (method == NULL) {\n        method = \"chacha20-ietf-poly1305\";\n    }\n\n    if (timeout == NULL) {\n        timeout = \"60\";\n    }\n\n#ifdef HAVE_SETRLIMIT\n    /*\n     * no need to check the return value here since we will show\n     * the user an error message if setrlimit(2) fails\n     */\n    if (nofile > 1024) {\n        if (verbose) {\n            LOGI(\"setting NOFILE to %d\", nofile);\n        }\n        set_nofile(nofile);\n    }\n#endif\n\n    USE_SYSLOG(argv[0], pid_flags);\n    if (pid_flags) {\n        daemonize(pid_path);\n    }\n\n    if (ipv6first) {\n        LOGI(\"resolving hostname to IPv6 address first\");\n    }\n\n    if (fast_open == 1) {\n#ifdef TCP_FASTOPEN\n        LOGI(\"using tcp fast open\");\n#else\n        LOGE(\"tcp fast open is not supported by this environment\");\n        fast_open = 0;\n#endif\n    }\n\n    if (plugin != NULL) {\n        LOGI(\"plugin \\\"%s\\\" enabled\", plugin);\n    }\n\n    if (mode != TCP_ONLY) {\n        LOGI(\"UDP relay enabled\");\n    }\n\n    if (mode == UDP_ONLY) {\n        LOGI(\"TCP relay disabled\");\n    }\n\n    if (no_delay) {\n        LOGI(\"enable TCP no-delay\");\n    }\n\n#ifndef __MINGW32__\n    // ignore SIGPIPE\n    signal(SIGPIPE, SIG_IGN);\n    signal(SIGABRT, SIG_IGN);\n#endif\n\n    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);\n    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);\n    ev_signal_start(EV_DEFAULT, &sigint_watcher);\n    ev_signal_start(EV_DEFAULT, &sigterm_watcher);\n#ifndef __MINGW32__\n    ev_signal_init(&sigchld_watcher, signal_cb, SIGCHLD);\n    ev_signal_start(EV_DEFAULT, &sigchld_watcher);\n#endif\n\n    // setup keys\n    LOGI(\"initializing ciphers... %s\", method);\n    crypto = crypto_init(password, key, method);\n    if (crypto == NULL)\n        FATAL(\"failed to initialize ciphers\");\n\n    // initialize ev loop\n    struct ev_loop *loop = EV_DEFAULT;\n\n    // setup dns\n    resolv_init(loop, nameservers, ipv6first);\n\n    if (nameservers != NULL)\n        LOGI(\"using nameserver: %s\", nameservers);\n\n#ifdef __MINGW32__\n    // Listen on plugin control port\n    if (plugin != NULL && plugin_watcher.port != 0) {\n        SOCKET fd;\n        fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);\n        if (fd != INVALID_SOCKET) {\n            plugin_watcher.valid = 0;\n            do {\n                struct sockaddr_in addr;\n                memset(&addr, 0, sizeof(addr));\n                addr.sin_family      = AF_INET;\n                addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);\n                addr.sin_port        = htons(plugin_watcher.port);\n                if (bind(fd, (struct sockaddr *)&addr, sizeof(addr))) {\n                    LOGE(\"failed to bind plugin control port\");\n                    break;\n                }\n                if (listen(fd, 1)) {\n                    LOGE(\"failed to listen on plugin control port\");\n                    break;\n                }\n                plugin_watcher.fd = fd;\n                ev_io_init(&plugin_watcher.io, plugin_watcher_cb, fd, EV_READ);\n                ev_io_start(EV_DEFAULT, &plugin_watcher.io);\n                plugin_watcher.valid = 1;\n            } while (0);\n            if (!plugin_watcher.valid) {\n                closesocket(fd);\n                plugin_watcher.port = 0;\n            }\n        }\n    }\n#endif\n\n    // Start plugin server\n    if (plugin != NULL) {\n        int len          = 0;\n        size_t buf_size  = 256 * server_num;\n        char *server_str = ss_malloc(buf_size);\n\n        snprintf(server_str, buf_size, \"%s\", server_addr[0].host);\n        len = strlen(server_str);\n        for (int i = 1; i < server_num; i++) {\n            snprintf(server_str + len, buf_size - len, \"|%s\", server_addr[i].host);\n            len = strlen(server_str);\n        }\n\n        int err = start_plugin(plugin, plugin_opts, server_str,\n                               plugin_port, plugin_host, server_port,\n#ifdef __MINGW32__\n                               plugin_watcher.port,\n#endif\n                               MODE_SERVER);\n        if (err) {\n            ERROR(\"start_plugin\");\n            FATAL(\"failed to start the plugin\");\n        }\n    }\n\n    // initialize listen context\n    listen_ctx_t listen_ctx_list[server_num];\n\n    // bind to each interface\n    if (mode != UDP_ONLY) {\n        int num_listen_ctx = 0;\n        for (int i = 0; i < server_num; i++) {\n            const char *host = server_addr[i].host;\n            const char *port = server_addr[i].port ? server_addr[i].port : server_port;\n\n            if (plugin != NULL) {\n                host = plugin_host;\n            }\n\n            if (host && ss_is_ipv6addr(host))\n                LOGI(\"tcp server listening at [%s]:%s\", host, port);\n            else\n                LOGI(\"tcp server listening at %s:%s\", host ? host : \"0.0.0.0\", port);\n\n            // Bind to port\n            int listenfd;\n            listenfd = create_and_bind(host, port, mptcp);\n            if (listenfd == -1) {\n                continue;\n            }\n            if (listen(listenfd, SSMAXCONN) == -1) {\n                ERROR(\"listen()\");\n                continue;\n            }\n            setfastopen(listenfd);\n            setnonblocking(listenfd);\n            listen_ctx_t *listen_ctx = &listen_ctx_list[i];\n\n            // Setup proxy context\n            listen_ctx->timeout = atoi(timeout);\n            listen_ctx->fd      = listenfd;\n            listen_ctx->iface   = iface;\n            listen_ctx->loop    = loop;\n\n            ev_io_init(&listen_ctx->io, accept_cb, listenfd, EV_READ);\n            ev_io_start(loop, &listen_ctx->io);\n\n            num_listen_ctx++;\n\n            if (plugin != NULL)\n                break;\n        }\n\n        if (num_listen_ctx == 0) {\n            FATAL(\"failed to listen on any address\");\n        }\n    }\n\n    if (mode != TCP_ONLY) {\n        int num_listen_ctx = 0;\n        for (int i = 0; i < server_num; i++) {\n            const char *host = server_addr[i].host;\n            const char *port = server_addr[i].port ? server_addr[i].port : server_port;\n            if (plugin != NULL) {\n                port = plugin_port;\n            }\n            if (host && ss_is_ipv6addr(host))\n                LOGI(\"udp server listening at [%s]:%s\", host, port);\n            else\n                LOGI(\"udp server listening at %s:%s\", host ? host : \"0.0.0.0\", port);\n            // Setup UDP\n            int err = init_udprelay(host, port, mtu, crypto, atoi(timeout), iface);\n            if (err == -1)\n                continue;\n            num_listen_ctx++;\n        }\n\n        if (num_listen_ctx == 0) {\n            FATAL(\"failed to listen on any address\");\n        }\n    }\n\n#ifndef __MINGW32__\n    if (manager_addr != NULL) {\n        ev_timer_init(&stat_update_watcher, stat_update_cb, UPDATE_INTERVAL, UPDATE_INTERVAL);\n        ev_timer_start(EV_DEFAULT, &stat_update_watcher);\n    }\n#endif\n\n#ifndef __MINGW32__\n    // setuid\n    if (user != NULL && !run_as(user)) {\n        FATAL(\"failed to switch user\");\n    }\n\n    if (geteuid() == 0) {\n        LOGI(\"running from root user\");\n    }\n#endif\n\n    // Init connections\n    cork_dllist_init(&connections);\n\n    // start ev loop\n    ev_run(loop, 0);\n\n    if (verbose) {\n        LOGI(\"closed gracefully\");\n    }\n\n#ifndef __MINGW32__\n    if (manager_addr != NULL) {\n        ev_timer_stop(EV_DEFAULT, &stat_update_watcher);\n    }\n#endif\n\n    if (plugin != NULL) {\n        stop_plugin();\n    }\n\n    // Clean up\n\n    resolv_shutdown(loop);\n\n    for (int i = 0; i < server_num; i++) {\n        listen_ctx_t *listen_ctx = &listen_ctx_list[i];\n        if (mode != UDP_ONLY) {\n            ev_io_stop(loop, &listen_ctx->io);\n            close(listen_ctx->fd);\n        }\n        if (plugin != NULL)\n            break;\n    }\n\n    if (mode != UDP_ONLY) {\n        free_connections(loop);\n    }\n\n    if (mode != TCP_ONLY) {\n        free_udprelay();\n    }\n\n#ifdef __MINGW32__\n    if (plugin_watcher.valid) {\n        closesocket(plugin_watcher.fd);\n    }\n\n    winsock_cleanup();\n#endif\n\n    return ret_val;\n}\n"
  },
  {
    "path": "src/server.h",
    "content": "/*\n * server.h - Define shadowsocks server's buffers and callbacks\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _SERVER_H\n#define _SERVER_H\n\n#include <time.h>\n#include <libcork/ds.h>\n\n#ifdef HAVE_LIBEV_EV_H\n#include <libev/ev.h>\n#else\n#include <ev.h>\n#endif\n\n#ifdef __MINGW32__\n#include \"winsock.h\"\n#endif\n\n#include \"crypto.h\"\n#include \"jconf.h\"\n#include \"netutils.h\"\n\n#include \"common.h\"\n\ntypedef struct listen_ctx {\n    ev_io io;\n    int fd;\n    int timeout;\n    char *iface;\n    struct ev_loop *loop;\n} listen_ctx_t;\n\ntypedef struct server_ctx {\n    ev_io io;\n    ev_timer watcher;\n    int connected;\n    struct server *server;\n} server_ctx_t;\n\n#ifdef USE_NFCONNTRACK_TOS\n\n#include <libnetfilter_conntrack/libnetfilter_conntrack.h>\n#include <libnetfilter_conntrack/libnetfilter_conntrack_tcp.h>\n\nstruct dscptracker {\n    struct nf_conntrack *ct;\n    long unsigned int mark;\n    unsigned int dscp;\n    unsigned int packet_count;\n};\n\n#endif\n\nstruct query;\n\ntypedef struct server {\n    int fd;\n    int stage;\n    int frag;\n\n    buffer_t *buf;\n\n    cipher_ctx_t *e_ctx;\n    cipher_ctx_t *d_ctx;\n    struct server_ctx *recv_ctx;\n    struct server_ctx *send_ctx;\n    struct listen_ctx *listen_ctx;\n    struct remote *remote;\n\n    struct query *query;\n\n    struct cork_dllist_item entries;\n#ifdef USE_NFCONNTRACK_TOS\n    struct dscptracker *tracker;\n#endif\n} server_t;\n\ntypedef struct query {\n    server_t *server;\n    char hostname[MAX_HOSTNAME_LEN];\n} query_t;\n\ntypedef struct remote_ctx {\n    ev_io io;\n    int connected;\n    struct remote *remote;\n} remote_ctx_t;\n\ntypedef struct remote {\n    int fd;\n#ifdef TCP_FASTOPEN_WINSOCK\n    OVERLAPPED olap;\n    int connect_ex_done;\n#endif\n    buffer_t *buf;\n    struct remote_ctx *recv_ctx;\n    struct remote_ctx *send_ctx;\n    struct server *server;\n} remote_t;\n\n#endif // _SERVER_H\n"
  },
  {
    "path": "src/shadowsocks.h",
    "content": "/*\n * shadowsocks.h - Header files of library interfaces\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _SHADOWSOCKS_H\n#define _SHADOWSOCKS_H\n\ntypedef struct {\n    /*  Required  */\n    char *remote_host;    // hostname or ip of remote server\n    char *local_addr;     // local ip to bind\n    char *method;         // encryption method\n    char *password;       // password of remote server\n    int remote_port;      // port number of remote server\n    int local_port;       // port number of local server\n    int timeout;          // connection timeout\n\n    /*  Optional, set NULL if not valid   */\n    char *acl;            // file path to acl\n    char *log;            // file path to log\n    int fast_open;        // enable tcp fast open\n    int mode;             // enable udp relay\n    int mtu;              // MTU of interface\n    int mptcp;            // enable multipath TCP\n    int verbose;          // verbose mode\n} profile_t;\n\n/* An example profile\n *\n * const profile_t EXAMPLE_PROFILE = {\n *  .remote_host = \"example.com\",\n *  .local_addr = \"127.0.0.1\",\n *  .method = \"bf-cfb\",\n *  .password = \"barfoo!\",\n *  .remote_port = 8338,\n *  .local_port = 1080,\n *  .timeout = 600;\n *  .acl = NULL,\n *  .log = NULL,\n *  .fast_open = 0,\n *  .mode = 0,\n *  .verbose = 0\n * };\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef void (*ss_local_callback)(int socks_fd, int udp_fd, void *data);\n\n/*\n * Create and start a shadowsocks local server.\n *\n * Calling this function will block the current thread forever if the server\n * starts successfully.\n *\n * Make sure start the server in a separate process to avoid any potential\n * memory and socket leak.\n *\n * If failed, -1 is returned. Errors will output to the log file.\n */\nint start_ss_local_server(profile_t profile);\n\n/*\n * Create and start a shadowsocks local server, specifying a callback.\n *\n * The callback is invoked when the local server has started successfully. It passes the SOCKS\n * server and UDP relay file descriptors, along with any supplied user data.\n *\n * Returns -1 on failure.\n */\nint start_ss_local_server_with_callback(profile_t profile, ss_local_callback callback, void *udata);\n\n#ifdef __cplusplus\n}\n#endif\n\n// To stop the service on posix system, just kill the daemon process\n// kill(pid, SIGKILL);\n// Otherwise, If you start the service in a thread, you may need to send a signal SIGUSER1 to the thread.\n// pthread_kill(pthread_t, SIGUSR1);\n\n#endif // _SHADOWSOCKS_H\n"
  },
  {
    "path": "src/socks5.h",
    "content": "/*\n * socks5.h - Define SOCKS5's header\n *\n * Copyright (C) 2013, clowwindy <clowwindy42@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _SOCKS5_H\n#define _SOCKS5_H\n\n#define SVERSION 0x05\n#define METHOD_NOAUTH 0x00\n#define METHOD_UNACCEPTABLE 0xff\n\n// see also: https://www.ietf.org/rfc/rfc1928.txt\n#define SOCKS5_CMD_CONNECT 0x01\n#define SOCKS5_CMD_BIND 0x02\n#define SOCKS5_CMD_UDP_ASSOCIATE 0x03\n\n#define SOCKS5_ATYP_IPV4 0x01\n#define SOCKS5_ATYP_DOMAIN 0x03\n#define SOCKS5_ATYP_IPV6 0x04\n\n#define SOCKS5_REP_SUCCEEDED 0x00\n#define SOCKS5_REP_GENERAL 0x01\n#define SOCKS5_REP_CONN_DISALLOWED 0x02\n#define SOCKS5_REP_NETWORK_UNREACHABLE 0x03\n#define SOCKS5_REP_HOST_UNREACHABLE 0x04\n#define SOCKS5_REP_CONN_REFUSED 0x05\n#define SOCKS5_REP_TTL_EXPIRED 0x06\n#define SOCKS5_REP_CMD_NOT_SUPPORTED 0x07\n#define SOCKS5_REP_ADDRTYPE_NOT_SUPPORTED 0x08\n#define SOCKS5_REP_FF_UNASSIGNED 0x09\n\nstruct method_select_request {\n    unsigned char ver;\n    unsigned char nmethods;\n    unsigned char methods[0];\n} __attribute__((packed, aligned(1)));\n\nstruct method_select_response {\n    unsigned char ver;\n    unsigned char method;\n} __attribute__((packed, aligned(1)));\n\nstruct socks5_request {\n    unsigned char ver;\n    unsigned char cmd;\n    unsigned char rsv;\n    unsigned char atyp;\n} __attribute__((packed, aligned(1)));\n\nstruct socks5_response {\n    unsigned char ver;\n    unsigned char rep;\n    unsigned char rsv;\n    unsigned char atyp;\n} __attribute__((packed, aligned(1)));\n\n#endif // _SOCKS5_H\n"
  },
  {
    "path": "src/ss-nat",
    "content": "#!/bin/bash\n#\n# Copyright (C) 2015 OpenWrt-dist\n# Copyright (C) 2015 Jian Chang <aa65535@live.com>\n#\n# This is free software, licensed under the GNU General Public License v3.\n# See /LICENSE for more information.\n#\n\nTAG=\"SS_SPEC\"          # iptables tag\nIPT=\"iptables -t nat\"  # alias of iptables\nFWI=$(uci get firewall.shadowsocks.path 2>/dev/null)  # firewall include file\nIP_REGEX=\"^([0-9]{1,3}\\.){3}[0-9]{1,3}\"\t\t      # used to check if input is a valid IP\n\nusage() {\n\tcat <<-EOF\n\n    Copyright (C) 2015 OpenWrt-dist\n    Copyright (C) 2015 Jian Chang <aa65535@live.com>\n\n    Usage: ss-nat [options]\n\n    Valid options are:\n\n        -s <server_ip>          hostname (requires dig) or ip address of shadowsocks remote server\n        -l <local_port>         port number of shadowsocks local server\n        -S <server_ip>          hostname (requires dig) or ip address of shadowsocks remote UDP server\n        -L <local_port>         port number of shadowsocks local UDP server\n        -i <ip_list_file>       a file content is bypassed ip list\n        -I <interface>          lan interface of nat, default: eth0\n        -a <lan_ips>            lan ip of access control, need a prefix to\n        define access control mode\n        -b <wan_ips>            wan ip of will be bypassed\n        -w <wan_ips>            wan ip of will be forwarded\n        -e <extra_options>      extra options for iptables\n        -o                      apply the rules to the OUTPUT chain\n        -u                      enable udprelay mode, TPROXY is required\n        -U                      enable udprelay mode, using different IP\n        and ports for TCP and UDP\n        -f                      flush the rules\n        -h                      show this help message and exit\n\n    This is free software, licensed under the GNU General Public License v3.\n    See /LICENSE for more information.\n\nEOF\n\texit $1\n}\n\nloger() {\n\t# 1.alert 2.crit 3.err 4.warn 5.notice 6.info 7.debug\n\tlogger -st ss-nat[$$] -p$1 $2\n}\n\nflush_r() {\n\tiptables-save -c | grep -v \"$TAG\" | iptables-restore -c\n\tip rule del fwmark 0x01/0x01 table 100 2>/dev/null\n\tip route del local 0.0.0.0/0 dev lo table 100 2>/dev/null\n\tipset -X ss_spec_lan_ac 2>/dev/null\n\tipset -X ss_spec_wan_ac 2>/dev/null\n\t[ -n \"$FWI\" ] && echo '#!/bin/sh' >$FWI\n\treturn 0\n}\n\nipset_r() {\n\tipset -! -R <<-EOF || return 1\n\t\tcreate ss_spec_wan_ac hash:net\n\t\t$(gen_iplist | sed \"/^\\s*$/d\" | sed -e \"s/^/add ss_spec_wan_ac /\")\n\t\t$(for ip in $WAN_FW_IP; do echo \"add ss_spec_wan_ac $ip nomatch\"; done)\nEOF\n\t$IPT -N SS_SPEC_WAN_AC && \\\n\t$IPT -A SS_SPEC_WAN_AC -m set --match-set ss_spec_wan_ac dst -j RETURN && \\\n\t$IPT -A SS_SPEC_WAN_AC -j SS_SPEC_WAN_FW\n\treturn $?\n}\n\nfw_rule() {\n\t$IPT -N SS_SPEC_WAN_FW && \\\n\t$IPT -A SS_SPEC_WAN_FW -p tcp \\\n\t\t-j REDIRECT --to-ports $local_port 2>/dev/null || {\n\t\tloger 3 \"Can't redirect, please check the iptables.\"\n\t\texit 1\n\t}\n\treturn $?\n}\n\nac_rule() {\n\tif [ -n \"$LAN_AC_IP\" ]; then\n\t\tcase \"${LAN_AC_IP:0:1}\" in\n\t\t\tw|W)\n\t\t\t\tMATCH_SET=\"-m set --match-set ss_spec_lan_ac src\"\n\t\t\t\t;;\n\t\t\tb|B)\n\t\t\t\tMATCH_SET=\"-m set ! --match-set ss_spec_lan_ac src\"\n\t\t\t\t;;\n\t\t\t*)\n\t\t\t\tloger 3 \"Illegal argument \\`-a $LAN_AC_IP\\`.\"\n\t\t\t\treturn 2\n\t\t\t\t;;\n\t\tesac\n\tfi\n\tIFNAME=${IFNAME:-eth0}\n\tipset -! -R <<-EOF || return 1\n\t\tcreate ss_spec_lan_ac hash:net\n\t\t$(for ip in ${LAN_AC_IP:1}; do echo \"add ss_spec_lan_ac $ip\"; done)\nEOF\n\t$IPT -I PREROUTING 1 ${IFNAME:+-i $IFNAME} -p tcp $EXT_ARGS $MATCH_SET \\\n\t\t-j SS_SPEC_WAN_AC\n\tif [ \"$OUTPUT\" = 1 ]; then\n\t\t$IPT -I OUTPUT 1 -p tcp $EXT_ARGS -j SS_SPEC_WAN_AC\n\tfi\n\treturn $?\n}\n\ntp_rule() {\n\tlsmod | grep -q TPROXY || return 0\n\t[ -n \"$TPROXY\" ] || return 0\n\tip rule add fwmark 0x01/0x01 table 100\n\tip route add local 0.0.0.0/0 dev lo table 100\n\tlocal ipt=\"iptables -t mangle\"\n\t$ipt -N SS_SPEC_TPROXY\n\t$ipt -A SS_SPEC_TPROXY -p udp -m set ! --match-set ss_spec_wan_ac dst \\\n\t\t-j TPROXY --on-port \"$LOCAL_PORT\" --tproxy-mark 0x01/0x01\n\t$ipt -I PREROUTING 1 ${IFNAME:+-i $IFNAME} -p udp $EXT_ARGS $MATCH_SET \\\n\t\t-j SS_SPEC_TPROXY\n\treturn $?\n}\n\nget_wan_ip() {\n\tcat <<-EOF | grep -E $IP_REGEX\n\t\t$server\n\t\t$SERVER\n\t\t$WAN_BP_IP\nEOF\n}\n\ngen_iplist() {\n\tcat <<-EOF\n\t\t0.0.0.0/8\n\t\t10.0.0.0/8\n\t\t100.64.0.0/10\n\t\t127.0.0.0/8\n\t\t169.254.0.0/16\n\t\t172.16.0.0/12\n\t\t192.0.0.0/24\n\t\t192.0.2.0/24\n\t\t192.88.99.0/24\n\t\t192.168.0.0/16\n\t\t198.18.0.0/15\n\t\t198.51.100.0/24\n\t\t203.0.113.0/24\n\t\t224.0.0.0/4\n\t\t240.0.0.0/4\n\t\t255.255.255.255\n\t\t$(get_wan_ip)\n\t\t$(cat ${IGNORE_LIST:=/dev/null} 2>/dev/null)\nEOF\n}\n\ngen_include() {\n\t[ -n \"$FWI\" ] || return 0\n\tcat <<-EOF >>$FWI\n\tiptables-restore -n <<-EOT\n\t$(iptables-save | grep -E \"$TAG|^\\*|^COMMIT\" |\\\n\t\t\tsed -e \"s/^-A \\(OUTPUT\\|PREROUTING\\)/-I \\1 1/\")\n\tEOT\nEOF\n\treturn $?\n}\n\nwhile getopts \":s:l:S:L:i:I:e:a:b:w:ouUfh\" arg; do\n\tcase \"$arg\" in\n\t\ts)\n            if [[ $OPTARG =~ $IP_REGEX ]]\n            then\n                server=$OPTARG\n            else\n                server=$(ping -4 -q -c 1 -s 0 -W 1 -w 1 $OPTARG| head -n 1 | sed -n 's/[^(]*(\\([^)]*\\)).*/\\1/p')\n            fi\n\t\t\t;;\n\t\tl)\n\t\t\tlocal_port=$OPTARG\n\t\t\t;;\n\t\tS)\n            if [[ $OPTARG =~ $IP_REGEX ]]\n            then\n                SERVER=$OPTARG\n            else\n                SERVER=$(ping -4 -q -c 1 -s 0 -W 1 -w 1 $OPTARG| head -n 1 | sed -n 's/[^(]*(\\([^)]*\\)).*/\\1/p')\n            fi\n\t\t\t;;\n\t\tL)\n\t\t\tLOCAL_PORT=$OPTARG\n\t\t\t;;\n\t\ti)\n\t\t\tIGNORE_LIST=$OPTARG\n\t\t\t;;\n\t\tI)\n\t\t\tIFNAME=$OPTARG\n\t\t\t;;\n\t\te)\n\t\t\tEXT_ARGS=$OPTARG\n\t\t\t;;\n\t\ta)\n\t\t\tLAN_AC_IP=$OPTARG\n\t\t\t;;\n\t\tb)\n\t\t\tWAN_BP_IP=$(for ip in $OPTARG; do echo $ip; done)\n\t\t\t;;\n\t\tw)\n\t\t\tWAN_FW_IP=$OPTARG\n\t\t\t;;\n\t\to)\n\t\t\tOUTPUT=1\n\t\t\t;;\n\t\tu)\n\t\t\tTPROXY=1\n\t\t\t;;\n\t\tU)\n\t\t\tTPROXY=2\n\t\t\t;;\n\t\tf)\n\t\t\tflush_r\n\t\t\texit 0\n\t\t\t;;\n\t\th)\n\t\t\tusage 0\n\t\t\t;;\n\tesac\ndone\n\nif [ -z \"$server\" -o -z \"$local_port\" ]; then\n\tusage 2\nfi\n\nif [ \"$TPROXY\" = 1 ]; then\n\tSERVER=$server\n\tLOCAL_PORT=$local_port\nelif [ \"$TPROXY\" = 2 ]; then\n\t: ${SERVER:?\"You must assign an ip for the udp relay server.\"}\n\t: ${LOCAL_PORT:?\"You must assign a port for the udp relay server.\"}\nfi\n\nflush_r && fw_rule && ipset_r && ac_rule && tp_rule && gen_include\n[ \"$?\" = 0 ] || loger 3 \"Start failed!\"\nexit $?\n"
  },
  {
    "path": "src/stream.c",
    "content": "/*\n * stream.c - Manage stream ciphers\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <mbedtls/entropy.h>\n#include <mbedtls/ctr_drbg.h>\n#include <mbedtls/version.h>\n#define CIPHER_UNSUPPORTED \"unsupported\"\n\n#include <sodium.h>\n\n#include \"ppbloom.h\"\n#include \"stream.h\"\n#include \"utils.h\"\n\n#define SODIUM_BLOCK_SIZE   64\n\n/*\n * Spec: http://shadowsocks.org/en/spec/Stream-Ciphers.html\n *\n * Stream ciphers provide only confidentiality. Data integrity and authenticity is not guaranteed. Users should use AEAD\n * ciphers whenever possible.\n *\n * Stream Encryption/Decryption\n *\n * Stream_encrypt is a function that takes a secret key, an initialization vector, a message, and produces a ciphertext\n * with the same length as the message.\n *\n *      Stream_encrypt(key, IV, message) => ciphertext\n *\n * Stream_decrypt is a function that takes a secret key, an initializaiton vector, a ciphertext, and produces the\n * original message.\n *\n *      Stream_decrypt(key, IV, ciphertext) => message\n *\n * TCP\n *\n * A stream cipher encrypted TCP stream starts with a randomly generated initializaiton vector, followed by encrypted\n * payload data.\n *\n *      [IV][encrypted payload]\n *\n * UDP\n *\n * A stream cipher encrypted UDP packet has the following structure:\n *\n *      [IV][encrypted payload]\n *\n * Each UDP packet is encrypted/decrypted independently with a randomly generated initialization vector.\n *\n */\n\n#define NONE                -1\n#define TABLE               0\n#define RC4                 1\n#define RC4_MD5             2\n#define AES_128_CFB         3\n#define AES_192_CFB         4\n#define AES_256_CFB         5\n#define AES_128_CTR         6\n#define AES_192_CTR         7\n#define AES_256_CTR         8\n#define BF_CFB              9\n#define CAMELLIA_128_CFB    10\n#define CAMELLIA_192_CFB    11\n#define CAMELLIA_256_CFB    12\n#define CAST5_CFB           13\n#define DES_CFB             14\n#define IDEA_CFB            15\n#define RC2_CFB             16\n#define SEED_CFB            17\n#define SALSA20             18\n#define CHACHA20            19\n#define CHACHA20IETF        20\n\nconst char *supported_stream_ciphers[STREAM_CIPHER_NUM] = {\n    \"table\",\n    \"rc4\",\n    \"rc4-md5\",\n    \"aes-128-cfb\",\n    \"aes-192-cfb\",\n    \"aes-256-cfb\",\n    \"aes-128-ctr\",\n    \"aes-192-ctr\",\n    \"aes-256-ctr\",\n    \"bf-cfb\",\n    \"camellia-128-cfb\",\n    \"camellia-192-cfb\",\n    \"camellia-256-cfb\",\n    \"cast5-cfb\",\n    \"des-cfb\",\n    \"idea-cfb\",\n    \"rc2-cfb\",\n    \"seed-cfb\",\n    \"salsa20\",\n    \"chacha20\",\n    \"chacha20-ietf\"\n};\n\nstatic const char *supported_stream_ciphers_mbedtls[STREAM_CIPHER_NUM] = {\n    \"table\",\n    \"ARC4-128\",\n    \"ARC4-128\",\n    \"AES-128-CFB128\",\n    \"AES-192-CFB128\",\n    \"AES-256-CFB128\",\n    \"AES-128-CTR\",\n    \"AES-192-CTR\",\n    \"AES-256-CTR\",\n    \"BLOWFISH-CFB64\",\n    \"CAMELLIA-128-CFB128\",\n    \"CAMELLIA-192-CFB128\",\n    \"CAMELLIA-256-CFB128\",\n    CIPHER_UNSUPPORTED,\n    CIPHER_UNSUPPORTED,\n    CIPHER_UNSUPPORTED,\n    CIPHER_UNSUPPORTED,\n    CIPHER_UNSUPPORTED,\n    \"salsa20\",\n    \"chacha20\",\n    \"chacha20-ietf\"\n};\n\nstatic const int supported_stream_ciphers_nonce_size[STREAM_CIPHER_NUM] = {\n    0, 0, 16, 16, 16, 16, 16, 16, 16, 8, 16, 16, 16, 8, 8, 8, 8, 16, 8, 8, 12\n};\n\nstatic const int supported_stream_ciphers_key_size[STREAM_CIPHER_NUM] = {\n    0, 16, 16, 16, 24, 32, 16, 24, 32, 16, 16, 24, 32, 16, 8, 16, 16, 16, 32, 32, 32\n};\n\nstatic int\ncrypto_stream_xor_ic(uint8_t *c, const uint8_t *m, uint64_t mlen,\n                     const uint8_t *n, uint64_t ic, const uint8_t *k,\n                     int method)\n{\n    switch (method) {\n    case SALSA20:\n        return crypto_stream_salsa20_xor_ic(c, m, mlen, n, ic, k);\n    case CHACHA20:\n        return crypto_stream_chacha20_xor_ic(c, m, mlen, n, ic, k);\n    case CHACHA20IETF:\n        return crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, n, (uint32_t)ic, k);\n    }\n    // always return 0\n    return 0;\n}\n\nconst cipher_kt_t *\nstream_get_cipher_type(int method)\n{\n    if (method <= TABLE || method >= STREAM_CIPHER_NUM) {\n        LOGE(\"stream_get_cipher_type(): Illegal method\");\n        return NULL;\n    }\n\n    if (method == RC4_MD5) {\n        method = RC4;\n    }\n\n    if (method >= SALSA20) {\n        return NULL;\n    }\n\n    const char *ciphername  = supported_stream_ciphers[method];\n    const char *mbedtlsname = supported_stream_ciphers_mbedtls[method];\n    if (strcmp(mbedtlsname, CIPHER_UNSUPPORTED) == 0) {\n        LOGE(\"Cipher %s currently is not supported by mbed TLS library\",\n             ciphername);\n        return NULL;\n    }\n    return mbedtls_cipher_info_from_string(mbedtlsname);\n}\n\nvoid\nstream_cipher_ctx_init(cipher_ctx_t *ctx, int method, int enc)\n{\n    if (method <= TABLE || method >= STREAM_CIPHER_NUM) {\n        LOGE(\"stream_ctx_init(): Illegal method\");\n        return;\n    }\n\n    if (method >= SALSA20) {\n        return;\n    }\n\n    const char *ciphername    = supported_stream_ciphers[method];\n    const cipher_kt_t *cipher = stream_get_cipher_type(method);\n\n    ctx->evp = ss_malloc(sizeof(cipher_evp_t));\n    memset(ctx->evp, 0, sizeof(cipher_evp_t));\n    cipher_evp_t *evp = ctx->evp;\n\n    if (cipher == NULL) {\n        LOGE(\"Cipher %s not found in mbed TLS library\", ciphername);\n        FATAL(\"Cannot initialize mbed TLS cipher\");\n    }\n    mbedtls_cipher_init(evp);\n    if (mbedtls_cipher_setup(evp, cipher) != 0) {\n        FATAL(\"Cannot initialize mbed TLS cipher context\");\n    }\n}\n\nvoid\nstream_ctx_release(cipher_ctx_t *cipher_ctx)\n{\n    if (cipher_ctx->chunk != NULL) {\n        bfree(cipher_ctx->chunk);\n        ss_free(cipher_ctx->chunk);\n        cipher_ctx->chunk = NULL;\n    }\n\n    if (cipher_ctx->cipher->method >= SALSA20) {\n        return;\n    }\n\n    mbedtls_cipher_free(cipher_ctx->evp);\n    ss_free(cipher_ctx->evp);\n}\n\nvoid\ncipher_ctx_set_nonce(cipher_ctx_t *cipher_ctx, uint8_t *nonce, size_t nonce_len,\n                     int enc)\n{\n    const unsigned char *true_key;\n\n    cipher_t *cipher = cipher_ctx->cipher;\n\n    if (nonce == NULL) {\n        LOGE(\"cipher_ctx_set_nonce(): NONCE is null\");\n        return;\n    }\n\n    if (cipher->method >= SALSA20) {\n        return;\n    }\n\n    if (cipher->method == RC4_MD5) {\n        unsigned char key_nonce[32];\n        memcpy(key_nonce, cipher->key, 16);\n        memcpy(key_nonce + 16, nonce, 16);\n        true_key  = crypto_md5(key_nonce, 32, NULL);\n        nonce_len = 0;\n    } else {\n        true_key = cipher->key;\n    }\n\n    cipher_evp_t *evp = cipher_ctx->evp;\n    if (evp == NULL) {\n        LOGE(\"cipher_ctx_set_nonce(): Cipher context is null\");\n        return;\n    }\n    if (mbedtls_cipher_setkey(evp, true_key, cipher->key_len * 8, enc) != 0) {\n        mbedtls_cipher_free(evp);\n        FATAL(\"Cannot set mbed TLS cipher key\");\n    }\n    if (mbedtls_cipher_set_iv(evp, nonce, nonce_len) != 0) {\n        mbedtls_cipher_free(evp);\n        FATAL(\"Cannot set mbed TLS cipher NONCE\");\n    }\n    if (mbedtls_cipher_reset(evp) != 0) {\n        mbedtls_cipher_free(evp);\n        FATAL(\"Cannot finalize mbed TLS cipher context\");\n    }\n\n#ifdef SS_DEBUG\n    dump(\"NONCE\", (char *)nonce, nonce_len);\n    dump(\"KEY\", (char *)true_key, 32);\n#endif\n}\n\nstatic int\ncipher_ctx_update(cipher_ctx_t *ctx, uint8_t *output, size_t *olen,\n                  const uint8_t *input, size_t ilen)\n{\n    cipher_evp_t *evp = ctx->evp;\n    return mbedtls_cipher_update(evp, (const uint8_t *)input, ilen,\n                                 (uint8_t *)output, olen);\n}\n\nint\nstream_encrypt_all(buffer_t *plaintext, cipher_t *cipher, size_t capacity)\n{\n    cipher_ctx_t cipher_ctx;\n    stream_ctx_init(cipher, &cipher_ctx, 1);\n\n    size_t nonce_len = cipher->nonce_len;\n    int err          = CRYPTO_OK;\n\n    static buffer_t tmp = { 0, 0, 0, NULL };\n    brealloc(&tmp, nonce_len + plaintext->len, capacity);\n    buffer_t *ciphertext = &tmp;\n    ciphertext->len = plaintext->len;\n\n    uint8_t *nonce = cipher_ctx.nonce;\n    cipher_ctx_set_nonce(&cipher_ctx, nonce, nonce_len, 1);\n    memcpy(ciphertext->data, nonce, nonce_len);\n\n#ifdef MODULE_REMOTE\n    ppbloom_add((void *)nonce, nonce_len);\n#endif\n\n    if (cipher->method >= SALSA20) {\n        crypto_stream_xor_ic((uint8_t *)(ciphertext->data + nonce_len),\n                             (const uint8_t *)plaintext->data, (uint64_t)(plaintext->len),\n                             (const uint8_t *)nonce,\n                             0, cipher->key, cipher->method);\n    } else {\n        err = cipher_ctx_update(&cipher_ctx, (uint8_t *)(ciphertext->data + nonce_len),\n                                &ciphertext->len, (const uint8_t *)plaintext->data,\n                                plaintext->len);\n    }\n\n    stream_ctx_release(&cipher_ctx);\n\n    if (err)\n        return CRYPTO_ERROR;\n\n#ifdef SS_DEBUG\n    dump(\"PLAIN\", plaintext->data, plaintext->len);\n    dump(\"CIPHER\", ciphertext->data + nonce_len, ciphertext->len);\n    dump(\"NONCE\", ciphertext->data, nonce_len);\n#endif\n\n    bswap_data(plaintext, ciphertext);\n    plaintext->len = nonce_len + ciphertext->len;\n\n    return CRYPTO_OK;\n}\n\nint\nstream_encrypt(buffer_t *plaintext, cipher_ctx_t *cipher_ctx, size_t capacity)\n{\n    if (cipher_ctx == NULL)\n        return CRYPTO_ERROR;\n\n    cipher_t *cipher = cipher_ctx->cipher;\n\n    // In-place fast path for non-Salsa20 ciphers after init.\n    // mbedtls_cipher_update supports output == input for CFB/CTR stream modes.\n    if (cipher_ctx->init && cipher->method < SALSA20) {\n        size_t out_len = plaintext->len;\n        int err = cipher_ctx_update(cipher_ctx,\n                                    (uint8_t *)plaintext->data, &out_len,\n                                    (const uint8_t *)plaintext->data, plaintext->len);\n        if (err)\n            return CRYPTO_ERROR;\n        plaintext->len = out_len;\n        return CRYPTO_OK;\n    }\n\n    static buffer_t tmp = { 0, 0, 0, NULL };\n\n    int err          = CRYPTO_OK;\n    size_t nonce_len = 0;\n    if (!cipher_ctx->init) {\n        nonce_len = cipher_ctx->cipher->nonce_len;\n    }\n\n    brealloc(&tmp, nonce_len + plaintext->len, capacity);\n    buffer_t *ciphertext = &tmp;\n    ciphertext->len = plaintext->len;\n\n    if (!cipher_ctx->init) {\n        cipher_ctx_set_nonce(cipher_ctx, cipher_ctx->nonce, nonce_len, 1);\n        memcpy(ciphertext->data, cipher_ctx->nonce, nonce_len);\n        cipher_ctx->counter = 0;\n        cipher_ctx->init    = 1;\n\n#ifdef MODULE_REMOTE\n        ppbloom_add((void *)cipher_ctx->nonce, nonce_len);\n#endif\n    }\n\n    if (cipher->method >= SALSA20) {\n        int padding = cipher_ctx->counter % SODIUM_BLOCK_SIZE;\n        brealloc(ciphertext, nonce_len + (padding + ciphertext->len) * 2, capacity);\n        if (padding) {\n            brealloc(plaintext, plaintext->len + padding, capacity);\n            memmove(plaintext->data + padding, plaintext->data, plaintext->len);\n            sodium_memzero(plaintext->data, padding);\n        }\n        crypto_stream_xor_ic((uint8_t *)(ciphertext->data + nonce_len),\n                             (const uint8_t *)plaintext->data,\n                             (uint64_t)(plaintext->len + padding),\n                             (const uint8_t *)cipher_ctx->nonce,\n                             cipher_ctx->counter / SODIUM_BLOCK_SIZE, cipher->key,\n                             cipher->method);\n        cipher_ctx->counter += plaintext->len;\n        if (padding) {\n            memmove(ciphertext->data + nonce_len,\n                    ciphertext->data + nonce_len + padding, ciphertext->len);\n        }\n    } else {\n        err = cipher_ctx_update(cipher_ctx,\n                                (uint8_t *)(ciphertext->data + nonce_len),\n                                &ciphertext->len, (const uint8_t *)plaintext->data,\n                                plaintext->len);\n        if (err) {\n            return CRYPTO_ERROR;\n        }\n    }\n\n#ifdef SS_DEBUG\n    dump(\"PLAIN\", plaintext->data, plaintext->len);\n    dump(\"CIPHER\", ciphertext->data + nonce_len, ciphertext->len);\n#endif\n\n    bswap_data(plaintext, ciphertext);\n    plaintext->len = nonce_len + ciphertext->len;\n\n    return CRYPTO_OK;\n}\n\nint\nstream_decrypt_all(buffer_t *ciphertext, cipher_t *cipher, size_t capacity)\n{\n    size_t nonce_len = cipher->nonce_len;\n    int err          = CRYPTO_OK;\n\n    if (ciphertext->len <= nonce_len) {\n        return CRYPTO_ERROR;\n    }\n\n    cipher_ctx_t cipher_ctx;\n    stream_ctx_init(cipher, &cipher_ctx, 0);\n\n    static buffer_t tmp = { 0, 0, 0, NULL };\n    brealloc(&tmp, ciphertext->len, capacity);\n    buffer_t *plaintext = &tmp;\n    plaintext->len = ciphertext->len - nonce_len;\n\n    uint8_t *nonce = cipher_ctx.nonce;\n    memcpy(nonce, ciphertext->data, nonce_len);\n\n    if (ppbloom_check((void *)nonce, nonce_len) == 1) {\n        LOGE(\"crypto: stream: repeat IV detected\");\n        return CRYPTO_ERROR;\n    }\n\n    cipher_ctx_set_nonce(&cipher_ctx, nonce, nonce_len, 0);\n\n    if (cipher->method >= SALSA20) {\n        crypto_stream_xor_ic((uint8_t *)plaintext->data,\n                             (const uint8_t *)(ciphertext->data + nonce_len),\n                             (uint64_t)(ciphertext->len - nonce_len),\n                             (const uint8_t *)nonce, 0, cipher->key, cipher->method);\n    } else {\n        err = cipher_ctx_update(&cipher_ctx, (uint8_t *)plaintext->data, &plaintext->len,\n                                (const uint8_t *)(ciphertext->data + nonce_len),\n                                ciphertext->len - nonce_len);\n    }\n\n    stream_ctx_release(&cipher_ctx);\n\n    if (err)\n        return CRYPTO_ERROR;\n\n#ifdef SS_DEBUG\n    dump(\"PLAIN\", plaintext->data, plaintext->len);\n    dump(\"CIPHER\", ciphertext->data + nonce_len, ciphertext->len - nonce_len);\n    dump(\"NONCE\", ciphertext->data, nonce_len);\n#endif\n\n    ppbloom_add((void *)nonce, nonce_len);\n\n    bswap_data(ciphertext, plaintext);\n    ciphertext->len = plaintext->len;\n\n    return CRYPTO_OK;\n}\n\nint\nstream_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity)\n{\n    if (cipher_ctx == NULL)\n        return CRYPTO_ERROR;\n\n    cipher_t *cipher = cipher_ctx->cipher;\n\n    // In-place fast path for non-Salsa20 ciphers after init.\n    // mbedtls_cipher_update supports output == input for CFB/CTR stream modes.\n    if (cipher_ctx->init && cipher->method < SALSA20) {\n        if (ciphertext->len <= 0)\n            return CRYPTO_NEED_MORE;\n        size_t out_len = ciphertext->len;\n        int err = cipher_ctx_update(cipher_ctx,\n                                    (uint8_t *)ciphertext->data, &out_len,\n                                    (const uint8_t *)ciphertext->data, ciphertext->len);\n        if (err)\n            return CRYPTO_ERROR;\n        ciphertext->len = out_len;\n        if (cipher_ctx->init == 1 && cipher->method >= RC4_MD5) {\n            if (ppbloom_check((void *)cipher_ctx->nonce, cipher->nonce_len) == 1) {\n                LOGE(\"crypto: stream: repeat IV detected\");\n                return CRYPTO_ERROR;\n            }\n            ppbloom_add((void *)cipher_ctx->nonce, cipher->nonce_len);\n            cipher_ctx->init = 2;\n        }\n        return CRYPTO_OK;\n    }\n\n    static buffer_t tmp = { 0, 0, 0, NULL };\n\n    int err = CRYPTO_OK;\n\n    brealloc(&tmp, ciphertext->len, capacity);\n    buffer_t *plaintext = &tmp;\n    plaintext->len = ciphertext->len;\n\n    if (!cipher_ctx->init) {\n        if (cipher_ctx->chunk == NULL) {\n            cipher_ctx->chunk = (buffer_t *)ss_malloc(sizeof(buffer_t));\n            memset(cipher_ctx->chunk, 0, sizeof(buffer_t));\n            balloc(cipher_ctx->chunk, cipher->nonce_len);\n        }\n\n        size_t left_len = min(cipher->nonce_len - cipher_ctx->chunk->len,\n                              ciphertext->len);\n\n        if (left_len > 0) {\n            memcpy(cipher_ctx->chunk->data + cipher_ctx->chunk->len, ciphertext->data, left_len);\n            memmove(ciphertext->data, ciphertext->data + left_len,\n                    ciphertext->len - left_len);\n            cipher_ctx->chunk->len += left_len;\n            ciphertext->len        -= left_len;\n        }\n\n        if (cipher_ctx->chunk->len < cipher->nonce_len)\n            return CRYPTO_NEED_MORE;\n\n        uint8_t *nonce   = cipher_ctx->nonce;\n        size_t nonce_len = cipher->nonce_len;\n        plaintext->len -= left_len;\n\n        memcpy(nonce, cipher_ctx->chunk->data, nonce_len);\n        cipher_ctx_set_nonce(cipher_ctx, nonce, nonce_len, 0);\n        cipher_ctx->counter = 0;\n        cipher_ctx->init    = 1;\n\n        if (cipher->method >= RC4_MD5) {\n            if (ppbloom_check((void *)nonce, nonce_len) == 1) {\n                LOGE(\"crypto: stream: repeat IV detected\");\n                return CRYPTO_ERROR;\n            }\n        }\n    }\n\n    if (ciphertext->len <= 0)\n        return CRYPTO_NEED_MORE;\n\n    if (cipher->method >= SALSA20) {\n        int padding = cipher_ctx->counter % SODIUM_BLOCK_SIZE;\n        brealloc(plaintext, (plaintext->len + padding) * 2, capacity);\n\n        if (padding) {\n            brealloc(ciphertext, ciphertext->len + padding, capacity);\n            memmove(ciphertext->data + padding, ciphertext->data,\n                    ciphertext->len);\n            sodium_memzero(ciphertext->data, padding);\n        }\n        crypto_stream_xor_ic((uint8_t *)plaintext->data,\n                             (const uint8_t *)(ciphertext->data),\n                             (uint64_t)(ciphertext->len + padding),\n                             (const uint8_t *)cipher_ctx->nonce,\n                             cipher_ctx->counter / SODIUM_BLOCK_SIZE, cipher->key,\n                             cipher->method);\n        cipher_ctx->counter += ciphertext->len;\n        if (padding) {\n            memmove(plaintext->data, plaintext->data + padding, plaintext->len);\n        }\n    } else {\n        err = cipher_ctx_update(cipher_ctx, (uint8_t *)plaintext->data, &plaintext->len,\n                                (const uint8_t *)(ciphertext->data),\n                                ciphertext->len);\n    }\n\n    if (err)\n        return CRYPTO_ERROR;\n\n#ifdef SS_DEBUG\n    dump(\"PLAIN\", plaintext->data, plaintext->len);\n    dump(\"CIPHER\", ciphertext->data, ciphertext->len);\n#endif\n\n    // Add to bloom filter\n    if (cipher_ctx->init == 1) {\n        if (cipher->method >= RC4_MD5) {\n            if (ppbloom_check((void *)cipher_ctx->nonce, cipher->nonce_len) == 1) {\n                LOGE(\"crypto: stream: repeat IV detected\");\n                return CRYPTO_ERROR;\n            }\n            ppbloom_add((void *)cipher_ctx->nonce, cipher->nonce_len);\n            cipher_ctx->init = 2;\n        }\n    }\n\n    bswap_data(ciphertext, plaintext);\n    ciphertext->len = plaintext->len;\n\n    return CRYPTO_OK;\n}\n\nvoid\nstream_ctx_init(cipher_t *cipher, cipher_ctx_t *cipher_ctx, int enc)\n{\n    sodium_memzero(cipher_ctx, sizeof(cipher_ctx_t));\n    stream_cipher_ctx_init(cipher_ctx, cipher->method, enc);\n    cipher_ctx->cipher = cipher;\n\n    if (enc) {\n        rand_bytes(cipher_ctx->nonce, cipher->nonce_len);\n    }\n}\n\ncipher_t *\nstream_key_init(int method, const char *pass, const char *key)\n{\n    if (method <= TABLE || method >= STREAM_CIPHER_NUM) {\n        LOGE(\"cipher->key_init(): Illegal method\");\n        return NULL;\n    }\n\n    cipher_t *cipher = (cipher_t *)ss_malloc(sizeof(cipher_t));\n    memset(cipher, 0, sizeof(cipher_t));\n\n    if (method < SALSA20 && stream_get_cipher_type(method) == NULL) {\n        LOGE(\"Cipher %s not found in crypto library\", supported_stream_ciphers[method]);\n        FATAL(\"Cannot initialize cipher\");\n    }\n\n    if (key != NULL)\n        cipher->key_len = crypto_parse_key(key, cipher->key,\n                                           supported_stream_ciphers_key_size[method]);\n    else\n        cipher->key_len = crypto_derive_key(pass, cipher->key,\n                                            supported_stream_ciphers_key_size[method]);\n\n    if (cipher->key_len == 0) {\n        FATAL(\"Cannot generate key and NONCE\");\n    }\n    cipher->nonce_len = supported_stream_ciphers_nonce_size[method];\n    cipher->method = method;\n\n    return cipher;\n}\n\ncipher_t *\nstream_init(const char *pass, const char *key, const char *method)\n{\n    int m = TABLE;\n    if (method != NULL) {\n        for (m = TABLE; m < STREAM_CIPHER_NUM; m++)\n            if (strcmp(method, supported_stream_ciphers[m]) == 0) {\n                break;\n            }\n        if (m >= STREAM_CIPHER_NUM) {\n            LOGE(\"Invalid cipher name: %s, use chacha20-ietf instead\", method);\n            m = CHACHA20IETF;\n        }\n    }\n    if (m == TABLE) {\n        LOGE(\"Table is deprecated\");\n        return NULL;\n    }\n    return stream_key_init(m, pass, key);\n}\n"
  },
  {
    "path": "src/stream.h",
    "content": "/*\n * encrypt.h - Define the enryptor's interface\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _STREAM_H\n#define _STREAM_H\n\n#ifndef __MINGW32__\n#include <sys/socket.h>\n#endif\n#include <string.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdint.h>\n#ifdef HAVE_STDINT_H\n#include <stdint.h>\n#elif HAVE_INTTYPES_H\n#include <inttypes.h>\n#endif\n\n#include <sodium.h>\n#define STREAM_CIPHER_NUM          21\n\n#include \"crypto.h\"\n\nint stream_encrypt_all(buffer_t *, cipher_t *, size_t);\nint stream_decrypt_all(buffer_t *, cipher_t *, size_t);\nint stream_encrypt(buffer_t *, cipher_ctx_t *, size_t);\nint stream_decrypt(buffer_t *, cipher_ctx_t *, size_t);\n\nvoid stream_ctx_init(cipher_t *, cipher_ctx_t *, int);\nvoid stream_ctx_release(cipher_ctx_t *);\n\ncipher_t *stream_init(const char *pass, const char *key, const char *method);\n\n#endif // _STREAM_H\n"
  },
  {
    "path": "src/tunnel.c",
    "content": "/*\n * tunnel.c - Setup a local port forwarding through remote shadowsocks server\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <fcntl.h>\n#include <locale.h>\n#include <signal.h>\n#include <string.h>\n#include <strings.h>\n#include <unistd.h>\n#include <getopt.h>\n#ifndef __MINGW32__\n#include <errno.h>\n#include <arpa/inet.h>\n#include <netdb.h>\n#include <netinet/in.h>\n#include <pthread.h>\n#endif\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__)\n#include <net/if.h>\n#include <sys/ioctl.h>\n#define SET_INTERFACE\n#endif\n\n#include <libcork/core.h>\n\n#include \"netutils.h\"\n#include \"utils.h\"\n#include \"plugin.h\"\n#include \"tunnel.h\"\n#include \"winsock.h\"\n\n#ifndef EAGAIN\n#define EAGAIN EWOULDBLOCK\n#endif\n\n#ifndef EWOULDBLOCK\n#define EWOULDBLOCK EAGAIN\n#endif\n\nstatic void accept_cb(EV_P_ ev_io *w, int revents);\nstatic void server_recv_cb(EV_P_ ev_io *w, int revents);\nstatic void server_send_cb(EV_P_ ev_io *w, int revents);\nstatic void remote_recv_cb(EV_P_ ev_io *w, int revents);\nstatic void remote_send_cb(EV_P_ ev_io *w, int revents);\n\nstatic remote_t *new_remote(int fd, int timeout);\nstatic server_t *new_server(int fd);\n\nstatic void free_remote(remote_t *remote);\nstatic void close_and_free_remote(EV_P_ remote_t *remote);\nstatic void free_server(server_t *server);\nstatic void close_and_free_server(EV_P_ server_t *server);\n\n#ifdef __ANDROID__\nint vpn = 0;\n#endif\n\nint verbose    = 0;\nint reuse_port = 0;\nint tcp_incoming_sndbuf = 0;\nint tcp_incoming_rcvbuf = 0;\nint tcp_outgoing_sndbuf = 0;\nint tcp_outgoing_rcvbuf = 0;\n\nstatic crypto_t *crypto;\n\nstatic int ipv6first = 0;\nstatic int mode      = TCP_ONLY;\n#ifdef HAVE_SETRLIMIT\nstatic int nofile = 0;\n#endif\nstatic int no_delay = 0;\nint fast_open       = 0;\nstatic int ret_val  = 0;\n\nstatic struct ev_signal sigint_watcher;\nstatic struct ev_signal sigterm_watcher;\n#ifndef __MINGW32__\nstatic struct ev_signal sigchld_watcher;\n#else\nstatic struct plugin_watcher_t {\n    ev_io io;\n    SOCKET fd;\n    uint16_t port;\n    int valid;\n} plugin_watcher;\n#endif\n\n#ifndef __MINGW32__\nstatic int\nsetnonblocking(int fd)\n{\n    int flags;\n    if (-1 == (flags = fcntl(fd, F_GETFL, 0))) {\n        flags = 0;\n    }\n    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);\n}\n\n#endif\n\nint\ncreate_and_bind(const char *addr, const char *port)\n{\n    struct addrinfo hints;\n    struct addrinfo *result, *rp;\n    int s, listen_sock = -1;\n\n    memset(&hints, 0, sizeof(struct addrinfo));\n    hints.ai_family   = AF_UNSPEC;   /* Return IPv4 and IPv6 choices */\n    hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */\n\n    result = NULL;\n\n    s = getaddrinfo(addr, port, &hints, &result);\n    if (s != 0) {\n        LOGI(\"getaddrinfo: %s\", gai_strerror(s));\n        return -1;\n    }\n\n    if (result == NULL) {\n        LOGE(\"Could not bind\");\n        return -1;\n    }\n\n    for (rp = result; rp != NULL; rp = rp->ai_next) {\n        listen_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);\n        if (listen_sock == -1) {\n            continue;\n        }\n\n        int opt = 1;\n        setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));\n#ifdef SO_NOSIGPIPE\n        setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));\n#endif\n        if (reuse_port) {\n            int err = set_reuseport(listen_sock);\n            if (err == 0) {\n                LOGI(\"tcp port reuse enabled\");\n            }\n        }\n\n        s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);\n        if (s == 0) {\n            /* We managed to bind successfully! */\n            break;\n        } else {\n            ERROR(\"bind\");\n        }\n\n        close(listen_sock);\n        listen_sock = -1;\n    }\n\n    freeaddrinfo(result);\n\n    return listen_sock;\n}\n\nstatic void\nserver_recv_cb(EV_P_ ev_io *w, int revents)\n{\n    server_ctx_t *server_recv_ctx = (server_ctx_t *)w;\n    server_t *server              = server_recv_ctx->server;\n    remote_t *remote              = server->remote;\n\n    if (remote == NULL) {\n        close_and_free_server(EV_A_ server);\n        return;\n    }\n\n    ssize_t r = recv(server->fd, remote->buf->data, SOCKET_BUF_SIZE, 0);\n\n    if (r == 0) {\n        // connection closed\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else if (r == -1) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) {\n            // no data\n            // continue to wait for recv\n            return;\n        } else {\n            ERROR(\"server recv\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    }\n\n    remote->buf->len = r;\n\n    int err = crypto->encrypt(remote->buf, server->e_ctx, SOCKET_BUF_SIZE);\n\n    if (err) {\n        LOGE(\"invalid password or cipher\");\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    }\n\n    int s = send(remote->fd, remote->buf->data, remote->buf->len, 0);\n\n    if (s == -1) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) {\n            // no data, wait for send\n            remote->buf->idx = 0;\n            ev_io_stop(EV_A_ & server_recv_ctx->io);\n            ev_io_start(EV_A_ & remote->send_ctx->io);\n            return;\n        } else {\n            ERROR(\"send\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    } else if (s < remote->buf->len) {\n        remote->buf->len -= s;\n        remote->buf->idx  = s;\n        ev_io_stop(EV_A_ & server_recv_ctx->io);\n        ev_io_start(EV_A_ & remote->send_ctx->io);\n        return;\n    }\n}\n\nstatic void\nserver_send_cb(EV_P_ ev_io *w, int revents)\n{\n    server_ctx_t *server_send_ctx = (server_ctx_t *)w;\n    server_t *server              = server_send_ctx->server;\n    remote_t *remote              = server->remote;\n    if (server->buf->len == 0) {\n        // close and free\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else {\n        // has data to send\n        ssize_t s = send(server->fd, server->buf->data + server->buf->idx,\n                         server->buf->len, 0);\n        if (s == -1) {\n            if (errno != EAGAIN && errno != EWOULDBLOCK) {\n                ERROR(\"send\");\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n            }\n            return;\n        } else if (s < server->buf->len) {\n            // partly sent, move memory, wait for the next time to send\n            server->buf->len -= s;\n            server->buf->idx += s;\n            return;\n        } else {\n            // all sent out, wait for reading\n            server->buf->len = 0;\n            server->buf->idx = 0;\n            ev_io_stop(EV_A_ & server_send_ctx->io);\n            if (remote != NULL) {\n                ev_io_start(EV_A_ & remote->recv_ctx->io);\n            } else {\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n                return;\n            }\n        }\n    }\n}\n\nstatic void\nremote_timeout_cb(EV_P_ ev_timer *watcher, int revents)\n{\n    remote_ctx_t *remote_ctx\n        = cork_container_of(watcher, remote_ctx_t, watcher);\n\n    remote_t *remote = remote_ctx->remote;\n    server_t *server = remote->server;\n\n    if (verbose) {\n        LOGI(\"TCP connection timeout\");\n    }\n\n    ev_timer_stop(EV_A_ watcher);\n\n    close_and_free_remote(EV_A_ remote);\n    close_and_free_server(EV_A_ server);\n}\n\nstatic void\nremote_recv_cb(EV_P_ ev_io *w, int revents)\n{\n    remote_ctx_t *remote_recv_ctx = (remote_ctx_t *)w;\n    remote_t *remote              = remote_recv_ctx->remote;\n    server_t *server              = remote->server;\n\n    ssize_t r = recv(remote->fd, server->buf->data, SOCKET_BUF_SIZE, 0);\n\n    if (r == 0) {\n        // connection closed\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else if (r == -1) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) {\n            // no data\n            // continue to wait for recv\n            return;\n        } else {\n            ERROR(\"remote recv\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    }\n\n    server->buf->len = r;\n\n    int err = crypto->decrypt(server->buf, server->d_ctx, SOCKET_BUF_SIZE);\n    if (err == CRYPTO_ERROR) {\n        LOGE(\"invalid password or cipher\");\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else if (err == CRYPTO_NEED_MORE) {\n        return; // Wait for more\n    }\n\n    int s = send(server->fd, server->buf->data, server->buf->len, 0);\n\n    if (s == -1) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) {\n            // no data, wait for send\n            server->buf->idx = 0;\n            ev_io_stop(EV_A_ & remote_recv_ctx->io);\n            ev_io_start(EV_A_ & server->send_ctx->io);\n        } else {\n            ERROR(\"send\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    } else if (s < server->buf->len) {\n        server->buf->len -= s;\n        server->buf->idx  = s;\n        ev_io_stop(EV_A_ & remote_recv_ctx->io);\n        ev_io_start(EV_A_ & server->send_ctx->io);\n    }\n\n    // Disable TCP_NODELAY after the first response are sent\n    if (!remote->recv_ctx->connected && !no_delay) {\n        int opt = 0;\n        setsockopt(server->fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n        setsockopt(remote->fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n    }\n    remote->recv_ctx->connected = 1;\n}\n\nstatic void\nremote_send_cb(EV_P_ ev_io *w, int revents)\n{\n    remote_ctx_t *remote_send_ctx = (remote_ctx_t *)w;\n    remote_t *remote              = remote_send_ctx->remote;\n    server_t *server              = remote->server;\n\n    ev_timer_stop(EV_A_ & remote_send_ctx->watcher);\n\n    if (!remote_send_ctx->connected) {\n        int r = 0;\n\n        if (remote->addr == NULL) {\n            struct sockaddr_storage addr;\n            socklen_t len = sizeof(struct sockaddr_storage);\n            r = getpeername(remote->fd, (struct sockaddr *)&addr, &len);\n        }\n\n        if (r == 0) {\n            remote_send_ctx->connected = 1;\n\n            assert(remote->buf->len == 0);\n            buffer_t *abuf = remote->buf;\n\n            ss_addr_t *sa = &server->destaddr;\n            struct cork_ip ip;\n            if (cork_ip_init(&ip, sa->host) != -1) {\n                if (ip.version == 4) {\n                    // send as IPv4\n                    struct in_addr host;\n                    memset(&host, 0, sizeof(struct in_addr));\n                    int host_len = sizeof(struct in_addr);\n\n                    if (inet_pton(AF_INET, sa->host, &host) == -1) {\n                        FATAL(\"IP parser error\");\n                    }\n                    abuf->data[abuf->len++] = 1;\n                    memcpy(abuf->data + abuf->len, &host, host_len);\n                    abuf->len += host_len;\n                } else if (ip.version == 6) {\n                    // send as IPv6\n                    struct in6_addr host;\n                    memset(&host, 0, sizeof(struct in6_addr));\n                    int host_len = sizeof(struct in6_addr);\n\n                    if (inet_pton(AF_INET6, sa->host, &host) == -1) {\n                        FATAL(\"IP parser error\");\n                    }\n                    abuf->data[abuf->len++] = 4;\n                    memcpy(abuf->data + abuf->len, &host, host_len);\n                    abuf->len += host_len;\n                } else {\n                    FATAL(\"IP parser error\");\n                }\n            } else {\n                // send as domain\n                int host_len = strlen(sa->host);\n\n                abuf->data[abuf->len++] = 3;\n                abuf->data[abuf->len++] = host_len;\n                memcpy(abuf->data + abuf->len, sa->host, host_len);\n                abuf->len += host_len;\n            }\n\n            uint16_t port = htons(atoi(sa->port));\n            memcpy(abuf->data + abuf->len, &port, 2);\n            abuf->len += 2;\n\n            int err = crypto->encrypt(abuf, server->e_ctx, SOCKET_BUF_SIZE);\n\n            if (err) {\n                LOGE(\"invalid password or cipher\");\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n                return;\n            }\n\n            ev_io_start(EV_A_ & remote->recv_ctx->io);\n        } else {\n            ERROR(\"getpeername\");\n            // not connected\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    }\n\n    if (remote->buf->len == 0) {\n        // close and free\n        close_and_free_remote(EV_A_ remote);\n        close_and_free_server(EV_A_ server);\n        return;\n    } else {\n        // has data to send\n        ssize_t s = -1;\n        if (remote->addr != NULL) {\n#if defined(TCP_FASTOPEN_WINSOCK)\n            DWORD s   = -1;\n            DWORD err = 0;\n            do {\n                int optval = 1;\n                // Set fast open option\n                if (setsockopt(remote->fd, IPPROTO_TCP, TCP_FASTOPEN,\n                               &optval, sizeof(optval)) != 0) {\n                    ERROR(\"setsockopt\");\n                    break;\n                }\n                // Load ConnectEx function\n                LPFN_CONNECTEX ConnectEx = winsock_getconnectex();\n                if (ConnectEx == NULL) {\n                    LOGE(\"Cannot load ConnectEx() function\");\n                    err = WSAENOPROTOOPT;\n                    break;\n                }\n                // ConnectEx requires a bound socket\n                if (winsock_dummybind(remote->fd,\n                                      (struct sockaddr *)&(remote->addr)) != 0) {\n                    ERROR(\"bind\");\n                    break;\n                }\n                // Call ConnectEx to send data\n                memset(&remote->olap, 0, sizeof(remote->olap));\n                remote->connect_ex_done = 0;\n                if (ConnectEx(remote->fd, (const struct sockaddr *)&(remote->addr),\n                              get_sockaddr_len(remote->addr), remote->buf->data, remote->buf->len,\n                              &s, &remote->olap)) {\n                    remote->connect_ex_done = 1;\n                    break;\n                }\n                // XXX: ConnectEx pending, check later in remote_send\n                if (WSAGetLastError() == ERROR_IO_PENDING) {\n                    err = CONNECT_IN_PROGRESS;\n                    break;\n                }\n                ERROR(\"ConnectEx\");\n            } while (0);\n            // Set error number\n            if (err) {\n                SetLastError(err);\n            }\n#elif defined(CONNECT_DATA_IDEMPOTENT)\n            ((struct sockaddr_in *)&(remote->addr))->sin_len = sizeof(struct sockaddr_in);\n            sa_endpoints_t endpoints;\n            memset((char *)&endpoints, 0, sizeof(endpoints));\n            endpoints.sae_dstaddr    = (struct sockaddr *)&(remote->addr);\n            endpoints.sae_dstaddrlen = get_sockaddr_len(remote->addr);\n            s                        = connectx(remote->fd, &endpoints, SAE_ASSOCID_ANY,\n                                                CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,\n                                                NULL, 0, NULL, NULL);\n#elif defined(TCP_FASTOPEN_CONNECT)\n            int optval = 1;\n            if (setsockopt(remote->fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,\n                           (void *)&optval, sizeof(optval)) < 0)\n                FATAL(\"failed to set TCP_FASTOPEN_CONNECT\");\n            s = connect(remote->fd, remote->addr, get_sockaddr_len(remote->addr));\n            if (s == 0)\n                s = send(remote->fd, remote->buf->data, remote->buf->len, 0);\n#elif defined(MSG_FASTOPEN)\n            s = sendto(remote->fd, remote->buf->data + remote->buf->idx,\n                       remote->buf->len, MSG_FASTOPEN, remote->addr,\n                       get_sockaddr_len(remote->addr));\n#else\n            FATAL(\"tcp fast open is not supported on this platform\");\n#endif\n\n            remote->addr = NULL;\n\n            if (s == -1) {\n                if (errno == CONNECT_IN_PROGRESS) {\n                    ev_io_start(EV_A_ & remote_send_ctx->io);\n                    ev_timer_start(EV_A_ & remote_send_ctx->watcher);\n                } else {\n                    fast_open = 0;\n                    if (errno == EOPNOTSUPP || errno == EPROTONOSUPPORT ||\n                        errno == ENOPROTOOPT) {\n                        LOGE(\"fast open is not supported on this platform\");\n                    } else {\n                        ERROR(\"fast_open_connect\");\n                    }\n                    close_and_free_remote(EV_A_ remote);\n                    close_and_free_server(EV_A_ server);\n                }\n                return;\n            }\n        } else {\n            s = send(remote->fd, remote->buf->data + remote->buf->idx,\n                     remote->buf->len, 0);\n        }\n\n        if (s == -1) {\n            if (errno != EAGAIN && errno != EWOULDBLOCK) {\n                ERROR(\"send\");\n                // close and free\n                close_and_free_remote(EV_A_ remote);\n                close_and_free_server(EV_A_ server);\n            }\n            return;\n        } else if (s < remote->buf->len) {\n            // partly sent, move memory, wait for the next time to send\n            remote->buf->len -= s;\n            remote->buf->idx += s;\n            return;\n        } else {\n            // all sent out, wait for reading\n            remote->buf->len = 0;\n            remote->buf->idx = 0;\n            ev_io_stop(EV_A_ & remote_send_ctx->io);\n            ev_io_start(EV_A_ & server->recv_ctx->io);\n        }\n    }\n}\n\nstatic remote_t *\nnew_remote(int fd, int timeout)\n{\n    remote_t *remote = ss_malloc(sizeof(remote_t));\n    memset(remote, 0, sizeof(remote_t));\n\n    remote->recv_ctx = ss_malloc(sizeof(remote_ctx_t));\n    remote->send_ctx = ss_malloc(sizeof(remote_ctx_t));\n    remote->buf      = ss_malloc(sizeof(buffer_t));\n    balloc(remote->buf, SOCKET_BUF_SIZE);\n    memset(remote->recv_ctx, 0, sizeof(remote_ctx_t));\n    memset(remote->send_ctx, 0, sizeof(remote_ctx_t));\n    remote->fd                  = fd;\n    remote->recv_ctx->remote    = remote;\n    remote->recv_ctx->connected = 0;\n    remote->send_ctx->remote    = remote;\n    remote->send_ctx->connected = 0;\n\n    ev_io_init(&remote->recv_ctx->io, remote_recv_cb, fd, EV_READ);\n    ev_io_init(&remote->send_ctx->io, remote_send_cb, fd, EV_WRITE);\n    ev_timer_init(&remote->send_ctx->watcher, remote_timeout_cb,\n                  min(MAX_CONNECT_TIMEOUT, timeout), 0);\n\n    return remote;\n}\n\nstatic void\nfree_remote(remote_t *remote)\n{\n    if (remote->server != NULL) {\n        remote->server->remote = NULL;\n    }\n    if (remote->buf != NULL) {\n        bfree(remote->buf);\n        ss_free(remote->buf);\n    }\n    ss_free(remote->recv_ctx);\n    ss_free(remote->send_ctx);\n    ss_free(remote);\n}\n\nstatic void\nclose_and_free_remote(EV_P_ remote_t *remote)\n{\n    if (remote != NULL) {\n        ev_timer_stop(EV_A_ & remote->send_ctx->watcher);\n        ev_io_stop(EV_A_ & remote->send_ctx->io);\n        ev_io_stop(EV_A_ & remote->recv_ctx->io);\n        close(remote->fd);\n        free_remote(remote);\n    }\n}\n\nstatic server_t *\nnew_server(int fd)\n{\n    server_t *server = ss_malloc(sizeof(server_t));\n    memset(server, 0, sizeof(server_t));\n\n    server->recv_ctx = ss_malloc(sizeof(server_ctx_t));\n    server->send_ctx = ss_malloc(sizeof(server_ctx_t));\n    server->buf      = ss_malloc(sizeof(buffer_t));\n    balloc(server->buf, SOCKET_BUF_SIZE);\n    memset(server->recv_ctx, 0, sizeof(server_ctx_t));\n    memset(server->send_ctx, 0, sizeof(server_ctx_t));\n    server->fd                  = fd;\n    server->recv_ctx->server    = server;\n    server->recv_ctx->connected = 0;\n    server->send_ctx->server    = server;\n    server->send_ctx->connected = 0;\n\n    server->e_ctx = ss_malloc(sizeof(cipher_ctx_t));\n    server->d_ctx = ss_malloc(sizeof(cipher_ctx_t));\n    crypto->ctx_init(crypto->cipher, server->e_ctx, 1);\n    crypto->ctx_init(crypto->cipher, server->d_ctx, 0);\n\n    ev_io_init(&server->recv_ctx->io, server_recv_cb, fd, EV_READ);\n    ev_io_init(&server->send_ctx->io, server_send_cb, fd, EV_WRITE);\n\n    return server;\n}\n\nstatic void\nfree_server(server_t *server)\n{\n    if (server->remote != NULL) {\n        server->remote->server = NULL;\n    }\n    if (server->e_ctx != NULL) {\n        crypto->ctx_release(server->e_ctx);\n        ss_free(server->e_ctx);\n    }\n    if (server->d_ctx != NULL) {\n        crypto->ctx_release(server->d_ctx);\n        ss_free(server->d_ctx);\n    }\n    if (server->buf != NULL) {\n        bfree(server->buf);\n        ss_free(server->buf);\n    }\n    ss_free(server->recv_ctx);\n    ss_free(server->send_ctx);\n    ss_free(server);\n}\n\nstatic void\nclose_and_free_server(EV_P_ server_t *server)\n{\n    if (server != NULL) {\n        ev_io_stop(EV_A_ & server->send_ctx->io);\n        ev_io_stop(EV_A_ & server->recv_ctx->io);\n        close(server->fd);\n        free_server(server);\n    }\n}\n\nstatic void\naccept_cb(EV_P_ ev_io *w, int revents)\n{\n    struct listen_ctx *listener = (struct listen_ctx *)w;\n    int serverfd                = accept(listener->fd, NULL, NULL);\n    if (serverfd == -1) {\n        ERROR(\"accept\");\n        return;\n    }\n    setnonblocking(serverfd);\n    int opt = 1;\n    setsockopt(serverfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n#ifdef SO_NOSIGPIPE\n    setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));\n#endif\n\n    if (tcp_incoming_sndbuf > 0) {\n        setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &tcp_incoming_sndbuf, sizeof(int));\n    }\n\n    if (tcp_incoming_rcvbuf > 0) {\n        setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &tcp_incoming_rcvbuf, sizeof(int));\n    }\n\n    int index                    = rand() % listener->remote_num;\n    struct sockaddr *remote_addr = listener->remote_addr[index];\n\n    int protocol = IPPROTO_TCP;\n    if (listener->mptcp < 0) {\n        protocol = IPPROTO_MPTCP; // Enable upstream MPTCP\n    }\n    int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, protocol);\n    if (remotefd == -1) {\n        ERROR(\"socket\");\n        return;\n    }\n\n#ifdef __ANDROID__\n    if (vpn) {\n        int not_protect = 0;\n        if (remote_addr->sa_family == AF_INET) {\n            struct sockaddr_in *s = (struct sockaddr_in *)remote_addr;\n            if (s->sin_addr.s_addr == inet_addr(\"127.0.0.1\"))\n                not_protect = 1;\n        }\n        if (!not_protect) {\n            if (protect_socket(remotefd) == -1) {\n                ERROR(\"protect_socket\");\n                close(remotefd);\n                return;\n            }\n        }\n    }\n#endif\n\n    int keepAlive = 1;\n    setsockopt(remotefd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));\n    setsockopt(remotefd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));\n#ifdef SO_NOSIGPIPE\n    setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));\n#endif\n\n    // Enable out-of-tree MPTCP\n    if (listener->mptcp > 1) {\n        int err = setsockopt(remotefd, SOL_TCP, listener->mptcp, &opt, sizeof(opt));\n        if (err == -1) {\n            ERROR(\"failed to enable out-of-tree multipath TCP\");\n        }\n    } else if (listener->mptcp == 1) {\n        int i = 0;\n        while ((listener->mptcp = mptcp_enabled_values[i]) > 0) {\n            int err = setsockopt(remotefd, SOL_TCP, listener->mptcp, &opt, sizeof(opt));\n            if (err != -1) {\n                break;\n            }\n            i++;\n        }\n        if (listener->mptcp == 0) {\n            ERROR(\"failed to enable out-of-tree multipath TCP\");\n        }\n    }\n\n    if (tcp_outgoing_sndbuf > 0) {\n        setsockopt(remotefd, SOL_SOCKET, SO_SNDBUF, &tcp_outgoing_sndbuf, sizeof(int));\n    }\n\n    if (tcp_outgoing_rcvbuf > 0) {\n        setsockopt(remotefd, SOL_SOCKET, SO_RCVBUF, &tcp_outgoing_rcvbuf, sizeof(int));\n    }\n\n    // Setup\n    setnonblocking(remotefd);\n#ifdef SET_INTERFACE\n    if (listener->iface) {\n        if (setinterface(remotefd, listener->iface) == -1)\n            ERROR(\"setinterface\");\n    }\n#endif\n\n    server_t *server = new_server(serverfd);\n    remote_t *remote = new_remote(remotefd, listener->timeout);\n    server->destaddr = listener->tunnel_addr;\n    server->remote   = remote;\n    remote->server   = server;\n\n    if (fast_open) {\n        remote->addr = remote_addr;\n    } else {\n        int r = connect(remotefd, remote_addr, get_sockaddr_len(remote_addr));\n\n        if (r == -1 && errno != CONNECT_IN_PROGRESS) {\n            ERROR(\"connect\");\n            close_and_free_remote(EV_A_ remote);\n            close_and_free_server(EV_A_ server);\n            return;\n        }\n    }\n\n    // listen to remote connected event\n    ev_io_start(EV_A_ & remote->send_ctx->io);\n    ev_timer_start(EV_A_ & remote->send_ctx->watcher);\n}\n\nstatic void\nsignal_cb(EV_P_ ev_signal *w, int revents)\n{\n    if (revents & EV_SIGNAL) {\n        switch (w->signum) {\n#ifndef __MINGW32__\n        case SIGCHLD:\n            if (!is_plugin_running()) {\n                LOGE(\"plugin service exit unexpectedly\");\n                ret_val = -1;\n            } else\n                return;\n#endif\n        case SIGINT:\n        case SIGTERM:\n            ev_signal_stop(EV_DEFAULT, &sigint_watcher);\n            ev_signal_stop(EV_DEFAULT, &sigterm_watcher);\n#ifndef __MINGW32__\n            ev_signal_stop(EV_DEFAULT, &sigchld_watcher);\n#else\n            ev_io_stop(EV_DEFAULT, &plugin_watcher.io);\n#endif\n            ev_unloop(EV_A_ EVUNLOOP_ALL);\n        }\n    }\n}\n\n#ifdef __MINGW32__\nstatic void\nplugin_watcher_cb(EV_P_ ev_io *w, int revents)\n{\n    char buf[1];\n    SOCKET fd = accept(plugin_watcher.fd, NULL, NULL);\n    if (fd == INVALID_SOCKET) {\n        return;\n    }\n    recv(fd, buf, 1, 0);\n    closesocket(fd);\n    LOGE(\"plugin service exit unexpectedly\");\n    ret_val = -1;\n    ev_signal_stop(EV_DEFAULT, &sigint_watcher);\n    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);\n    ev_io_stop(EV_DEFAULT, &plugin_watcher.io);\n    ev_unloop(EV_A_ EVUNLOOP_ALL);\n}\n\n#endif\n\nint\nmain(int argc, char **argv)\n{\n    srand(time(NULL));\n\n    int i, c;\n    int pid_flags    = 0;\n    int mptcp        = 0;\n    int mtu          = 0;\n    char *user       = NULL;\n    char *local_port = NULL;\n    char *local_addr = NULL;\n    char *password   = NULL;\n    char *key        = NULL;\n    char *timeout    = NULL;\n    char *method     = NULL;\n    char *pid_path   = NULL;\n    char *conf_path  = NULL;\n    char *iface      = NULL;\n\n    char *plugin      = NULL;\n    char *plugin_opts = NULL;\n    char *plugin_host = NULL;\n    char *plugin_port = NULL;\n    char tmp_port[8];\n\n    ss_addr_t tunnel_addr = { .host = NULL, .port = NULL };\n    char *tunnel_addr_str = NULL;\n\n    int remote_num    = 0;\n    char *remote_port = NULL;\n    ss_addr_t remote_addr[MAX_REMOTE_NUM];\n\n    memset(remote_addr, 0, sizeof(ss_addr_t) * MAX_REMOTE_NUM);\n\n    static struct option long_options[] = {\n        { \"fast-open\",   no_argument,       NULL, GETOPT_VAL_FAST_OPEN   },\n        { \"mtu\",         required_argument, NULL, GETOPT_VAL_MTU         },\n        { \"no-delay\",    no_argument,       NULL, GETOPT_VAL_NODELAY     },\n        { \"mptcp\",       no_argument,       NULL, GETOPT_VAL_MPTCP       },\n        { \"plugin\",      required_argument, NULL, GETOPT_VAL_PLUGIN      },\n        { \"plugin-opts\", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },\n        { \"reuse-port\",  no_argument,       NULL, GETOPT_VAL_REUSE_PORT  },\n        { \"tcp-incoming-sndbuf\", required_argument, NULL, GETOPT_VAL_TCP_INCOMING_SNDBUF },\n        { \"tcp-incoming-rcvbuf\", required_argument, NULL, GETOPT_VAL_TCP_INCOMING_RCVBUF },\n        { \"tcp-outgoing-sndbuf\", required_argument, NULL, GETOPT_VAL_TCP_OUTGOING_SNDBUF },\n        { \"tcp-outgoing-rcvbuf\", required_argument, NULL, GETOPT_VAL_TCP_OUTGOING_RCVBUF },\n        { \"password\",    required_argument, NULL, GETOPT_VAL_PASSWORD    },\n        { \"key\",         required_argument, NULL, GETOPT_VAL_KEY         },\n        { \"help\",        no_argument,       NULL, GETOPT_VAL_HELP        },\n        { NULL,          0,                 NULL, 0                      }\n    };\n\n    opterr = 0;\n\n    USE_TTY();\n\n#ifdef __ANDROID__\n    while ((c = getopt_long(argc, argv, \"f:s:p:l:k:t:m:i:c:b:L:a:n:huUvV6A\",\n                            long_options, NULL)) != -1) {\n#else\n    while ((c = getopt_long(argc, argv, \"f:s:p:l:k:t:m:i:c:b:L:a:n:huUv6A\",\n                            long_options, NULL)) != -1) {\n#endif\n        switch (c) {\n        case GETOPT_VAL_FAST_OPEN:\n            fast_open = 1;\n            break;\n        case GETOPT_VAL_MTU:\n            mtu = atoi(optarg);\n            LOGI(\"set MTU to %d\", mtu);\n            break;\n        case GETOPT_VAL_MPTCP:\n            mptcp = get_mptcp(1);\n            if (mptcp)\n                LOGI(\"enable multipath TCP (%s)\", mptcp > 0 ? \"out-of-tree\" : \"upstream\");\n            break;\n        case GETOPT_VAL_NODELAY:\n            no_delay = 1;\n            LOGI(\"enable TCP no-delay\");\n            break;\n        case GETOPT_VAL_PLUGIN:\n            plugin = optarg;\n            break;\n        case GETOPT_VAL_PLUGIN_OPTS:\n            plugin_opts = optarg;\n            break;\n        case GETOPT_VAL_KEY:\n            key = optarg;\n            break;\n        case GETOPT_VAL_REUSE_PORT:\n            reuse_port = 1;\n            break;\n        case GETOPT_VAL_TCP_INCOMING_SNDBUF:\n            tcp_incoming_sndbuf = atoi(optarg);\n            break;\n        case GETOPT_VAL_TCP_INCOMING_RCVBUF:\n            tcp_incoming_rcvbuf = atoi(optarg);\n            break;\n        case GETOPT_VAL_TCP_OUTGOING_SNDBUF:\n            tcp_outgoing_sndbuf = atoi(optarg);\n            break;\n        case GETOPT_VAL_TCP_OUTGOING_RCVBUF:\n            tcp_outgoing_rcvbuf = atoi(optarg);\n            break;\n        case 's':\n            if (remote_num < MAX_REMOTE_NUM) {\n                parse_addr(optarg, &remote_addr[remote_num++]);\n            }\n            break;\n        case 'p':\n            remote_port = optarg;\n            break;\n        case 'l':\n            local_port = optarg;\n            break;\n        case GETOPT_VAL_PASSWORD:\n        case 'k':\n            password = optarg;\n            break;\n        case 'f':\n            pid_flags = 1;\n            pid_path  = optarg;\n            break;\n        case 't':\n            timeout = optarg;\n            break;\n        case 'm':\n            method = optarg;\n            break;\n        case 'c':\n            conf_path = optarg;\n            break;\n        case 'i':\n            iface = optarg;\n            break;\n        case 'b':\n            local_addr = optarg;\n            break;\n        case 'u':\n            mode = TCP_AND_UDP;\n            break;\n        case 'U':\n            mode = UDP_ONLY;\n            break;\n        case 'L':\n            tunnel_addr_str = optarg;\n            break;\n        case 'a':\n            user = optarg;\n            break;\n#ifdef HAVE_SETRLIMIT\n        case 'n':\n            nofile = atoi(optarg);\n            break;\n#endif\n        case 'v':\n            verbose = 1;\n            break;\n        case GETOPT_VAL_HELP:\n        case 'h':\n            usage();\n            exit(EXIT_SUCCESS);\n        case '6':\n            ipv6first = 1;\n            break;\n#ifdef __ANDROID__\n        case 'V':\n            vpn = 1;\n            break;\n#endif\n        case 'A':\n            FATAL(\"One time auth has been deprecated. Try AEAD ciphers instead.\");\n            break;\n        case '?':\n            // The option character is not recognized.\n            LOGE(\"Unrecognized option: %s\", optarg);\n            opterr = 1;\n            break;\n        }\n    }\n\n    if (opterr) {\n        usage();\n        exit(EXIT_FAILURE);\n    }\n\n    if (argc == 1) {\n        if (conf_path == NULL) {\n            conf_path = get_default_conf();\n        }\n    }\n\n    if (conf_path != NULL) {\n        jconf_t *conf = read_jconf(conf_path);\n        if (remote_num == 0) {\n            remote_num = conf->remote_num;\n            for (i = 0; i < remote_num; i++)\n                remote_addr[i] = conf->remote_addr[i];\n        }\n        if (remote_port == NULL) {\n            remote_port = conf->remote_port;\n        }\n        if (local_addr == NULL) {\n            local_addr = conf->local_addr;\n        }\n        if (local_port == NULL) {\n            local_port = conf->local_port;\n        }\n        if (password == NULL) {\n            password = conf->password;\n        }\n        if (key == NULL) {\n            key = conf->key;\n        }\n        if (method == NULL) {\n            method = conf->method;\n        }\n        if (timeout == NULL) {\n            timeout = conf->timeout;\n        }\n        if (user == NULL) {\n            user = conf->user;\n        }\n        if (plugin == NULL) {\n            plugin = conf->plugin;\n        }\n        if (plugin_opts == NULL) {\n            plugin_opts = conf->plugin_opts;\n        }\n        if (tunnel_addr_str == NULL) {\n            tunnel_addr_str = conf->tunnel_address;\n        }\n        if (mode == TCP_ONLY) {\n            mode = conf->mode;\n        }\n        if (mtu == 0) {\n            mtu = conf->mtu;\n        }\n        if (mptcp == 0) {\n            mptcp = conf->mptcp;\n        }\n        if (no_delay == 0) {\n            no_delay = conf->no_delay;\n        }\n        if (reuse_port == 0) {\n            reuse_port = conf->reuse_port;\n        }\n        if (tcp_incoming_sndbuf == 0) {\n            tcp_incoming_sndbuf = conf->tcp_incoming_sndbuf;\n        }\n        if (tcp_incoming_rcvbuf == 0) {\n            tcp_incoming_rcvbuf = conf->tcp_incoming_rcvbuf;\n        }\n        if (tcp_outgoing_sndbuf == 0) {\n            tcp_outgoing_sndbuf = conf->tcp_outgoing_sndbuf;\n        }\n        if (tcp_outgoing_rcvbuf == 0) {\n            tcp_outgoing_rcvbuf = conf->tcp_outgoing_rcvbuf;\n        }\n        if (fast_open == 0) {\n            fast_open = conf->fast_open;\n        }\n#ifdef HAVE_SETRLIMIT\n        if (nofile == 0) {\n            nofile = conf->nofile;\n        }\n#endif\n    }\n\n    if (remote_num == 0 || remote_port == NULL || tunnel_addr_str == NULL\n        || local_port == NULL || (password == NULL && key == NULL)) {\n        usage();\n        exit(EXIT_FAILURE);\n    }\n\n#ifdef __MINGW32__\n    winsock_init();\n#endif\n\n    if (tcp_incoming_sndbuf != 0 && tcp_incoming_sndbuf < SOCKET_BUF_SIZE) {\n        tcp_incoming_sndbuf = 0;\n    }\n\n    if (tcp_incoming_sndbuf != 0) {\n        LOGI(\"set TCP incoming connection send buffer size to %d\", tcp_incoming_sndbuf);\n    }\n\n    if (tcp_incoming_rcvbuf != 0 && tcp_incoming_rcvbuf < SOCKET_BUF_SIZE) {\n        tcp_incoming_rcvbuf = 0;\n    }\n\n    if (tcp_incoming_rcvbuf != 0) {\n        LOGI(\"set TCP incoming connection receive buffer size to %d\", tcp_incoming_rcvbuf);\n    }\n\n    if (tcp_outgoing_sndbuf != 0 && tcp_outgoing_sndbuf < SOCKET_BUF_SIZE) {\n        tcp_outgoing_sndbuf = 0;\n    }\n\n    if (tcp_outgoing_sndbuf != 0) {\n        LOGI(\"set TCP outgoing connection send buffer size to %d\", tcp_outgoing_sndbuf);\n    }\n\n    if (tcp_outgoing_rcvbuf != 0 && tcp_outgoing_rcvbuf < SOCKET_BUF_SIZE) {\n        tcp_outgoing_rcvbuf = 0;\n    }\n\n    if (tcp_outgoing_rcvbuf != 0) {\n        LOGI(\"set TCP outgoing connection receive buffer size to %d\", tcp_outgoing_rcvbuf);\n    }\n\n    if (plugin != NULL) {\n        uint16_t port = get_local_port();\n        if (port == 0) {\n            FATAL(\"failed to find a free port\");\n        }\n        snprintf(tmp_port, 8, \"%d\", port);\n        if (is_ipv6only(remote_addr, remote_num, ipv6first)) {\n            plugin_host = \"::1\";\n        } else {\n            plugin_host = \"127.0.0.1\";\n        }\n        plugin_port = tmp_port;\n\n#ifdef __MINGW32__\n        memset(&plugin_watcher, 0, sizeof(plugin_watcher));\n        plugin_watcher.port = get_local_port();\n        if (plugin_watcher.port == 0) {\n            LOGE(\"failed to assign a control port for plugin\");\n        }\n#endif\n\n        LOGI(\"plugin \\\"%s\\\" enabled\", plugin);\n    }\n\n    if (method == NULL) {\n        method = \"chacha20-ietf-poly1305\";\n    }\n\n    if (timeout == NULL) {\n        timeout = \"60\";\n    }\n\n#ifdef HAVE_SETRLIMIT\n    /*\n     * no need to check the return value here since we will show\n     * the user an error message if setrlimit(2) fails\n     */\n    if (nofile > 1024) {\n        if (verbose) {\n            LOGI(\"setting NOFILE to %d\", nofile);\n        }\n        set_nofile(nofile);\n    }\n#endif\n\n    if (local_addr == NULL) {\n        if (is_ipv6only(remote_addr, remote_num, ipv6first)) {\n            local_addr = \"::1\";\n        } else {\n            local_addr = \"127.0.0.1\";\n        }\n    }\n\n    if (fast_open == 1) {\n#ifdef TCP_FASTOPEN\n        LOGI(\"using tcp fast open\");\n#else\n        LOGE(\"tcp fast open is not supported by this environment\");\n        fast_open = 0;\n#endif\n    }\n\n    USE_SYSLOG(argv[0], pid_flags);\n    if (pid_flags) {\n        daemonize(pid_path);\n    }\n\n    if (ipv6first) {\n        LOGI(\"resolving hostname to IPv6 address first\");\n    }\n\n    // parse tunnel addr\n    parse_addr(tunnel_addr_str, &tunnel_addr);\n\n    if (tunnel_addr.port == NULL) {\n        FATAL(\"tunnel port is not defined\");\n    }\n\n#ifdef __MINGW32__\n    // Listen on plugin control port\n    if (plugin != NULL && plugin_watcher.port != 0) {\n        SOCKET fd;\n        fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);\n        if (fd != INVALID_SOCKET) {\n            plugin_watcher.valid = 0;\n            do {\n                struct sockaddr_in addr;\n                memset(&addr, 0, sizeof(addr));\n                addr.sin_family      = AF_INET;\n                addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);\n                addr.sin_port        = htons(plugin_watcher.port);\n                if (bind(fd, (struct sockaddr *)&addr, sizeof(addr))) {\n                    LOGE(\"failed to bind plugin control port\");\n                    break;\n                }\n                if (listen(fd, 1)) {\n                    LOGE(\"failed to listen on plugin control port\");\n                    break;\n                }\n                plugin_watcher.fd = fd;\n                ev_io_init(&plugin_watcher.io, plugin_watcher_cb, fd, EV_READ);\n                ev_io_start(EV_DEFAULT, &plugin_watcher.io);\n                plugin_watcher.valid = 1;\n            } while (0);\n            if (!plugin_watcher.valid) {\n                closesocket(fd);\n                plugin_watcher.port = 0;\n            }\n        }\n    }\n#endif\n\n    if (plugin != NULL) {\n        int len          = 0;\n        size_t buf_size  = 256 * remote_num;\n        char *remote_str = ss_malloc(buf_size);\n\n        snprintf(remote_str, buf_size, \"%s\", remote_addr[0].host);\n        for (int i = 1; i < remote_num; i++) {\n            snprintf(remote_str + len, buf_size - len, \"|%s\", remote_addr[i].host);\n            len = strlen(remote_str);\n        }\n        int err = start_plugin(plugin, plugin_opts, remote_str,\n                               remote_port, plugin_host, plugin_port,\n#ifdef __MINGW32__\n                               plugin_watcher.port,\n#endif\n                               MODE_CLIENT);\n        if (err) {\n            ERROR(\"start_plugin\");\n            FATAL(\"failed to start the plugin\");\n        }\n    }\n\n#ifndef __MINGW32__\n    // ignore SIGPIPE\n    signal(SIGPIPE, SIG_IGN);\n    signal(SIGABRT, SIG_IGN);\n#endif\n\n    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);\n    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);\n    ev_signal_start(EV_DEFAULT, &sigint_watcher);\n    ev_signal_start(EV_DEFAULT, &sigterm_watcher);\n#ifndef __MINGW32__\n    ev_signal_init(&sigchld_watcher, signal_cb, SIGCHLD);\n    ev_signal_start(EV_DEFAULT, &sigchld_watcher);\n#endif\n\n    // Setup keys\n    LOGI(\"initializing ciphers... %s\", method);\n    crypto = crypto_init(password, key, method);\n    if (crypto == NULL)\n        FATAL(\"failed to initialize ciphers\");\n\n    // Setup proxy context\n    struct listen_ctx listen_ctx;\n    memset(&listen_ctx, 0, sizeof(struct listen_ctx));\n    listen_ctx.tunnel_addr = tunnel_addr;\n    listen_ctx.remote_num  = remote_num;\n    listen_ctx.remote_addr = ss_malloc(sizeof(struct sockaddr *) * remote_num);\n    memset(listen_ctx.remote_addr, 0, sizeof(struct sockaddr *) * remote_num);\n    for (i = 0; i < remote_num; i++) {\n        char *host = remote_addr[i].host;\n        char *port = remote_addr[i].port == NULL ? remote_port : remote_addr[i].port;\n        if (plugin != NULL) {\n            host = plugin_host;\n            port = plugin_port;\n        }\n        struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage));\n        memset(storage, 0, sizeof(struct sockaddr_storage));\n        if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) {\n            FATAL(\"failed to resolve the provided hostname\");\n        }\n        listen_ctx.remote_addr[i] = (struct sockaddr *)storage;\n\n        if (plugin != NULL)\n            break;\n    }\n    listen_ctx.timeout = atoi(timeout);\n    listen_ctx.iface   = iface;\n    listen_ctx.mptcp   = mptcp;\n\n    LOGI(\"listening at %s:%s\", local_addr, local_port);\n\n    struct ev_loop *loop = EV_DEFAULT;\n\n    if (mode != UDP_ONLY) {\n        // Setup socket\n        int listenfd;\n        listenfd = create_and_bind(local_addr, local_port);\n        if (listenfd == -1) {\n            FATAL(\"bind() error\");\n        }\n        if (listen(listenfd, SOMAXCONN) == -1) {\n            FATAL(\"listen() error\");\n        }\n        setnonblocking(listenfd);\n\n        listen_ctx.fd = listenfd;\n\n        ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);\n        ev_io_start(loop, &listen_ctx.io);\n    }\n\n    // Setup UDP\n    if (mode != TCP_ONLY) {\n        LOGI(\"UDP relay enabled\");\n        char *host                       = remote_addr[0].host;\n        char *port                       = remote_addr[0].port == NULL ? remote_port : remote_addr[0].port;\n        struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage));\n        memset(storage, 0, sizeof(struct sockaddr_storage));\n        if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) {\n            FATAL(\"failed to resolve the provided hostname\");\n        }\n        struct sockaddr *addr = (struct sockaddr *)storage;\n        init_udprelay(local_addr, local_port, addr, get_sockaddr_len(addr),\n                      tunnel_addr, mtu, crypto, listen_ctx.timeout, iface);\n    }\n\n    if (mode == UDP_ONLY) {\n        LOGI(\"TCP relay disabled\");\n    }\n\n#ifndef __MINGW32__\n    // setuid\n    if (user != NULL && !run_as(user)) {\n        FATAL(\"failed to switch user\");\n    }\n\n    if (geteuid() == 0) {\n        LOGI(\"running from root user\");\n    }\n#endif\n\n    ev_run(loop, 0);\n\n    if (plugin != NULL) {\n        stop_plugin();\n    }\n\n    for (i = 0; i < remote_num; i++)\n        ss_free(listen_ctx.remote_addr[i]);\n    ss_free(listen_ctx.remote_addr);\n\n#ifdef __MINGW32__\n    if (plugin_watcher.valid) {\n        closesocket(plugin_watcher.fd);\n    }\n\n    winsock_cleanup();\n#endif\n\n    return ret_val;\n}\n"
  },
  {
    "path": "src/tunnel.h",
    "content": "/*\n * tunnel.h - Define tunnel's buffers and callbacks\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _TUNNEL_H\n#define _TUNNEL_H\n\n#ifdef HAVE_LIBEV_EV_H\n#include <libev/ev.h>\n#else\n#include <ev.h>\n#endif\n\n#ifdef __MINGW32__\n#include \"winsock.h\"\n#endif\n\n#include \"crypto.h\"\n#include \"jconf.h\"\n\n#include \"common.h\"\n\ntypedef struct listen_ctx {\n    ev_io io;\n    ss_addr_t tunnel_addr;\n    char *iface;\n    int remote_num;\n    int timeout;\n    int fd;\n    int mptcp;\n    struct sockaddr **remote_addr;\n} listen_ctx_t;\n\ntypedef struct server_ctx {\n    ev_io io;\n    int connected;\n    struct server *server;\n} server_ctx_t;\n\ntypedef struct server {\n    int fd;\n\n    buffer_t *buf;\n    cipher_ctx_t *e_ctx;\n    cipher_ctx_t *d_ctx;\n    struct server_ctx *recv_ctx;\n    struct server_ctx *send_ctx;\n    struct remote *remote;\n    ss_addr_t destaddr;\n} server_t;\n\ntypedef struct remote_ctx {\n    ev_io io;\n    ev_timer watcher;\n    int connected;\n    struct remote *remote;\n} remote_ctx_t;\n\ntypedef struct remote {\n    int fd;\n#ifdef TCP_FASTOPEN_WINSOCK\n    OVERLAPPED olap;\n    int connect_ex_done;\n#endif\n    buffer_t *buf;\n    struct remote_ctx *recv_ctx;\n    struct remote_ctx *send_ctx;\n    struct server *server;\n    struct sockaddr *addr;\n    uint32_t counter;\n} remote_t;\n\n#endif // _TUNNEL_H\n"
  },
  {
    "path": "src/udprelay.c",
    "content": "/*\n * udprelay.c - Setup UDP relay for both client and server\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <fcntl.h>\n#include <locale.h>\n#include <signal.h>\n#include <string.h>\n#include <strings.h>\n#include <time.h>\n#include <unistd.h>\n#ifndef __MINGW32__\n#include <arpa/inet.h>\n#include <errno.h>\n#include <netdb.h>\n#include <netinet/in.h>\n#include <pthread.h>\n#endif\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__)\n#include <net/if.h>\n#include <sys/ioctl.h>\n#define SET_INTERFACE\n#endif\n\n#include <libcork/core.h>\n\n#include \"utils.h\"\n#include \"netutils.h\"\n#include \"cache.h\"\n#include \"udprelay.h\"\n#include \"winsock.h\"\n\n#ifdef MODULE_REMOTE\n#define MAX_UDP_CONN_NUM 512\n#else\n#define MAX_UDP_CONN_NUM 256\n#endif\n\n#ifdef MODULE_REMOTE\n#ifdef MODULE_\n#error \"MODULE_REMOTE and MODULE_LOCAL should not be both defined\"\n#endif\n#endif\n\n#ifndef EAGAIN\n#define EAGAIN EWOULDBLOCK\n#endif\n\n#ifndef EWOULDBLOCK\n#define EWOULDBLOCK EAGAIN\n#endif\n\nstatic void server_recv_cb(EV_P_ ev_io *w, int revents);\nstatic void remote_recv_cb(EV_P_ ev_io *w, int revents);\nstatic void remote_timeout_cb(EV_P_ ev_timer *watcher, int revents);\n\nstatic char *hash_key(const int af, const struct sockaddr_storage *addr);\n#ifdef MODULE_REMOTE\nstatic void resolv_free_cb(void *data);\nstatic void resolv_cb(struct sockaddr *addr, void *data);\n#endif\nstatic void close_and_free_remote(EV_P_ remote_ctx_t *ctx);\nstatic remote_ctx_t *new_remote(int fd, server_ctx_t *server_ctx);\n\n#ifdef __ANDROID__\nextern uint64_t tx;\nextern uint64_t rx;\nextern int vpn;\nextern void stat_update_cb();\n#endif\n\nextern int verbose;\nextern int reuse_port;\n#ifdef MODULE_REMOTE\nextern uint64_t tx;\nextern uint64_t rx;\n\nextern int is_bind_local_addr;\nextern struct sockaddr_storage local_addr_v4;\nextern struct sockaddr_storage local_addr_v6;\n#endif\n\nstatic int packet_size                               = DEFAULT_PACKET_SIZE;\nstatic int buf_size                                  = DEFAULT_PACKET_SIZE * 2;\nstatic int server_num                                = 0;\nstatic server_ctx_t *server_ctx_list[MAX_REMOTE_NUM] = { NULL };\n\nconst char *s_port = NULL;\n\n#ifndef __MINGW32__\nstatic int\nsetnonblocking(int fd)\n{\n    int flags;\n    if (-1 == (flags = fcntl(fd, F_GETFL, 0))) {\n        flags = 0;\n    }\n    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);\n}\n\n#endif\n\n#if defined(MODULE_REMOTE) && defined(SO_BROADCAST)\nstatic int\nset_broadcast(int socket_fd)\n{\n    int opt = 1;\n    return setsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt));\n}\n\n#endif\n\n#ifdef SO_NOSIGPIPE\nstatic int\nset_nosigpipe(int socket_fd)\n{\n    int opt = 1;\n    return setsockopt(socket_fd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));\n}\n\n#endif\n\n#ifdef MODULE_REDIR\n\n#ifndef IP_TRANSPARENT\n#define IP_TRANSPARENT       19\n#endif\n\n#ifndef IPV6_TRANSPARENT\n#define IPV6_TRANSPARENT     75\n#endif\n\n#ifndef IP_RECVORIGDSTADDR\n#ifdef  IP_ORIGDSTADDR\n#define IP_RECVORIGDSTADDR   IP_ORIGDSTADDR\n#else\n#define IP_RECVORIGDSTADDR   20\n#endif\n#endif\n\n#ifndef IPV6_RECVORIGDSTADDR\n#ifdef  IPV6_ORIGDSTADDR\n#define IPV6_RECVORIGDSTADDR   IPV6_ORIGDSTADDR\n#else\n#define IPV6_RECVORIGDSTADDR   74\n#endif\n#endif\n\nstatic int\nget_dstaddr(struct msghdr *msg, struct sockaddr_storage *dstaddr)\n{\n    struct cmsghdr *cmsg;\n\n    for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {\n        if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVORIGDSTADDR) {\n            memcpy(dstaddr, CMSG_DATA(cmsg), sizeof(struct sockaddr_in));\n            dstaddr->ss_family = AF_INET;\n            return 0;\n        } else if (cmsg->cmsg_level == SOL_IPV6 && cmsg->cmsg_type == IPV6_RECVORIGDSTADDR) {\n            memcpy(dstaddr, CMSG_DATA(cmsg), sizeof(struct sockaddr_in6));\n            dstaddr->ss_family = AF_INET6;\n            return 0;\n        }\n    }\n\n    return 1;\n}\n\n#endif\n\n#define HASH_KEY_LEN sizeof(struct sockaddr_storage) + sizeof(int)\nstatic char *\nhash_key(const int af, const struct sockaddr_storage *addr)\n{\n    size_t addr_len = sizeof(struct sockaddr_storage);\n    static char key[HASH_KEY_LEN];\n\n    memset(key, 0, HASH_KEY_LEN);\n    memcpy(key, &af, sizeof(int));\n    memcpy(key + sizeof(int), (const uint8_t *)addr, addr_len);\n\n    return key;\n}\n\n#if defined(MODULE_REDIR) || defined(MODULE_REMOTE)\n\nstatic int\nconstruct_udprelay_header(const struct sockaddr_storage *in_addr,\n                          char *addr_header)\n{\n    int addr_header_len = 0;\n\n    if (in_addr->ss_family == AF_INET) {\n        struct sockaddr_in *addr = (struct sockaddr_in *)in_addr;\n        size_t addr_len          = sizeof(struct in_addr);\n\n        addr_header[addr_header_len++] = 1;\n        memcpy(addr_header + addr_header_len, &addr->sin_addr, addr_len);\n        addr_header_len += addr_len;\n        memcpy(addr_header + addr_header_len, &addr->sin_port, 2);\n        addr_header_len += 2;\n    } else if (in_addr->ss_family == AF_INET6) {\n        struct sockaddr_in6 *addr = (struct sockaddr_in6 *)in_addr;\n        size_t addr_len           = sizeof(struct in6_addr);\n\n        addr_header[addr_header_len++] = 4;\n        memcpy(addr_header + addr_header_len, &addr->sin6_addr, addr_len);\n        addr_header_len += addr_len;\n        memcpy(addr_header + addr_header_len, &addr->sin6_port, 2);\n        addr_header_len += 2;\n    } else {\n        return 0;\n    }\n\n    return addr_header_len;\n}\n\n#endif\n\nstatic int\nparse_udprelay_header(const char *buf, const size_t buf_len,\n                      char *host, char *port, struct sockaddr_storage *storage)\n{\n    const uint8_t atyp = *(uint8_t *)buf;\n    int offset         = 1;\n\n    // get remote addr and port\n    if ((atyp & ADDRTYPE_MASK) == 1) {\n        // IP V4\n        size_t in_addr_len = sizeof(struct in_addr);\n        if (buf_len >= in_addr_len + 3) {\n            if (storage != NULL) {\n                struct sockaddr_in *addr = (struct sockaddr_in *)storage;\n                addr->sin_family = AF_INET;\n                memcpy(&addr->sin_addr, buf + offset, sizeof(struct in_addr));\n                memcpy(&addr->sin_port, buf + offset + in_addr_len, sizeof(uint16_t));\n            }\n            if (host != NULL) {\n                inet_ntop(AF_INET, (const void *)(buf + offset),\n                          host, INET_ADDRSTRLEN);\n            }\n            offset += in_addr_len;\n        }\n    } else if ((atyp & ADDRTYPE_MASK) == 3) {\n        // Domain name\n        uint8_t name_len = *(uint8_t *)(buf + offset);\n        if (name_len + 4 <= buf_len) {\n            if (storage != NULL) {\n                char tmp[MAX_HOSTNAME_LEN] = { 0 };\n                struct cork_ip ip;\n                memcpy(tmp, buf + offset + 1, name_len);\n                if (cork_ip_init(&ip, tmp) != -1) {\n                    if (ip.version == 4) {\n                        struct sockaddr_in *addr = (struct sockaddr_in *)storage;\n                        inet_pton(AF_INET, tmp, &(addr->sin_addr));\n                        memcpy(&addr->sin_port, buf + offset + 1 + name_len, sizeof(uint16_t));\n                        addr->sin_family = AF_INET;\n                    } else if (ip.version == 6) {\n                        struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage;\n                        inet_pton(AF_INET, tmp, &(addr->sin6_addr));\n                        memcpy(&addr->sin6_port, buf + offset + 1 + name_len, sizeof(uint16_t));\n                        addr->sin6_family = AF_INET6;\n                    }\n                }\n            }\n            if (host != NULL) {\n                memcpy(host, buf + offset + 1, name_len);\n            }\n            offset += 1 + name_len;\n        }\n    } else if ((atyp & ADDRTYPE_MASK) == 4) {\n        // IP V6\n        size_t in6_addr_len = sizeof(struct in6_addr);\n        if (buf_len >= in6_addr_len + 3) {\n            if (storage != NULL) {\n                struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage;\n                addr->sin6_family = AF_INET6;\n                memcpy(&addr->sin6_addr, buf + offset, sizeof(struct in6_addr));\n                memcpy(&addr->sin6_port, buf + offset + in6_addr_len, sizeof(uint16_t));\n            }\n            if (host != NULL) {\n                inet_ntop(AF_INET6, (const void *)(buf + offset),\n                          host, INET6_ADDRSTRLEN);\n            }\n            offset += in6_addr_len;\n        }\n    }\n\n    if (offset == 1) {\n        LOGE(\"[udp] invalid header with addr type %d\", atyp);\n        return 0;\n    }\n\n    if (port != NULL) {\n        sprintf(port, \"%d\", load16_be(buf + offset));\n    }\n    offset += 2;\n\n    return offset;\n}\n\nstatic char *\nget_addr_str(const struct sockaddr *sa, bool has_port)\n{\n    static char s[SS_ADDRSTRLEN];\n    memset(s, 0, SS_ADDRSTRLEN);\n    char addr[INET6_ADDRSTRLEN] = { 0 };\n    char port[PORTSTRLEN]       = { 0 };\n    uint16_t p;\n    struct sockaddr_in sa_in;\n    struct sockaddr_in6 sa_in6;\n\n    switch (sa->sa_family) {\n    case AF_INET:\n        memcpy(&sa_in, sa, sizeof(struct sockaddr_in));\n        inet_ntop(AF_INET, &sa_in.sin_addr, addr, INET_ADDRSTRLEN);\n        p = ntohs(sa_in.sin_port);\n        sprintf(port, \"%d\", p);\n        break;\n\n    case AF_INET6:\n        memcpy(&sa_in6, sa, sizeof(struct sockaddr_in6));\n        inet_ntop(AF_INET6, &sa_in6.sin6_addr, addr, INET6_ADDRSTRLEN);\n        p = ntohs(sa_in6.sin6_port);\n        sprintf(port, \"%d\", p);\n        break;\n\n    default:\n        strncpy(s, \"Unknown AF\", SS_ADDRSTRLEN);\n    }\n\n    int addr_len = strlen(addr);\n    int port_len = strlen(port);\n    memcpy(s, addr, addr_len);\n\n    if (has_port) {\n        memcpy(s + addr_len + 1, port, port_len);\n        s[addr_len] = ':';\n    }\n\n    return s;\n}\n\nint\ncreate_remote_socket(int ipv6)\n{\n    int remote_sock;\n\n    if (ipv6) {\n        // Try to bind IPv6 first\n        struct sockaddr_in6 addr;\n        memset(&addr, 0, sizeof(struct sockaddr_in6));\n        addr.sin6_family = AF_INET6;\n        addr.sin6_addr   = in6addr_any;\n        addr.sin6_port   = 0;\n        remote_sock      = socket(AF_INET6, SOCK_DGRAM, 0);\n        if (remote_sock == -1) {\n            ERROR(\"[udp] cannot create socket\");\n            return -1;\n        }\n#ifdef MODULE_REMOTE\n        if (is_bind_local_addr) {\n            if (local_addr_v6.ss_family == AF_INET6) {\n                if (bind_to_addr(&local_addr_v6, remote_sock) == -1) {\n                    ERROR(\"bind_to_addr\");\n                    FATAL(\"[udp] cannot bind socket\");\n                    return -1;\n                }\n            }\n        } else {\n#endif\n        if (bind(remote_sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) {\n            FATAL(\"[udp] cannot bind socket\");\n            return -1;\n        }\n#ifdef MODULE_REMOTE\n    }\n#endif\n    } else {\n        // Or else bind to IPv4\n        struct sockaddr_in addr;\n        memset(&addr, 0, sizeof(struct sockaddr_in));\n        addr.sin_family      = AF_INET;\n        addr.sin_addr.s_addr = INADDR_ANY;\n        addr.sin_port        = 0;\n        remote_sock          = socket(AF_INET, SOCK_DGRAM, 0);\n        if (remote_sock == -1) {\n            ERROR(\"[udp] cannot create socket\");\n            return -1;\n        }\n#ifdef MODULE_REMOTE\n        if (is_bind_local_addr) {\n            if (local_addr_v4.ss_family == AF_INET) {\n                if (bind_to_addr(&local_addr_v4, remote_sock) == -1) {\n                    ERROR(\"bind_to_addr\");\n                    FATAL(\"[udp] cannot bind socket\");\n                    return -1;\n                }\n            }\n        } else {\n#endif\n        if (bind(remote_sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) {\n            FATAL(\"[udp] cannot bind remote\");\n            return -1;\n        }\n#ifdef MODULE_REMOTE\n    }\n#endif\n    }\n\n#if defined(__linux__)\n    // Disable fragmentation\n    int val = IP_PMTUDISC_DO;\n    setsockopt(remote_sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val));\n#endif\n\n    return remote_sock;\n}\n\nint\ncreate_server_socket(const char *host, const char *port)\n{\n    struct addrinfo hints;\n    struct addrinfo *result, *rp, *ipv4v6bindall;\n    int s, server_sock = -1;\n\n    memset(&hints, 0, sizeof(struct addrinfo));\n    hints.ai_family   = AF_UNSPEC;               /* Return IPv4 and IPv6 choices */\n    hints.ai_socktype = SOCK_DGRAM;              /* We want a UDP socket */\n    hints.ai_flags    = AI_PASSIVE | AI_ADDRCONFIG; /* For wildcard IP address */\n    hints.ai_protocol = IPPROTO_UDP;\n\n    s = getaddrinfo(host, port, &hints, &result);\n    if (s != 0) {\n        LOGE(\"[udp] getaddrinfo: %s\", gai_strerror(s));\n        return -1;\n    }\n\n    if (result == NULL) {\n        LOGE(\"[udp] cannot bind\");\n        return -1;\n    }\n\n    rp = result;\n\n    /*\n     * On Linux, with net.ipv6.bindv6only = 0 (the default), getaddrinfo(NULL) with\n     * AI_PASSIVE returns 0.0.0.0 and :: (in this order). AI_PASSIVE was meant to\n     * return a list of addresses to listen on, but it is impossible to listen on\n     * 0.0.0.0 and :: at the same time, if :: implies dualstack mode.\n     */\n    if (!host) {\n        ipv4v6bindall = result;\n\n        /* Loop over all address infos found until a IPV6 address is found. */\n        while (ipv4v6bindall) {\n            if (ipv4v6bindall->ai_family == AF_INET6) {\n                rp = ipv4v6bindall; /* Take first IPV6 address available */\n                break;\n            }\n            ipv4v6bindall = ipv4v6bindall->ai_next; /* Get next address info, if any */\n        }\n    }\n\n    for (/*rp = result*/; rp != NULL; rp = rp->ai_next) {\n        server_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);\n        if (server_sock == -1) {\n            continue;\n        }\n\n        if (rp->ai_family == AF_INET6) {\n            int ipv6only = host ? 1 : 0;\n            setsockopt(server_sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only));\n        }\n\n        int opt = 1;\n        setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));\n#ifdef SO_NOSIGPIPE\n        set_nosigpipe(server_sock);\n#endif\n        if (reuse_port) {\n            int err = set_reuseport(server_sock);\n            if (err == 0) {\n                LOGI(\"udp port reuse enabled\");\n            }\n        }\n#ifdef IP_TOS\n        // Set QoS flag\n        int tos   = 46 << 2;\n        int rc = setsockopt(server_sock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));\n        if (rc < 0 && errno != ENOPROTOOPT) {\n            LOGE(\"setting ipv4 dscp failed: %d\", errno);\n        }\n#ifdef IPV6_TCLASS\n        rc = setsockopt(server_sock, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos));\n        if (rc < 0 && errno != ENOPROTOOPT) {\n            LOGE(\"setting ipv6 dscp failed: %d\", errno);\n        }\n#endif\n#endif\n\n#ifdef MODULE_REDIR\n        int sol    = rp->ai_family == AF_INET ? SOL_IP : SOL_IPV6;\n        int flag_t = rp->ai_family == AF_INET ? IP_TRANSPARENT : IPV6_TRANSPARENT;\n        int flag_r = rp->ai_family == AF_INET ? IP_RECVORIGDSTADDR : IPV6_RECVORIGDSTADDR;\n\n        if (setsockopt(server_sock, sol, flag_t, &opt, sizeof(opt))) {\n            ERROR(\"[udp] setsockopt IP_TRANSPARENT\");\n            exit(EXIT_FAILURE);\n        }\n\n        if (setsockopt(server_sock, sol, flag_r, &opt, sizeof(opt))) {\n            FATAL(\"[udp] setsockopt IP_RECVORIGDSTADDR\");\n        }\n#endif\n\n        s = bind(server_sock, rp->ai_addr, rp->ai_addrlen);\n        if (s == 0) {\n            /* We managed to bind successfully! */\n            break;\n        } else {\n            ERROR(\"[udp] bind\");\n        }\n\n        close(server_sock);\n        server_sock = -1;\n    }\n\n    freeaddrinfo(result);\n\n#if defined(__linux__)\n    // Disable fragmentation\n    int val = IP_PMTUDISC_DO;\n    setsockopt(server_sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val));\n#endif\n\n    return server_sock;\n}\n\nremote_ctx_t *\nnew_remote(int fd, server_ctx_t *server_ctx)\n{\n    remote_ctx_t *ctx = ss_malloc(sizeof(remote_ctx_t));\n    memset(ctx, 0, sizeof(remote_ctx_t));\n\n    ctx->fd         = fd;\n    ctx->server_ctx = server_ctx;\n    ctx->af         = AF_UNSPEC;\n\n    ev_io_init(&ctx->io, remote_recv_cb, fd, EV_READ);\n    ev_timer_init(&ctx->watcher, remote_timeout_cb, server_ctx->timeout,\n                  server_ctx->timeout);\n\n    return ctx;\n}\n\nserver_ctx_t *\nnew_server_ctx(int fd)\n{\n    server_ctx_t *ctx = ss_malloc(sizeof(server_ctx_t));\n    memset(ctx, 0, sizeof(server_ctx_t));\n\n    ctx->fd = fd;\n\n    ev_io_init(&ctx->io, server_recv_cb, fd, EV_READ);\n\n    return ctx;\n}\n\n#ifdef MODULE_REMOTE\nstruct query_ctx *\nnew_query_ctx(char *buf, size_t len)\n{\n    struct query_ctx *ctx = ss_malloc(sizeof(struct query_ctx));\n    memset(ctx, 0, sizeof(struct query_ctx));\n    ctx->buf = ss_malloc(sizeof(buffer_t));\n    balloc(ctx->buf, len);\n    memcpy(ctx->buf->data, buf, len);\n    ctx->buf->len = len;\n    return ctx;\n}\n\nvoid\nclose_and_free_query(EV_P_ struct query_ctx *ctx)\n{\n    if (ctx != NULL) {\n        if (ctx->buf != NULL) {\n            bfree(ctx->buf);\n            ss_free(ctx->buf);\n        }\n        ss_free(ctx);\n    }\n}\n\n#endif\n\nvoid\nclose_and_free_remote(EV_P_ remote_ctx_t *ctx)\n{\n    if (ctx != NULL) {\n        ev_timer_stop(EV_A_ & ctx->watcher);\n        ev_io_stop(EV_A_ & ctx->io);\n        close(ctx->fd);\n        ss_free(ctx);\n    }\n}\n\nstatic void\nremote_timeout_cb(EV_P_ ev_timer *watcher, int revents)\n{\n    remote_ctx_t *remote_ctx\n        = cork_container_of(watcher, remote_ctx_t, watcher);\n\n    if (verbose) {\n        LOGI(\"[udp] connection timeout\");\n    }\n\n    char *key = hash_key(remote_ctx->af, &remote_ctx->src_addr);\n    cache_remove(remote_ctx->server_ctx->conn_cache, key, HASH_KEY_LEN);\n}\n\n#ifdef MODULE_REMOTE\nstatic void\nresolv_free_cb(void *data)\n{\n    struct query_ctx *ctx = (struct query_ctx *)data;\n    if (ctx->buf != NULL) {\n        bfree(ctx->buf);\n        ss_free(ctx->buf);\n    }\n    ss_free(ctx);\n}\n\nstatic void\nresolv_cb(struct sockaddr *addr, void *data)\n{\n    struct query_ctx *query_ctx = (struct query_ctx *)data;\n    struct ev_loop *loop        = query_ctx->server_ctx->loop;\n\n    if (addr == NULL) {\n        LOGE(\"[udp] unable to resolve\");\n    } else {\n        remote_ctx_t *remote_ctx = query_ctx->remote_ctx;\n        int cache_hit            = 0;\n\n        // Lookup in the conn cache\n        if (remote_ctx == NULL) {\n            char *key = hash_key(AF_UNSPEC, &query_ctx->src_addr);\n            cache_lookup(query_ctx->server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)&remote_ctx);\n        }\n\n        if (remote_ctx == NULL) {\n            int remotefd = create_remote_socket(addr->sa_family == AF_INET6);\n            if (remotefd != -1) {\n                setnonblocking(remotefd);\n#ifdef SO_BROADCAST\n                set_broadcast(remotefd);\n#endif\n#ifdef SO_NOSIGPIPE\n                set_nosigpipe(remotefd);\n#endif\n#ifdef IP_TOS\n                // Set QoS flag\n                int tos   = 46 << 2;\n                int rc = setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));\n                if (rc < 0 && errno != ENOPROTOOPT) {\n                    LOGE(\"setting ipv4 dscp failed: %d\", errno);\n                }\n#ifdef IPV6_TCLASS\n                rc = setsockopt(remotefd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos));\n                if (rc < 0 && errno != ENOPROTOOPT) {\n                    LOGE(\"setting ipv6 dscp failed: %d\", errno);\n                }\n#endif\n#endif\n#ifdef SET_INTERFACE\n                if (query_ctx->server_ctx->iface) {\n                    if (setinterface(remotefd, query_ctx->server_ctx->iface) == -1)\n                        ERROR(\"setinterface\");\n                }\n#endif\n                remote_ctx             = new_remote(remotefd, query_ctx->server_ctx);\n                remote_ctx->src_addr   = query_ctx->src_addr;\n                remote_ctx->server_ctx = query_ctx->server_ctx;\n            } else {\n                ERROR(\"[udp] bind() error\");\n            }\n        } else {\n            cache_hit = 1;\n        }\n\n        if (remote_ctx != NULL) {\n            if (addr->sa_family == AF_INET)\n                memcpy(&remote_ctx->dst_addr, addr, sizeof(struct sockaddr_in));\n            else\n                memcpy(&remote_ctx->dst_addr, addr, sizeof(struct sockaddr_in6));\n\n            size_t addr_len = get_sockaddr_len(addr);\n            int s           = sendto(remote_ctx->fd, query_ctx->buf->data, query_ctx->buf->len,\n                                     0, addr, addr_len);\n\n            if (s == -1) {\n                ERROR(\"[udp] sendto_remote\");\n                if (!cache_hit) {\n                    close_and_free_remote(EV_A_ remote_ctx);\n                }\n            } else {\n                if (!cache_hit) {\n                    // Add to conn cache\n                    char *key = hash_key(AF_UNSPEC, &remote_ctx->src_addr);\n                    cache_insert(query_ctx->server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx);\n                    ev_io_start(EV_A_ & remote_ctx->io);\n                    ev_timer_start(EV_A_ & remote_ctx->watcher);\n                }\n            }\n        }\n    }\n}\n\n#endif\n\nvoid convert_ipv4_mapped_ipv6(struct sockaddr_storage* addr) {\n    if (addr->ss_family == AF_INET) {\n        struct sockaddr_in* ipv4_addr = (struct sockaddr_in*)addr;\n\n        struct sockaddr_storage mapped_addr;\n        memset(&mapped_addr, 0, sizeof(mapped_addr));\n\n        struct sockaddr_in6* mapped_ipv6_addr = (struct sockaddr_in6*)&mapped_addr;\n        mapped_ipv6_addr->sin6_family = AF_INET6;\n        mapped_ipv6_addr->sin6_port = ipv4_addr->sin_port;\n        uint8_t* ipv6_raw_addr = mapped_ipv6_addr->sin6_addr.s6_addr;\n        ipv6_raw_addr[10] = 0xff;\n        ipv6_raw_addr[11] = 0xff;\n        in_addr_t ipv4_raw_addr = ntohl(ipv4_addr->sin_addr.s_addr);\n        ipv6_raw_addr[12] = (ipv4_raw_addr >> 24) & 0xff;\n        ipv6_raw_addr[13] = (ipv4_raw_addr >> 16) & 0xff;\n        ipv6_raw_addr[14] = (ipv4_raw_addr >> 8) & 0xff;\n        ipv6_raw_addr[15] = ipv4_raw_addr & 0xff;\n\n        memcpy(addr, &mapped_addr, sizeof(mapped_addr));\n    }\n}\n\nstatic void\nremote_recv_cb(EV_P_ ev_io *w, int revents)\n{\n    ssize_t r;\n    remote_ctx_t *remote_ctx = (remote_ctx_t *)w;\n    server_ctx_t *server_ctx = remote_ctx->server_ctx;\n\n    // server has been closed\n    if (server_ctx == NULL) {\n        LOGE(\"[udp] invalid server\");\n        close_and_free_remote(EV_A_ remote_ctx);\n        return;\n    }\n\n    if (verbose) {\n        LOGI(\"[udp] remote receive a packet\");\n    }\n\n    struct sockaddr_storage src_addr;\n    socklen_t src_addr_len = sizeof(struct sockaddr_storage);\n    memset(&src_addr, 0, src_addr_len);\n\n    buffer_t *buf = ss_malloc(sizeof(buffer_t));\n    balloc(buf, buf_size);\n\n    // recv\n    r = recvfrom(remote_ctx->fd, buf->data, buf_size, 0, (struct sockaddr *)&src_addr, &src_addr_len);\n\n    if (r == -1) {\n        // error on recv\n        // simply drop that packet\n        ERROR(\"[udp] remote_recv_recvfrom\");\n        goto CLEAN_UP;\n    } else if (r > packet_size) {\n        if (verbose) {\n            LOGI(\"[udp] remote_recv_recvfrom fragmentation, MTU at least be: \" SSIZE_FMT, r + PACKET_HEADER_SIZE);\n        }\n    }\n\n    buf->len = r;\n\n#ifdef MODULE_LOCAL\n    int err = server_ctx->crypto->decrypt_all(buf, server_ctx->crypto->cipher, buf_size);\n    if (err) {\n        LOGE(\"failed to handshake with %s: %s\",\n                get_addr_str((struct sockaddr *)&src_addr, false), \"suspicious UDP packet\");\n        // drop the packet silently\n        goto CLEAN_UP;\n    }\n\n#ifdef MODULE_REDIR\n    struct sockaddr_storage dst_addr;\n    memset(&dst_addr, 0, sizeof(struct sockaddr_storage));\n    int len = parse_udprelay_header(buf->data, buf->len, NULL, NULL, &dst_addr);\n\n    if (dst_addr.ss_family != AF_INET && dst_addr.ss_family != AF_INET6) {\n        LOGI(\"[udp] ss-redir does not support domain name\");\n        goto CLEAN_UP;\n    }\n#else\n    int len = parse_udprelay_header(buf->data, buf->len, NULL, NULL, NULL);\n#endif\n\n    if (len == 0) {\n        // error when parsing header\n        LOGE(\"[udp] error in parse header\");\n        goto CLEAN_UP;\n    }\n\n#if defined(MODULE_TUNNEL) || defined(MODULE_REDIR)\n    // Construct packet\n    buf->len -= len;\n    memmove(buf->data, buf->data + len, buf->len);\n#else\n#ifdef __ANDROID__\n    rx += buf->len;\n    stat_update_cb();\n#endif\n    // Construct packet\n    brealloc(buf, buf->len + 3, buf_size);\n    memmove(buf->data + 3, buf->data, buf->len);\n    memset(buf->data, 0, 3);\n    buf->len += 3;\n#endif\n\n#endif\n\n#ifdef MODULE_REMOTE\n\n    rx += buf->len;\n\n    // Reconstruct UDP response header\n    char addr_header[MAX_ADDR_HEADER_SIZE];\n    int addr_header_len = construct_udprelay_header(&src_addr, addr_header);\n\n    // Construct packet\n    brealloc(buf, buf->len + addr_header_len, buf_size);\n    memmove(buf->data + addr_header_len, buf->data, buf->len);\n    memcpy(buf->data, addr_header, addr_header_len);\n    buf->len += addr_header_len;\n\n    int err = server_ctx->crypto->encrypt_all(buf, server_ctx->crypto->cipher, buf_size);\n    if (err) {\n        // drop the packet silently\n        goto CLEAN_UP;\n    }\n\n#endif\n\n    if (buf->len > packet_size) {\n        if (verbose) {\n            LOGI(\"[udp] remote_recv_sendto fragmentation, MTU at least be: \" SSIZE_FMT, buf->len + PACKET_HEADER_SIZE);\n        }\n    }\n\n\n#ifdef MODULE_REDIR\n    convert_ipv4_mapped_ipv6(&dst_addr);\n\n    size_t remote_dst_addr_len = get_sockaddr_len((struct sockaddr *)&dst_addr);\n\n    int src_fd = socket(AF_INET6, SOCK_DGRAM, 0);\n    if (src_fd < 0) {\n        ERROR(\"[udp] remote_recv_socket\");\n        goto CLEAN_UP;\n    }\n    int opt = 1;\n    if (setsockopt(src_fd, SOL_IPV6, IPV6_TRANSPARENT, &opt, sizeof(opt))) {\n        ERROR(\"[udp] remote_recv_setsockopt\");\n        close(src_fd);\n        goto CLEAN_UP;\n    }\n    if (setsockopt(src_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {\n        ERROR(\"[udp] remote_recv_setsockopt\");\n        close(src_fd);\n        goto CLEAN_UP;\n    }\n    if (reuse_port) {\n        if (set_reuseport(src_fd) != 0) {\n            ERROR(\"[udp] remote_recv port_reuse\");\n        }\n    }\n#ifdef IP_TOS\n    // Set QoS flag\n    int tos = 46 << 2;\n    int rc = setsockopt(src_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));\n    if (rc < 0 && errno != ENOPROTOOPT) {\n        LOGE(\"setting ipv4 dscp failed: %d\", errno);\n    }\n#ifdef IPV6_TCLASS\n    rc = setsockopt(src_fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos));\n    if (rc < 0 && errno != ENOPROTOOPT) {\n        LOGE(\"setting ipv6 dscp failed: %d\", errno);\n    }\n#endif\n#endif\n    if (bind(src_fd, (struct sockaddr *)&dst_addr, remote_dst_addr_len) != 0) {\n        ERROR(\"[udp] remote_recv_bind\");\n        close(src_fd);\n        goto CLEAN_UP;\n    }\n\n    struct sockaddr_storage mapped_src_addr;\n    memcpy(&mapped_src_addr, &remote_ctx->src_addr, sizeof(remote_ctx->src_addr));\n    convert_ipv4_mapped_ipv6(&mapped_src_addr);\n\n    size_t remote_src_addr_len = get_sockaddr_len((struct sockaddr *)&mapped_src_addr);\n\n    int s = sendto(src_fd, buf->data, buf->len, 0,\n                   (struct sockaddr *)&mapped_src_addr, remote_src_addr_len);\n    if (s == -1 && !(errno == EAGAIN || errno == EWOULDBLOCK)) {\n        ERROR(\"[udp] remote_recv_sendto\");\n        close(src_fd);\n        goto CLEAN_UP;\n    }\n    close(src_fd);\n\n#else\n    size_t remote_src_addr_len = get_sockaddr_len((struct sockaddr *)&remote_ctx->src_addr);\n\n    int s = sendto(server_ctx->fd, buf->data, buf->len, 0,\n                   (struct sockaddr *)&remote_ctx->src_addr, remote_src_addr_len);\n    if (s == -1 && !(errno == EAGAIN || errno == EWOULDBLOCK)) {\n        ERROR(\"[udp] remote_recv_sendto\");\n        goto CLEAN_UP;\n    }\n\n#endif\n\n    // handle the UDP packet successfully,\n    // triger the timer\n    ev_timer_again(EV_A_ & remote_ctx->watcher);\n\nCLEAN_UP:\n\n    bfree(buf);\n    ss_free(buf);\n}\n\nstatic void\nserver_recv_cb(EV_P_ ev_io *w, int revents)\n{\n    server_ctx_t *server_ctx = (server_ctx_t *)w;\n    struct sockaddr_storage src_addr;\n    memset(&src_addr, 0, sizeof(struct sockaddr_storage));\n\n    buffer_t *buf = ss_malloc(sizeof(buffer_t));\n    balloc(buf, buf_size);\n\n    socklen_t src_addr_len = sizeof(struct sockaddr_storage);\n    unsigned int offset    = 0;\n\n#ifdef MODULE_REDIR\n    char control_buffer[64] = { 0 };\n    struct msghdr msg;\n    memset(&msg, 0, sizeof(struct msghdr));\n    struct iovec iov[1];\n    struct sockaddr_storage dst_addr;\n    memset(&dst_addr, 0, sizeof(struct sockaddr_storage));\n\n    msg.msg_name       = &src_addr;\n    msg.msg_namelen    = src_addr_len;\n    msg.msg_control    = control_buffer;\n    msg.msg_controllen = sizeof(control_buffer);\n\n    iov[0].iov_base = buf->data;\n    iov[0].iov_len  = buf_size;\n    msg.msg_iov     = iov;\n    msg.msg_iovlen  = 1;\n\n    buf->len = recvmsg(server_ctx->fd, &msg, 0);\n    if (buf->len == -1) {\n        ERROR(\"[udp] server_recvmsg\");\n        goto CLEAN_UP;\n    } else if (buf->len > packet_size) {\n        if (verbose) {\n            LOGI(\"[udp] UDP server_recv_recvmsg fragmentation, MTU at least be: \" SSIZE_FMT,\n                 buf->len + PACKET_HEADER_SIZE);\n        }\n    }\n\n    if (get_dstaddr(&msg, &dst_addr)) {\n        LOGE(\"[udp] unable to get dest addr\");\n        goto CLEAN_UP;\n    }\n\n    src_addr_len = msg.msg_namelen;\n#else\n    ssize_t r;\n    r = recvfrom(server_ctx->fd, buf->data, buf_size,\n                 0, (struct sockaddr *)&src_addr, &src_addr_len);\n\n    if (r == -1) {\n        // error on recv\n        // simply drop that packet\n        ERROR(\"[udp] server_recv_recvfrom\");\n        goto CLEAN_UP;\n    } else if (r > packet_size) {\n        if (verbose) {\n            LOGI(\"[udp] server_recv_recvfrom fragmentation, MTU at least be: \" SSIZE_FMT, r + PACKET_HEADER_SIZE);\n        }\n    }\n\n    buf->len = r;\n#endif\n\n    if (verbose) {\n        LOGI(\"[udp] server receive a packet\");\n    }\n\n#ifdef MODULE_REMOTE\n    tx += buf->len;\n\n    int err = server_ctx->crypto->decrypt_all(buf, server_ctx->crypto->cipher, buf_size);\n    if (err) {\n        LOGE(\"failed to handshake with %s: %s\",\n                get_addr_str((struct sockaddr *)&src_addr, false), \"suspicious UDP packet\");\n        // drop the packet silently\n        goto CLEAN_UP;\n    }\n#endif\n\n#ifdef MODULE_LOCAL\n#if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR)\n#ifdef __ANDROID__\n    tx += buf->len;\n#endif\n    uint8_t frag = *(uint8_t *)(buf->data + 2);\n    offset += 3;\n#endif\n#endif\n\n    /*\n     *\n     * SOCKS5 UDP Request\n     * +----+------+------+----------+----------+----------+\n     * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |\n     * +----+------+------+----------+----------+----------+\n     * | 2  |  1   |  1   | Variable |    2     | Variable |\n     * +----+------+------+----------+----------+----------+\n     *\n     * SOCKS5 UDP Response\n     * +----+------+------+----------+----------+----------+\n     * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |\n     * +----+------+------+----------+----------+----------+\n     * | 2  |  1   |  1   | Variable |    2     | Variable |\n     * +----+------+------+----------+----------+----------+\n     *\n     * shadowsocks UDP Request (before encrypted)\n     * +------+----------+----------+----------+\n     * | ATYP | DST.ADDR | DST.PORT |   DATA   |\n     * +------+----------+----------+----------+\n     * |  1   | Variable |    2     | Variable |\n     * +------+----------+----------+----------+\n     *\n     * shadowsocks UDP Response (before encrypted)\n     * +------+----------+----------+----------+\n     * | ATYP | DST.ADDR | DST.PORT |   DATA   |\n     * +------+----------+----------+----------+\n     * |  1   | Variable |    2     | Variable |\n     * +------+----------+----------+----------+\n     *\n     * shadowsocks UDP Request and Response (after encrypted)\n     * +-------+--------------+\n     * |   IV  |    PAYLOAD   |\n     * +-------+--------------+\n     * | Fixed |   Variable   |\n     * +-------+--------------+\n     *\n     */\n\n#ifdef MODULE_REDIR\n    char addr_header[MAX_ADDR_HEADER_SIZE] = { 0 };\n    int addr_header_len                    = construct_udprelay_header(&dst_addr, addr_header);\n\n    if (addr_header_len == 0) {\n        LOGE(\"[udp] failed to parse tproxy addr\");\n        goto CLEAN_UP;\n    }\n\n    // reconstruct the buffer\n    brealloc(buf, buf->len + addr_header_len, buf_size);\n    memmove(buf->data + addr_header_len, buf->data, buf->len);\n    memcpy(buf->data, addr_header, addr_header_len);\n    buf->len += addr_header_len;\n\n#elif MODULE_TUNNEL\n\n    char addr_header[MAX_ADDR_HEADER_SIZE] = { 0 };\n    char *host                             = server_ctx->tunnel_addr.host;\n    char *port                             = server_ctx->tunnel_addr.port;\n    uint16_t port_num                      = (uint16_t)atoi(port);\n    uint16_t port_net_num                  = htons(port_num);\n    int addr_header_len                    = 0;\n\n    struct cork_ip ip;\n    if (cork_ip_init(&ip, host) != -1) {\n        if (ip.version == 4) {\n            // send as IPv4\n            struct in_addr host_addr;\n            memset(&host_addr, 0, sizeof(struct in_addr));\n            int host_len = sizeof(struct in_addr);\n\n            if (inet_pton(AF_INET, host, &host_addr) == -1) {\n                FATAL(\"IP parser error\");\n            }\n            addr_header[addr_header_len++] = 1;\n            memcpy(addr_header + addr_header_len, &host_addr, host_len);\n            addr_header_len += host_len;\n        } else if (ip.version == 6) {\n            // send as IPv6\n            struct in6_addr host_addr;\n            memset(&host_addr, 0, sizeof(struct in6_addr));\n            int host_len = sizeof(struct in6_addr);\n\n            if (inet_pton(AF_INET6, host, &host_addr) == -1) {\n                FATAL(\"IP parser error\");\n            }\n            addr_header[addr_header_len++] = 4;\n            memcpy(addr_header + addr_header_len, &host_addr, host_len);\n            addr_header_len += host_len;\n        } else {\n            FATAL(\"IP parser error\");\n        }\n    } else {\n        // send as domain\n        int host_len = strlen(host);\n\n        addr_header[addr_header_len++] = 3;\n        addr_header[addr_header_len++] = host_len;\n        memcpy(addr_header + addr_header_len, host, host_len);\n        addr_header_len += host_len;\n    }\n    memcpy(addr_header + addr_header_len, &port_net_num, 2);\n    addr_header_len += 2;\n\n    // reconstruct the buffer\n    brealloc(buf, buf->len + addr_header_len, buf_size);\n    memmove(buf->data + addr_header_len, buf->data, buf->len);\n    memcpy(buf->data, addr_header, addr_header_len);\n    buf->len += addr_header_len;\n\n#else\n\n    char host[MAX_HOSTNAME_LEN] = { 0 };\n    char port[MAX_PORT_STR_LEN] = { 0 };\n    struct sockaddr_storage dst_addr;\n    memset(&dst_addr, 0, sizeof(struct sockaddr_storage));\n\n    int addr_header_len = parse_udprelay_header(buf->data + offset, buf->len - offset,\n                                                host, port, &dst_addr);\n    if (addr_header_len == 0) {\n        // error in parse header\n        goto CLEAN_UP;\n    }\n\n#endif\n\n#ifdef MODULE_LOCAL\n    char *key = hash_key(server_ctx->remote_addr->sa_family, &src_addr);\n#else\n    char *key = hash_key(dst_addr.ss_family, &src_addr);\n#endif\n\n    struct cache *conn_cache = server_ctx->conn_cache;\n\n    remote_ctx_t *remote_ctx = NULL;\n    cache_lookup(conn_cache, key, HASH_KEY_LEN, (void *)&remote_ctx);\n\n    if (remote_ctx != NULL) {\n        if (sockaddr_cmp(&src_addr, &remote_ctx->src_addr, sizeof(src_addr))) {\n            remote_ctx = NULL;\n        }\n    }\n\n    // reset the timer\n    if (remote_ctx != NULL) {\n        ev_timer_again(EV_A_ & remote_ctx->watcher);\n    }\n\n    if (remote_ctx == NULL) {\n        if (verbose) {\n#ifdef MODULE_REDIR\n            char src[SS_ADDRSTRLEN];\n            char dst[SS_ADDRSTRLEN];\n            strcpy(src, get_addr_str((struct sockaddr *)&src_addr, true));\n            strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr, true));\n            LOGI(\"[%s] [udp] cache miss: %s <-> %s\", s_port, dst, src);\n#else\n            LOGI(\"[%s] [udp] cache miss: %s:%s <-> %s\", s_port, host, port,\n                 get_addr_str((struct sockaddr *)&src_addr, true));\n#endif\n        }\n    } else {\n        if (verbose) {\n#ifdef MODULE_REDIR\n            char src[SS_ADDRSTRLEN];\n            char dst[SS_ADDRSTRLEN];\n            strcpy(src, get_addr_str((struct sockaddr *)&src_addr, true));\n            strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr, true));\n            LOGI(\"[%s] [udp] cache hit: %s <-> %s\", s_port, dst, src);\n#else\n            LOGI(\"[%s] [udp] cache hit: %s:%s <-> %s\", s_port, host, port,\n                 get_addr_str((struct sockaddr *)&src_addr, true));\n#endif\n        }\n    }\n\n#ifdef MODULE_LOCAL\n\n#if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR)\n    if (frag) {\n        LOGE(\"[udp] drop a message since frag is not 0, but %d\", frag);\n        goto CLEAN_UP;\n    }\n#endif\n\n    const struct sockaddr *remote_addr = server_ctx->remote_addr;\n    const int remote_addr_len          = server_ctx->remote_addr_len;\n\n    if (remote_ctx == NULL) {\n        // Bind to any port\n        int remotefd = create_remote_socket(remote_addr->sa_family == AF_INET6);\n        if (remotefd < 0) {\n            ERROR(\"[udp] udprelay bind() error\");\n            goto CLEAN_UP;\n        }\n        setnonblocking(remotefd);\n\n#ifdef SO_NOSIGPIPE\n        set_nosigpipe(remotefd);\n#endif\n#ifdef IP_TOS\n        // Set QoS flag\n        int tos = 46 << 2;\n        int rc = setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));\n        if (rc < 0 && errno != ENOPROTOOPT) {\n            LOGE(\"setting ipv4 dscp failed: %d\", errno);\n        }\n#ifdef IPV6_TCLASS\n        rc = setsockopt(remotefd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos));\n        if (rc < 0 && errno != ENOPROTOOPT) {\n            LOGE(\"setting ipv6 dscp failed: %d\", errno);\n        }\n#endif\n#endif\n#ifdef SET_INTERFACE\n        if (server_ctx->iface) {\n            if (setinterface(remotefd, server_ctx->iface) == -1)\n                ERROR(\"setinterface\");\n        }\n#endif\n\n#ifdef __ANDROID__\n        if (vpn) {\n            if (protect_socket(remotefd) == -1) {\n                ERROR(\"protect_socket\");\n                close(remotefd);\n                goto CLEAN_UP;\n            }\n        }\n#endif\n\n        // Init remote_ctx\n        remote_ctx           = new_remote(remotefd, server_ctx);\n        remote_ctx->src_addr = src_addr;\n        remote_ctx->af       = remote_addr->sa_family;\n\n        // Add to conn cache\n        cache_insert(conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx);\n\n        // Start remote io\n        ev_io_start(EV_A_ & remote_ctx->io);\n        ev_timer_start(EV_A_ & remote_ctx->watcher);\n    }\n\n    if (offset > 0) {\n        buf->len -= offset;\n        memmove(buf->data, buf->data + offset, buf->len);\n    }\n\n    int err = server_ctx->crypto->encrypt_all(buf, server_ctx->crypto->cipher, buf_size);\n\n    if (err) {\n        // drop the packet silently\n        goto CLEAN_UP;\n    }\n\n    if (buf->len > packet_size) {\n        if (verbose) {\n            LOGI(\"[udp] server_recv_sendto fragmentation, MTU at least be: \" SSIZE_FMT, buf->len + PACKET_HEADER_SIZE);\n        }\n    }\n\n    int s = sendto(remote_ctx->fd, buf->data, buf->len, 0, remote_addr, remote_addr_len);\n\n    if (s == -1) {\n        ERROR(\"[udp] server_recv_sendto\");\n    }\n\n#else\n\n    int cache_hit  = 0;\n    int need_query = 0;\n\n    char *addr_header = buf->data + offset;\n\n    if (buf->len - addr_header_len > packet_size) {\n        if (verbose) {\n            LOGI(\"[udp] server_recv_sendto fragmentation, MTU at least be: \" SSIZE_FMT,\n                 buf->len - addr_header_len + PACKET_HEADER_SIZE);\n        }\n    }\n\n    if (remote_ctx != NULL) {\n        cache_hit = 1;\n        if (dst_addr.ss_family != AF_INET && dst_addr.ss_family != AF_INET6) {\n            need_query = 1;\n        }\n    } else {\n        if (dst_addr.ss_family == AF_INET || dst_addr.ss_family == AF_INET6) {\n            int remotefd = create_remote_socket(dst_addr.ss_family == AF_INET6);\n            if (remotefd != -1) {\n                setnonblocking(remotefd);\n#ifdef SO_BROADCAST\n                set_broadcast(remotefd);\n#endif\n#ifdef SO_NOSIGPIPE\n                set_nosigpipe(remotefd);\n#endif\n#ifdef IP_TOS\n                // Set QoS flag\n                int tos   = 46 << 2;\n                int rc = setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));\n                if (rc < 0 && errno != ENOPROTOOPT) {\n                    LOGE(\"setting ipv4 dscp failed: %d\", errno);\n                }\n#ifdef IPV6_TCLASS\n                rc = setsockopt(remotefd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos));\n                if (rc < 0 && errno != ENOPROTOOPT) {\n                    LOGE(\"setting ipv6 dscp failed: %d\", errno);\n                }\n#endif\n#endif\n#ifdef SET_INTERFACE\n                if (server_ctx->iface) {\n                    if (setinterface(remotefd, server_ctx->iface) == -1)\n                        ERROR(\"setinterface\");\n                }\n#endif\n                remote_ctx             = new_remote(remotefd, server_ctx);\n                remote_ctx->src_addr   = src_addr;\n                remote_ctx->server_ctx = server_ctx;\n                memcpy(&remote_ctx->dst_addr, &dst_addr, sizeof(struct sockaddr_storage));\n            } else {\n                ERROR(\"[udp] bind() error\");\n                goto CLEAN_UP;\n            }\n        }\n    }\n\n    if (remote_ctx != NULL && !need_query) {\n        size_t addr_len = get_sockaddr_len((struct sockaddr *)&dst_addr);\n        int s           = sendto(remote_ctx->fd, buf->data + addr_header_len,\n                                 buf->len - addr_header_len, 0,\n                                 (struct sockaddr *)&dst_addr, addr_len);\n\n        if (s == -1) {\n            ERROR(\"[udp] sendto_remote\");\n            if (!cache_hit) {\n                close_and_free_remote(EV_A_ remote_ctx);\n            }\n        } else {\n            if (!cache_hit) {\n                // Add to conn cache\n                remote_ctx->af = dst_addr.ss_family;\n                char *key = hash_key(remote_ctx->af, &remote_ctx->src_addr);\n                cache_insert(server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx);\n\n                ev_io_start(EV_A_ & remote_ctx->io);\n                ev_timer_start(EV_A_ & remote_ctx->watcher);\n            }\n        }\n    } else {\n        struct query_ctx *query_ctx = new_query_ctx(buf->data + addr_header_len,\n                                                    buf->len - addr_header_len);\n        query_ctx->server_ctx      = server_ctx;\n        query_ctx->addr_header_len = addr_header_len;\n        query_ctx->src_addr        = src_addr;\n        memcpy(query_ctx->addr_header, addr_header, addr_header_len);\n\n        if (need_query) {\n            query_ctx->remote_ctx = remote_ctx;\n        }\n\n        resolv_start(host, htons(atoi(port)), resolv_cb, resolv_free_cb, query_ctx);\n    }\n#endif\n\nCLEAN_UP:\n    bfree(buf);\n    ss_free(buf);\n}\n\nvoid\nfree_cb(void *key, void *element)\n{\n    remote_ctx_t *remote_ctx = (remote_ctx_t *)element;\n\n    if (verbose) {\n        LOGI(\"[udp] one connection freed\");\n    }\n\n    close_and_free_remote(EV_DEFAULT, remote_ctx);\n}\n\nint\ninit_udprelay(const char *server_host, const char *server_port,\n#ifdef MODULE_LOCAL\n              const struct sockaddr *remote_addr, const int remote_addr_len,\n#ifdef MODULE_TUNNEL\n              const ss_addr_t tunnel_addr,\n#endif\n#endif\n              int mtu, crypto_t *crypto, int timeout, const char *iface)\n{\n    s_port = server_port;\n    // Initialize ev loop\n    struct ev_loop *loop = EV_DEFAULT;\n\n    // Initialize MTU\n    if (mtu > 0) {\n        packet_size = mtu - PACKET_HEADER_SIZE;\n        buf_size    = packet_size * 2;\n    }\n\n    // ////////////////////////////////////////////////\n    // Setup server context\n\n    // Bind to port\n    int serverfd = create_server_socket(server_host, server_port);\n    if (serverfd < 0) {\n        return -1;\n    }\n    setnonblocking(serverfd);\n\n    // Initialize cache\n    struct cache *conn_cache;\n    cache_create(&conn_cache, MAX_UDP_CONN_NUM, free_cb);\n\n    server_ctx_t *server_ctx = new_server_ctx(serverfd);\n#ifdef MODULE_REMOTE\n    server_ctx->loop = loop;\n#endif\n    server_ctx->timeout    = max(timeout, MIN_UDP_TIMEOUT);\n    server_ctx->crypto     = crypto;\n    server_ctx->iface      = iface;\n    server_ctx->conn_cache = conn_cache;\n#ifdef MODULE_LOCAL\n    server_ctx->remote_addr     = remote_addr;\n    server_ctx->remote_addr_len = remote_addr_len;\n#ifdef MODULE_TUNNEL\n    server_ctx->tunnel_addr = tunnel_addr;\n#endif\n#endif\n\n    ev_io_start(loop, &server_ctx->io);\n\n    server_ctx_list[server_num++] = server_ctx;\n\n    return serverfd;\n}\n\nvoid\nfree_udprelay()\n{\n    struct ev_loop *loop = EV_DEFAULT;\n    while (server_num > 0) {\n        server_ctx_t *server_ctx = server_ctx_list[--server_num];\n        ev_io_stop(loop, &server_ctx->io);\n        close(server_ctx->fd);\n        cache_delete(server_ctx->conn_cache, 0);\n#ifdef MODULE_LOCAL\n        free((char*) server_ctx->remote_addr);\n#endif\n        ss_free(server_ctx);\n        server_ctx_list[server_num] = NULL;\n    }\n}\n"
  },
  {
    "path": "src/udprelay.h",
    "content": "/*\n * udprelay.h - Define UDP relay's buffers and callbacks\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _UDPRELAY_H\n#define _UDPRELAY_H\n\n#include <time.h>\n\n#ifdef HAVE_LIBEV_EV_H\n#include <libev/ev.h>\n#else\n#include <ev.h>\n#endif\n\n#include \"crypto.h\"\n#include \"jconf.h\"\n\n#ifdef MODULE_REMOTE\n#include \"resolv.h\"\n#endif\n\n#include \"cache.h\"\n\n#include \"common.h\"\n\n#define MAX_UDP_PACKET_SIZE (65507)\n\n#define PACKET_HEADER_SIZE (1 + 28 + 2 + 64)\n#define DEFAULT_PACKET_SIZE 1397 // 1492 - PACKET_HEADER_SIZE = 1397, the default MTU for UDP relay\n#define MAX_ADDR_HEADER_SIZE (1 + 256 + 2) // 1-byte atyp + 256-byte hostname + 2-byte port\n\ntypedef struct server_ctx {\n    ev_io io;\n    int fd;\n    crypto_t *crypto;\n    int timeout;\n    const char *iface;\n    struct cache *conn_cache;\n#ifdef MODULE_LOCAL\n    const struct sockaddr *remote_addr;\n    int remote_addr_len;\n#ifdef MODULE_TUNNEL\n    ss_addr_t tunnel_addr;\n#endif\n#endif\n#ifdef MODULE_REMOTE\n    struct ev_loop *loop;\n#endif\n} server_ctx_t;\n\n#ifdef MODULE_REMOTE\ntypedef struct query_ctx {\n    struct sockaddr_storage src_addr;\n    buffer_t *buf;\n    int addr_header_len;\n    char addr_header[MAX_ADDR_HEADER_SIZE];\n    struct server_ctx *server_ctx;\n    struct remote_ctx *remote_ctx;\n} query_ctx_t;\n#endif\n\ntypedef struct remote_ctx {\n    ev_io io;\n    ev_timer watcher;\n    int af;\n    int fd;\n    struct sockaddr_storage src_addr;\n#ifdef MODULE_REMOTE\n    struct sockaddr_storage dst_addr;\n#endif\n    struct server_ctx *server_ctx;\n} remote_ctx_t;\n\n#endif // _UDPRELAY_H\n"
  },
  {
    "path": "src/uthash.h",
    "content": "/*\nCopyright (c) 2003-2016, Troy D. Hanson     http://troydhanson.github.com/uthash/\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\nIS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\nTO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER\nOR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef UTHASH_H\n#define UTHASH_H\n\n#define UTHASH_VERSION 2.0.1\n\n#include <string.h>   /* memcmp,strlen */\n#include <stddef.h>   /* ptrdiff_t */\n#include <stdlib.h>   /* exit() */\n\n/* These macros use decltype or the earlier __typeof GNU extension.\n   As decltype is only available in newer compilers (VS2010 or gcc 4.3+\n   when compiling c++ source) this code uses whatever method is needed\n   or, for VS2008 where neither is available, uses casting workarounds. */\n#if defined(_MSC_VER)   /* MS compiler */\n#if _MSC_VER >= 1600 && defined(__cplusplus)  /* VS2010 or newer in C++ mode */\n#define DECLTYPE(x) (decltype(x))\n#else                   /* VS2008 or older (or VS2010 in C mode) */\n#define NO_DECLTYPE\n#define DECLTYPE(x)\n#endif\n#elif defined(__BORLANDC__) || defined(__LCC__) || defined(__WATCOMC__)\n#define NO_DECLTYPE\n#define DECLTYPE(x)\n#else                   /* GNU, Sun and other compilers */\n#define DECLTYPE(x) (__typeof(x))\n#endif\n\n#ifdef NO_DECLTYPE\n#define DECLTYPE_ASSIGN(dst,src)                                                 \\\ndo {                                                                             \\\n  char **_da_dst = (char**)(&(dst));                                             \\\n  *_da_dst = (char*)(src);                                                       \\\n} while (0)\n#else\n#define DECLTYPE_ASSIGN(dst,src)                                                 \\\ndo {                                                                             \\\n  (dst) = DECLTYPE(dst)(src);                                                    \\\n} while (0)\n#endif\n\n/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */\n#if defined(_WIN32)\n#if defined(_MSC_VER) && _MSC_VER >= 1600\n#include <stdint.h>\n#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__)\n#include <stdint.h>\n#else\ntypedef unsigned int uint32_t;\ntypedef unsigned char uint8_t;\n#endif\n#elif defined(__GNUC__) && !defined(__VXWORKS__)\n#include <stdint.h>\n#else\ntypedef unsigned int uint32_t;\ntypedef unsigned char uint8_t;\n#endif\n\n#ifndef uthash_fatal\n#define uthash_fatal(msg) exit(-1)        /* fatal error (out of memory,etc) */\n#endif\n#ifndef uthash_malloc\n#define uthash_malloc(sz) malloc(sz)      /* malloc fcn                      */\n#endif\n#ifndef uthash_free\n#define uthash_free(ptr,sz) free(ptr)     /* free fcn                        */\n#endif\n#ifndef uthash_strlen\n#define uthash_strlen(s) strlen(s)\n#endif\n#ifndef uthash_memcmp\n#define uthash_memcmp(a,b,n) memcmp(a,b,n)\n#endif\n\n#ifndef uthash_noexpand_fyi\n#define uthash_noexpand_fyi(tbl)          /* can be defined to log noexpand  */\n#endif\n#ifndef uthash_expand_fyi\n#define uthash_expand_fyi(tbl)            /* can be defined to log expands   */\n#endif\n\n/* initial number of buckets */\n#define HASH_INITIAL_NUM_BUCKETS 32U     /* initial number of buckets        */\n#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */\n#define HASH_BKT_CAPACITY_THRESH 10U     /* expand when bucket count reaches */\n\n/* calculate the element whose hash handle address is hhp */\n#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))\n/* calculate the hash handle from element address elp */\n#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle *)(((char*)(elp)) + ((tbl)->hho)))\n\n#define HASH_VALUE(keyptr,keylen,hashv)                                          \\\ndo {                                                                             \\\n  HASH_FCN(keyptr, keylen, hashv);                                               \\\n} while (0)\n\n#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out)                 \\\ndo {                                                                             \\\n  (out) = NULL;                                                                  \\\n  if (head) {                                                                    \\\n    unsigned _hf_bkt;                                                            \\\n    HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt);                  \\\n    if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) {                         \\\n      HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \\\n    }                                                                            \\\n  }                                                                              \\\n} while (0)\n\n#define HASH_FIND(hh,head,keyptr,keylen,out)                                     \\\ndo {                                                                             \\\n  unsigned _hf_hashv;                                                            \\\n  HASH_VALUE(keyptr, keylen, _hf_hashv);                                         \\\n  HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out);               \\\n} while (0)\n\n#ifdef HASH_BLOOM\n#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM)\n#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL)\n#define HASH_BLOOM_MAKE(tbl)                                                     \\\ndo {                                                                             \\\n  (tbl)->bloom_nbits = HASH_BLOOM;                                               \\\n  (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN);                 \\\n  if (!((tbl)->bloom_bv))  { uthash_fatal( \"out of memory\"); }                   \\\n  memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN);                                \\\n  (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE;                                       \\\n} while (0)\n\n#define HASH_BLOOM_FREE(tbl)                                                     \\\ndo {                                                                             \\\n  uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN);                              \\\n} while (0)\n\n#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U)))\n#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U)))\n\n#define HASH_BLOOM_ADD(tbl,hashv)                                                \\\n  HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U)))\n\n#define HASH_BLOOM_TEST(tbl,hashv)                                               \\\n  HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U)))\n\n#else\n#define HASH_BLOOM_MAKE(tbl)\n#define HASH_BLOOM_FREE(tbl)\n#define HASH_BLOOM_ADD(tbl,hashv)\n#define HASH_BLOOM_TEST(tbl,hashv) (1)\n#define HASH_BLOOM_BYTELEN 0U\n#endif\n\n#define HASH_MAKE_TABLE(hh,head)                                                 \\\ndo {                                                                             \\\n  (head)->hh.tbl = (UT_hash_table*)uthash_malloc(                                \\\n                  sizeof(UT_hash_table));                                        \\\n  if (!((head)->hh.tbl))  { uthash_fatal( \"out of memory\"); }                    \\\n  memset((head)->hh.tbl, 0, sizeof(UT_hash_table));                              \\\n  (head)->hh.tbl->tail = &((head)->hh);                                          \\\n  (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS;                        \\\n  (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2;              \\\n  (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head);                    \\\n  (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc(                      \\\n          HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));               \\\n  if (! (head)->hh.tbl->buckets) { uthash_fatal( \"out of memory\"); }             \\\n  memset((head)->hh.tbl->buckets, 0,                                             \\\n          HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));               \\\n  HASH_BLOOM_MAKE((head)->hh.tbl);                                               \\\n  (head)->hh.tbl->signature = HASH_SIGNATURE;                                    \\\n} while (0)\n\n#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \\\ndo {                                                                             \\\n  (replaced) = NULL;                                                             \\\n  HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \\\n  if (replaced) {                                                                \\\n     HASH_DELETE(hh, head, replaced);                                            \\\n  }                                                                              \\\n  HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \\\n} while (0)\n\n#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \\\ndo {                                                                             \\\n  (replaced) = NULL;                                                             \\\n  HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \\\n  if (replaced) {                                                                \\\n     HASH_DELETE(hh, head, replaced);                                            \\\n  }                                                                              \\\n  HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \\\n} while (0)\n\n#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced)                   \\\ndo {                                                                             \\\n  unsigned _hr_hashv;                                                            \\\n  HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv);                         \\\n  HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \\\n} while (0)\n\n#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn)    \\\ndo {                                                                             \\\n  unsigned _hr_hashv;                                                            \\\n  HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv);                         \\\n  HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \\\n} while (0)\n\n#define HASH_APPEND_LIST(hh, head, add)                                          \\\ndo {                                                                             \\\n  (add)->hh.next = NULL;                                                         \\\n  (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail);           \\\n  (head)->hh.tbl->tail->next = (add);                                            \\\n  (head)->hh.tbl->tail = &((add)->hh);                                           \\\n} while (0)\n\n#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \\\ndo {                                                                             \\\n  unsigned _ha_bkt;                                                              \\\n  (add)->hh.hashv = (hashval);                                                   \\\n  (add)->hh.key = (char*) (keyptr);                                              \\\n  (add)->hh.keylen = (unsigned) (keylen_in);                                     \\\n  if (!(head)) {                                                                 \\\n    (add)->hh.next = NULL;                                                       \\\n    (add)->hh.prev = NULL;                                                       \\\n    (head) = (add);                                                              \\\n    HASH_MAKE_TABLE(hh, head);                                                   \\\n  } else {                                                                       \\\n    struct UT_hash_handle *_hs_iter = &(head)->hh;                               \\\n    (add)->hh.tbl = (head)->hh.tbl;                                              \\\n    do {                                                                         \\\n      if (cmpfcn(DECLTYPE(head) ELMT_FROM_HH((head)->hh.tbl, _hs_iter), add) > 0) \\\n        break;                                                                   \\\n    } while ((_hs_iter = _hs_iter->next));                                       \\\n    if (_hs_iter) {                                                              \\\n      (add)->hh.next = _hs_iter;                                                 \\\n      if (((add)->hh.prev = _hs_iter->prev)) {                                   \\\n        HH_FROM_ELMT((head)->hh.tbl, _hs_iter->prev)->next = (add);              \\\n      } else {                                                                   \\\n        (head) = (add);                                                          \\\n      }                                                                          \\\n      _hs_iter->prev = (add);                                                    \\\n    } else {                                                                     \\\n      HASH_APPEND_LIST(hh, head, add);                                           \\\n    }                                                                            \\\n  }                                                                              \\\n  (head)->hh.tbl->num_items++;                                                   \\\n  HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt);                    \\\n  HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], &(add)->hh);                 \\\n  HASH_BLOOM_ADD((head)->hh.tbl, hashval);                                       \\\n  HASH_EMIT_KEY(hh, head, keyptr, keylen_in);                                    \\\n  HASH_FSCK(hh, head);                                                           \\\n} while (0)\n\n#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn)             \\\ndo {                                                                             \\\n  unsigned _hs_hashv;                                                            \\\n  HASH_VALUE(keyptr, keylen_in, _hs_hashv);                                      \\\n  HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \\\n} while (0)\n\n#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \\\n  HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn)\n\n#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn)                 \\\n  HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn)\n\n#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add)        \\\ndo {                                                                             \\\n  unsigned _ha_bkt;                                                              \\\n  (add)->hh.hashv = (hashval);                                                   \\\n  (add)->hh.key = (char*) (keyptr);                                              \\\n  (add)->hh.keylen = (unsigned) (keylen_in);                                     \\\n  if (!(head)) {                                                                 \\\n    (add)->hh.next = NULL;                                                       \\\n    (add)->hh.prev = NULL;                                                       \\\n    (head) = (add);                                                              \\\n    HASH_MAKE_TABLE(hh, head);                                                   \\\n  } else {                                                                       \\\n    (add)->hh.tbl = (head)->hh.tbl;                                              \\\n    HASH_APPEND_LIST(hh, head, add);                                             \\\n  }                                                                              \\\n  (head)->hh.tbl->num_items++;                                                   \\\n  HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt);                    \\\n  HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], &(add)->hh);                 \\\n  HASH_BLOOM_ADD((head)->hh.tbl, hashval);                                       \\\n  HASH_EMIT_KEY(hh, head, keyptr, keylen_in);                                    \\\n  HASH_FSCK(hh, head);                                                           \\\n} while (0)\n\n#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add)                            \\\ndo {                                                                             \\\n  unsigned _ha_hashv;                                                            \\\n  HASH_VALUE(keyptr, keylen_in, _ha_hashv);                                      \\\n  HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add);      \\\n} while (0)\n\n#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add)            \\\n  HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add)\n\n#define HASH_ADD(hh,head,fieldname,keylen_in,add)                                \\\n  HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add)\n\n#define HASH_TO_BKT(hashv,num_bkts,bkt)                                          \\\ndo {                                                                             \\\n  bkt = ((hashv) & ((num_bkts) - 1U));                                           \\\n} while (0)\n\n/* delete \"delptr\" from the hash table.\n * \"the usual\" patch-up process for the app-order doubly-linked-list.\n * The use of _hd_hh_del below deserves special explanation.\n * These used to be expressed using (delptr) but that led to a bug\n * if someone used the same symbol for the head and deletee, like\n *  HASH_DELETE(hh,users,users);\n * We want that to work, but by changing the head (users) below\n * we were forfeiting our ability to further refer to the deletee (users)\n * in the patch-up process. Solution: use scratch space to\n * copy the deletee pointer, then the latter references are via that\n * scratch pointer rather than through the repointed (users) symbol.\n */\n#define HASH_DELETE(hh,head,delptr)                                              \\\ndo {                                                                             \\\n    struct UT_hash_handle *_hd_hh_del;                                           \\\n    if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) )  {         \\\n        uthash_free((head)->hh.tbl->buckets,                                     \\\n                    (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \\\n        HASH_BLOOM_FREE((head)->hh.tbl);                                         \\\n        uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                      \\\n        head = NULL;                                                             \\\n    } else {                                                                     \\\n        unsigned _hd_bkt;                                                        \\\n        _hd_hh_del = &((delptr)->hh);                                            \\\n        if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) {     \\\n            (head)->hh.tbl->tail =                                               \\\n                (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) +               \\\n                (head)->hh.tbl->hho);                                            \\\n        }                                                                        \\\n        if ((delptr)->hh.prev != NULL) {                                         \\\n            ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) +                  \\\n                    (head)->hh.tbl->hho))->next = (delptr)->hh.next;             \\\n        } else {                                                                 \\\n            DECLTYPE_ASSIGN(head,(delptr)->hh.next);                             \\\n        }                                                                        \\\n        if (_hd_hh_del->next != NULL) {                                          \\\n            ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next +                     \\\n                    (head)->hh.tbl->hho))->prev =                                \\\n                    _hd_hh_del->prev;                                            \\\n        }                                                                        \\\n        HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt);   \\\n        HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del);        \\\n        (head)->hh.tbl->num_items--;                                             \\\n    }                                                                            \\\n    HASH_FSCK(hh,head);                                                          \\\n} while (0)\n\n\n/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */\n#define HASH_FIND_STR(head,findstr,out)                                          \\\n    HASH_FIND(hh,head,findstr,(unsigned)uthash_strlen(findstr),out)\n#define HASH_ADD_STR(head,strfield,add)                                          \\\n    HASH_ADD(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add)\n#define HASH_REPLACE_STR(head,strfield,add,replaced)                             \\\n    HASH_REPLACE(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add,replaced)\n#define HASH_FIND_INT(head,findint,out)                                          \\\n    HASH_FIND(hh,head,findint,sizeof(int),out)\n#define HASH_ADD_INT(head,intfield,add)                                          \\\n    HASH_ADD(hh,head,intfield,sizeof(int),add)\n#define HASH_REPLACE_INT(head,intfield,add,replaced)                             \\\n    HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)\n#define HASH_FIND_PTR(head,findptr,out)                                          \\\n    HASH_FIND(hh,head,findptr,sizeof(void *),out)\n#define HASH_ADD_PTR(head,ptrfield,add)                                          \\\n    HASH_ADD(hh,head,ptrfield,sizeof(void *),add)\n#define HASH_REPLACE_PTR(head,ptrfield,add,replaced)                             \\\n    HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)\n#define HASH_DEL(head,delptr)                                                    \\\n    HASH_DELETE(hh,head,delptr)\n\n/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.\n * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.\n */\n#ifdef HASH_DEBUG\n#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)\n#define HASH_FSCK(hh,head)                                                       \\\ndo {                                                                             \\\n    struct UT_hash_handle *_thh;                                                 \\\n    if (head) {                                                                  \\\n        unsigned _bkt_i;                                                         \\\n        unsigned _count;                                                         \\\n        char *_prev;                                                             \\\n        _count = 0;                                                              \\\n        for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) {       \\\n            unsigned _bkt_count = 0;                                             \\\n            _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head;                      \\\n            _prev = NULL;                                                        \\\n            while (_thh) {                                                       \\\n               if (_prev != (char*)(_thh->hh_prev)) {                            \\\n                   HASH_OOPS(\"invalid hh_prev %p, actual %p\\n\",                  \\\n                    _thh->hh_prev, _prev );                                      \\\n               }                                                                 \\\n               _bkt_count++;                                                     \\\n               _prev = (char*)(_thh);                                            \\\n               _thh = _thh->hh_next;                                             \\\n            }                                                                    \\\n            _count += _bkt_count;                                                \\\n            if ((head)->hh.tbl->buckets[_bkt_i].count !=  _bkt_count) {          \\\n               HASH_OOPS(\"invalid bucket count %u, actual %u\\n\",                 \\\n                (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count);              \\\n            }                                                                    \\\n        }                                                                        \\\n        if (_count != (head)->hh.tbl->num_items) {                               \\\n            HASH_OOPS(\"invalid hh item count %u, actual %u\\n\",                   \\\n                (head)->hh.tbl->num_items, _count );                             \\\n        }                                                                        \\\n        /* traverse hh in app order; check next/prev integrity, count */         \\\n        _count = 0;                                                              \\\n        _prev = NULL;                                                            \\\n        _thh =  &(head)->hh;                                                     \\\n        while (_thh) {                                                           \\\n           _count++;                                                             \\\n           if (_prev !=(char*)(_thh->prev)) {                                    \\\n              HASH_OOPS(\"invalid prev %p, actual %p\\n\",                          \\\n                    _thh->prev, _prev );                                         \\\n           }                                                                     \\\n           _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh);                    \\\n           _thh = ( _thh->next ?  (UT_hash_handle*)((char*)(_thh->next) +        \\\n                                  (head)->hh.tbl->hho) : NULL );                 \\\n        }                                                                        \\\n        if (_count != (head)->hh.tbl->num_items) {                               \\\n            HASH_OOPS(\"invalid app item count %u, actual %u\\n\",                  \\\n                (head)->hh.tbl->num_items, _count );                             \\\n        }                                                                        \\\n    }                                                                            \\\n} while (0)\n#else\n#define HASH_FSCK(hh,head)\n#endif\n\n/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to\n * the descriptor to which this macro is defined for tuning the hash function.\n * The app can #include <unistd.h> to get the prototype for write(2). */\n#ifdef HASH_EMIT_KEYS\n#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)                                   \\\ndo {                                                                             \\\n    unsigned _klen = fieldlen;                                                   \\\n    write(HASH_EMIT_KEYS, &_klen, sizeof(_klen));                                \\\n    write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen);                      \\\n} while (0)\n#else\n#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)\n#endif\n\n/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */\n#ifdef HASH_FUNCTION\n#define HASH_FCN HASH_FUNCTION\n#else\n#define HASH_FCN HASH_JEN\n#endif\n\n/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */\n#define HASH_BER(key,keylen,hashv)                                               \\\ndo {                                                                             \\\n  unsigned _hb_keylen=(unsigned)keylen;                                          \\\n  const unsigned char *_hb_key=(const unsigned char*)(key);                      \\\n  (hashv) = 0;                                                                   \\\n  while (_hb_keylen-- != 0U) {                                                   \\\n      (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++;                         \\\n  }                                                                              \\\n} while (0)\n\n\n/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at\n * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */\n#define HASH_SAX(key,keylen,hashv)                                               \\\ndo {                                                                             \\\n  unsigned _sx_i;                                                                \\\n  const unsigned char *_hs_key=(const unsigned char*)(key);                      \\\n  hashv = 0;                                                                     \\\n  for(_sx_i=0; _sx_i < keylen; _sx_i++) {                                        \\\n      hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i];                     \\\n  }                                                                              \\\n} while (0)\n/* FNV-1a variation */\n#define HASH_FNV(key,keylen,hashv)                                               \\\ndo {                                                                             \\\n  unsigned _fn_i;                                                                \\\n  const unsigned char *_hf_key=(const unsigned char*)(key);                      \\\n  hashv = 2166136261U;                                                           \\\n  for(_fn_i=0; _fn_i < keylen; _fn_i++) {                                        \\\n      hashv = hashv ^ _hf_key[_fn_i];                                            \\\n      hashv = hashv * 16777619U;                                                 \\\n  }                                                                              \\\n} while (0)\n\n#define HASH_OAT(key,keylen,hashv)                                               \\\ndo {                                                                             \\\n  unsigned _ho_i;                                                                \\\n  const unsigned char *_ho_key=(const unsigned char*)(key);                      \\\n  hashv = 0;                                                                     \\\n  for(_ho_i=0; _ho_i < keylen; _ho_i++) {                                        \\\n      hashv += _ho_key[_ho_i];                                                   \\\n      hashv += (hashv << 10);                                                    \\\n      hashv ^= (hashv >> 6);                                                     \\\n  }                                                                              \\\n  hashv += (hashv << 3);                                                         \\\n  hashv ^= (hashv >> 11);                                                        \\\n  hashv += (hashv << 15);                                                        \\\n} while (0)\n\n#define HASH_JEN_MIX(a,b,c)                                                      \\\ndo {                                                                             \\\n  a -= b; a -= c; a ^= ( c >> 13 );                                              \\\n  b -= c; b -= a; b ^= ( a << 8 );                                               \\\n  c -= a; c -= b; c ^= ( b >> 13 );                                              \\\n  a -= b; a -= c; a ^= ( c >> 12 );                                              \\\n  b -= c; b -= a; b ^= ( a << 16 );                                              \\\n  c -= a; c -= b; c ^= ( b >> 5 );                                               \\\n  a -= b; a -= c; a ^= ( c >> 3 );                                               \\\n  b -= c; b -= a; b ^= ( a << 10 );                                              \\\n  c -= a; c -= b; c ^= ( b >> 15 );                                              \\\n} while (0)\n\n#define HASH_JEN(key,keylen,hashv)                                               \\\ndo {                                                                             \\\n  unsigned _hj_i,_hj_j,_hj_k;                                                    \\\n  unsigned const char *_hj_key=(unsigned const char*)(key);                      \\\n  hashv = 0xfeedbeefu;                                                           \\\n  _hj_i = _hj_j = 0x9e3779b9u;                                                   \\\n  _hj_k = (unsigned)(keylen);                                                    \\\n  while (_hj_k >= 12U) {                                                         \\\n    _hj_i +=    (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 )                      \\\n        + ( (unsigned)_hj_key[2] << 16 )                                         \\\n        + ( (unsigned)_hj_key[3] << 24 ) );                                      \\\n    _hj_j +=    (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 )                      \\\n        + ( (unsigned)_hj_key[6] << 16 )                                         \\\n        + ( (unsigned)_hj_key[7] << 24 ) );                                      \\\n    hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 )                         \\\n        + ( (unsigned)_hj_key[10] << 16 )                                        \\\n        + ( (unsigned)_hj_key[11] << 24 ) );                                     \\\n                                                                                 \\\n     HASH_JEN_MIX(_hj_i, _hj_j, hashv);                                          \\\n                                                                                 \\\n     _hj_key += 12;                                                              \\\n     _hj_k -= 12U;                                                               \\\n  }                                                                              \\\n  hashv += (unsigned)(keylen);                                                   \\\n  switch ( _hj_k ) {                                                             \\\n     case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */        \\\n     case 10: hashv += ( (unsigned)_hj_key[9] << 16 );  /* FALLTHROUGH */        \\\n     case 9:  hashv += ( (unsigned)_hj_key[8] << 8 );   /* FALLTHROUGH */        \\\n     case 8:  _hj_j += ( (unsigned)_hj_key[7] << 24 );  /* FALLTHROUGH */        \\\n     case 7:  _hj_j += ( (unsigned)_hj_key[6] << 16 );  /* FALLTHROUGH */        \\\n     case 6:  _hj_j += ( (unsigned)_hj_key[5] << 8 );   /* FALLTHROUGH */        \\\n     case 5:  _hj_j += _hj_key[4];                      /* FALLTHROUGH */        \\\n     case 4:  _hj_i += ( (unsigned)_hj_key[3] << 24 );  /* FALLTHROUGH */        \\\n     case 3:  _hj_i += ( (unsigned)_hj_key[2] << 16 );  /* FALLTHROUGH */        \\\n     case 2:  _hj_i += ( (unsigned)_hj_key[1] << 8 );   /* FALLTHROUGH */        \\\n     case 1:  _hj_i += _hj_key[0];                                               \\\n  }                                                                              \\\n  HASH_JEN_MIX(_hj_i, _hj_j, hashv);                                             \\\n} while (0)\n\n/* The Paul Hsieh hash function */\n#undef get16bits\n#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__)             \\\n  || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)\n#define get16bits(d) (*((const uint16_t *) (d)))\n#endif\n\n#if !defined (get16bits)\n#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)             \\\n                       +(uint32_t)(((const uint8_t *)(d))[0]) )\n#endif\n#define HASH_SFH(key,keylen,hashv)                                               \\\ndo {                                                                             \\\n  unsigned const char *_sfh_key=(unsigned const char*)(key);                     \\\n  uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen;                                \\\n                                                                                 \\\n  unsigned _sfh_rem = _sfh_len & 3U;                                             \\\n  _sfh_len >>= 2;                                                                \\\n  hashv = 0xcafebabeu;                                                           \\\n                                                                                 \\\n  /* Main loop */                                                                \\\n  for (;_sfh_len > 0U; _sfh_len--) {                                             \\\n    hashv    += get16bits (_sfh_key);                                            \\\n    _sfh_tmp  = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv;              \\\n    hashv     = (hashv << 16) ^ _sfh_tmp;                                        \\\n    _sfh_key += 2U*sizeof (uint16_t);                                            \\\n    hashv    += hashv >> 11;                                                     \\\n  }                                                                              \\\n                                                                                 \\\n  /* Handle end cases */                                                         \\\n  switch (_sfh_rem) {                                                            \\\n    case 3: hashv += get16bits (_sfh_key);                                       \\\n            hashv ^= hashv << 16;                                                \\\n            hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18;              \\\n            hashv += hashv >> 11;                                                \\\n            break;                                                               \\\n    case 2: hashv += get16bits (_sfh_key);                                       \\\n            hashv ^= hashv << 11;                                                \\\n            hashv += hashv >> 17;                                                \\\n            break;                                                               \\\n    case 1: hashv += *_sfh_key;                                                  \\\n            hashv ^= hashv << 10;                                                \\\n            hashv += hashv >> 1;                                                 \\\n  }                                                                              \\\n                                                                                 \\\n    /* Force \"avalanching\" of final 127 bits */                                  \\\n    hashv ^= hashv << 3;                                                         \\\n    hashv += hashv >> 5;                                                         \\\n    hashv ^= hashv << 4;                                                         \\\n    hashv += hashv >> 17;                                                        \\\n    hashv ^= hashv << 25;                                                        \\\n    hashv += hashv >> 6;                                                         \\\n} while (0)\n\n#ifdef HASH_USING_NO_STRICT_ALIASING\n/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.\n * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.\n * MurmurHash uses the faster approach only on CPU's where we know it's safe.\n *\n * Note the preprocessor built-in defines can be emitted using:\n *\n *   gcc -m64 -dM -E - < /dev/null                  (on gcc)\n *   cc -## a.c (where a.c is a simple test file)   (Sun Studio)\n */\n#if (defined(__i386__) || defined(__x86_64__)  || defined(_M_IX86))\n#define MUR_GETBLOCK(p,i) p[i]\n#else /* non intel */\n#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL)\n#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL)\n#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL)\n#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL)\n#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))\n#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))\n#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))\n#define MUR_TWO_TWO(p)   ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))\n#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >>  8))\n#else /* assume little endian non-intel */\n#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))\n#define MUR_TWO_TWO(p)   ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))\n#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) <<  8))\n#endif\n#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) :           \\\n                            (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \\\n                             (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) :  \\\n                                                      MUR_ONE_THREE(p))))\n#endif\n#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))\n#define MUR_FMIX(_h) \\\ndo {                 \\\n  _h ^= _h >> 16;    \\\n  _h *= 0x85ebca6bu; \\\n  _h ^= _h >> 13;    \\\n  _h *= 0xc2b2ae35u; \\\n  _h ^= _h >> 16;    \\\n} while (0)\n\n#define HASH_MUR(key,keylen,hashv)                                     \\\ndo {                                                                   \\\n  const uint8_t *_mur_data = (const uint8_t*)(key);                    \\\n  const int _mur_nblocks = (int)(keylen) / 4;                          \\\n  uint32_t _mur_h1 = 0xf88D5353u;                                      \\\n  uint32_t _mur_c1 = 0xcc9e2d51u;                                      \\\n  uint32_t _mur_c2 = 0x1b873593u;                                      \\\n  uint32_t _mur_k1 = 0;                                                \\\n  const uint8_t *_mur_tail;                                            \\\n  const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \\\n  int _mur_i;                                                          \\\n  for(_mur_i = -_mur_nblocks; _mur_i!=0; _mur_i++) {                   \\\n    _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i);                        \\\n    _mur_k1 *= _mur_c1;                                                \\\n    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \\\n    _mur_k1 *= _mur_c2;                                                \\\n                                                                       \\\n    _mur_h1 ^= _mur_k1;                                                \\\n    _mur_h1 = MUR_ROTL32(_mur_h1,13);                                  \\\n    _mur_h1 = (_mur_h1*5U) + 0xe6546b64u;                              \\\n  }                                                                    \\\n  _mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4));          \\\n  _mur_k1=0;                                                           \\\n  switch((keylen) & 3U) {                                              \\\n    case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \\\n    case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8;  /* FALLTHROUGH */ \\\n    case 1: _mur_k1 ^= (uint32_t)_mur_tail[0];                         \\\n    _mur_k1 *= _mur_c1;                                                \\\n    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \\\n    _mur_k1 *= _mur_c2;                                                \\\n    _mur_h1 ^= _mur_k1;                                                \\\n  }                                                                    \\\n  _mur_h1 ^= (uint32_t)(keylen);                                       \\\n  MUR_FMIX(_mur_h1);                                                   \\\n  hashv = _mur_h1;                                                     \\\n} while (0)\n#endif  /* HASH_USING_NO_STRICT_ALIASING */\n\n/* iterate over items in a known bucket to find desired item */\n#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out)               \\\ndo {                                                                             \\\n  if ((head).hh_head != NULL) {                                                  \\\n    DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head));                     \\\n  } else {                                                                       \\\n    (out) = NULL;                                                                \\\n  }                                                                              \\\n  while ((out) != NULL) {                                                        \\\n    if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) {       \\\n      if (uthash_memcmp((out)->hh.key, keyptr, keylen_in) == 0) {                \\\n        break;                                                                   \\\n      }                                                                          \\\n    }                                                                            \\\n    if ((out)->hh.hh_next != NULL) {                                             \\\n      DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next));                \\\n    } else {                                                                     \\\n      (out) = NULL;                                                              \\\n    }                                                                            \\\n  }                                                                              \\\n} while (0)\n\n/* add an item to a bucket  */\n#define HASH_ADD_TO_BKT(head,addhh)                                              \\\ndo {                                                                             \\\n head.count++;                                                                   \\\n (addhh)->hh_next = head.hh_head;                                                \\\n (addhh)->hh_prev = NULL;                                                        \\\n if (head.hh_head != NULL) { (head).hh_head->hh_prev = (addhh); }                \\\n (head).hh_head=addhh;                                                           \\\n if ((head.count >= ((head.expand_mult+1U) * HASH_BKT_CAPACITY_THRESH))          \\\n     && ((addhh)->tbl->noexpand != 1U)) {                                        \\\n       HASH_EXPAND_BUCKETS((addhh)->tbl);                                        \\\n }                                                                               \\\n} while (0)\n\n/* remove an item from a given bucket */\n#define HASH_DEL_IN_BKT(hh,head,hh_del)                                          \\\n    (head).count--;                                                              \\\n    if ((head).hh_head == hh_del) {                                              \\\n      (head).hh_head = hh_del->hh_next;                                          \\\n    }                                                                            \\\n    if (hh_del->hh_prev) {                                                       \\\n        hh_del->hh_prev->hh_next = hh_del->hh_next;                              \\\n    }                                                                            \\\n    if (hh_del->hh_next) {                                                       \\\n        hh_del->hh_next->hh_prev = hh_del->hh_prev;                              \\\n    }\n\n/* Bucket expansion has the effect of doubling the number of buckets\n * and redistributing the items into the new buckets. Ideally the\n * items will distribute more or less evenly into the new buckets\n * (the extent to which this is true is a measure of the quality of\n * the hash function as it applies to the key domain).\n *\n * With the items distributed into more buckets, the chain length\n * (item count) in each bucket is reduced. Thus by expanding buckets\n * the hash keeps a bound on the chain length. This bounded chain\n * length is the essence of how a hash provides constant time lookup.\n *\n * The calculation of tbl->ideal_chain_maxlen below deserves some\n * explanation. First, keep in mind that we're calculating the ideal\n * maximum chain length based on the *new* (doubled) bucket count.\n * In fractions this is just n/b (n=number of items,b=new num buckets).\n * Since the ideal chain length is an integer, we want to calculate\n * ceil(n/b). We don't depend on floating point arithmetic in this\n * hash, so to calculate ceil(n/b) with integers we could write\n *\n *      ceil(n/b) = (n/b) + ((n%b)?1:0)\n *\n * and in fact a previous version of this hash did just that.\n * But now we have improved things a bit by recognizing that b is\n * always a power of two. We keep its base 2 log handy (call it lb),\n * so now we can write this with a bit shift and logical AND:\n *\n *      ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)\n *\n */\n#define HASH_EXPAND_BUCKETS(tbl)                                                 \\\ndo {                                                                             \\\n    unsigned _he_bkt;                                                            \\\n    unsigned _he_bkt_i;                                                          \\\n    struct UT_hash_handle *_he_thh, *_he_hh_nxt;                                 \\\n    UT_hash_bucket *_he_new_buckets, *_he_newbkt;                                \\\n    _he_new_buckets = (UT_hash_bucket*)uthash_malloc(                            \\\n             2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket));            \\\n    if (!_he_new_buckets) { uthash_fatal( \"out of memory\"); }                    \\\n    memset(_he_new_buckets, 0,                                                   \\\n            2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket));             \\\n    tbl->ideal_chain_maxlen =                                                    \\\n       (tbl->num_items >> (tbl->log2_num_buckets+1U)) +                          \\\n       (((tbl->num_items & ((tbl->num_buckets*2U)-1U)) != 0U) ? 1U : 0U);        \\\n    tbl->nonideal_items = 0;                                                     \\\n    for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++)                \\\n    {                                                                            \\\n        _he_thh = tbl->buckets[ _he_bkt_i ].hh_head;                             \\\n        while (_he_thh != NULL) {                                                \\\n           _he_hh_nxt = _he_thh->hh_next;                                        \\\n           HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2U, _he_bkt);           \\\n           _he_newbkt = &(_he_new_buckets[ _he_bkt ]);                           \\\n           if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) {                \\\n             tbl->nonideal_items++;                                              \\\n             _he_newbkt->expand_mult = _he_newbkt->count /                       \\\n                                        tbl->ideal_chain_maxlen;                 \\\n           }                                                                     \\\n           _he_thh->hh_prev = NULL;                                              \\\n           _he_thh->hh_next = _he_newbkt->hh_head;                               \\\n           if (_he_newbkt->hh_head != NULL) { _he_newbkt->hh_head->hh_prev =     \\\n                _he_thh; }                                                       \\\n           _he_newbkt->hh_head = _he_thh;                                        \\\n           _he_thh = _he_hh_nxt;                                                 \\\n        }                                                                        \\\n    }                                                                            \\\n    uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \\\n    tbl->num_buckets *= 2U;                                                      \\\n    tbl->log2_num_buckets++;                                                     \\\n    tbl->buckets = _he_new_buckets;                                              \\\n    tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ?         \\\n        (tbl->ineff_expands+1U) : 0U;                                            \\\n    if (tbl->ineff_expands > 1U) {                                               \\\n        tbl->noexpand=1;                                                         \\\n        uthash_noexpand_fyi(tbl);                                                \\\n    }                                                                            \\\n    uthash_expand_fyi(tbl);                                                      \\\n} while (0)\n\n\n/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */\n/* Note that HASH_SORT assumes the hash handle name to be hh.\n * HASH_SRT was added to allow the hash handle name to be passed in. */\n#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)\n#define HASH_SRT(hh,head,cmpfcn)                                                 \\\ndo {                                                                             \\\n  unsigned _hs_i;                                                                \\\n  unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize;               \\\n  struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail;            \\\n  if (head != NULL) {                                                            \\\n      _hs_insize = 1;                                                            \\\n      _hs_looping = 1;                                                           \\\n      _hs_list = &((head)->hh);                                                  \\\n      while (_hs_looping != 0U) {                                                \\\n          _hs_p = _hs_list;                                                      \\\n          _hs_list = NULL;                                                       \\\n          _hs_tail = NULL;                                                       \\\n          _hs_nmerges = 0;                                                       \\\n          while (_hs_p != NULL) {                                                \\\n              _hs_nmerges++;                                                     \\\n              _hs_q = _hs_p;                                                     \\\n              _hs_psize = 0;                                                     \\\n              for ( _hs_i = 0; _hs_i  < _hs_insize; _hs_i++ ) {                  \\\n                  _hs_psize++;                                                   \\\n                  _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ?              \\\n                          ((void*)((char*)(_hs_q->next) +                        \\\n                          (head)->hh.tbl->hho)) : NULL);                         \\\n                  if (! (_hs_q) ) { break; }                                     \\\n              }                                                                  \\\n              _hs_qsize = _hs_insize;                                            \\\n              while ((_hs_psize > 0U) || ((_hs_qsize > 0U) && (_hs_q != NULL))) {\\\n                  if (_hs_psize == 0U) {                                         \\\n                      _hs_e = _hs_q;                                             \\\n                      _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ?          \\\n                              ((void*)((char*)(_hs_q->next) +                    \\\n                              (head)->hh.tbl->hho)) : NULL);                     \\\n                      _hs_qsize--;                                               \\\n                  } else if ( (_hs_qsize == 0U) || (_hs_q == NULL) ) {           \\\n                      _hs_e = _hs_p;                                             \\\n                      if (_hs_p != NULL){                                        \\\n                        _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ?        \\\n                                ((void*)((char*)(_hs_p->next) +                  \\\n                                (head)->hh.tbl->hho)) : NULL);                   \\\n                       }                                                         \\\n                      _hs_psize--;                                               \\\n                  } else if ((                                                   \\\n                      cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \\\n                             DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \\\n                             ) <= 0) {                                           \\\n                      _hs_e = _hs_p;                                             \\\n                      if (_hs_p != NULL){                                        \\\n                        _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ?        \\\n                               ((void*)((char*)(_hs_p->next) +                   \\\n                               (head)->hh.tbl->hho)) : NULL);                    \\\n                       }                                                         \\\n                      _hs_psize--;                                               \\\n                  } else {                                                       \\\n                      _hs_e = _hs_q;                                             \\\n                      _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ?          \\\n                              ((void*)((char*)(_hs_q->next) +                    \\\n                              (head)->hh.tbl->hho)) : NULL);                     \\\n                      _hs_qsize--;                                               \\\n                  }                                                              \\\n                  if ( _hs_tail != NULL ) {                                      \\\n                      _hs_tail->next = ((_hs_e != NULL) ?                        \\\n                            ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL);          \\\n                  } else {                                                       \\\n                      _hs_list = _hs_e;                                          \\\n                  }                                                              \\\n                  if (_hs_e != NULL) {                                           \\\n                  _hs_e->prev = ((_hs_tail != NULL) ?                            \\\n                     ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL);              \\\n                  }                                                              \\\n                  _hs_tail = _hs_e;                                              \\\n              }                                                                  \\\n              _hs_p = _hs_q;                                                     \\\n          }                                                                      \\\n          if (_hs_tail != NULL){                                                 \\\n            _hs_tail->next = NULL;                                               \\\n          }                                                                      \\\n          if ( _hs_nmerges <= 1U ) {                                             \\\n              _hs_looping=0;                                                     \\\n              (head)->hh.tbl->tail = _hs_tail;                                   \\\n              DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list));      \\\n          }                                                                      \\\n          _hs_insize *= 2U;                                                      \\\n      }                                                                          \\\n      HASH_FSCK(hh,head);                                                        \\\n }                                                                               \\\n} while (0)\n\n/* This function selects items from one hash into another hash.\n * The end result is that the selected items have dual presence\n * in both hashes. There is no copy of the items made; rather\n * they are added into the new hash through a secondary hash\n * hash handle that must be present in the structure. */\n#define HASH_SELECT(hh_dst, dst, hh_src, src, cond)                              \\\ndo {                                                                             \\\n  unsigned _src_bkt, _dst_bkt;                                                   \\\n  void *_last_elt=NULL, *_elt;                                                   \\\n  UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL;                         \\\n  ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst));                 \\\n  if (src != NULL) {                                                             \\\n    for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) {     \\\n      for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head;                \\\n          _src_hh != NULL;                                                       \\\n          _src_hh = _src_hh->hh_next) {                                          \\\n          _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh);                       \\\n          if (cond(_elt)) {                                                      \\\n            _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho);               \\\n            _dst_hh->key = _src_hh->key;                                         \\\n            _dst_hh->keylen = _src_hh->keylen;                                   \\\n            _dst_hh->hashv = _src_hh->hashv;                                     \\\n            _dst_hh->prev = _last_elt;                                           \\\n            _dst_hh->next = NULL;                                                \\\n            if (_last_elt_hh != NULL) { _last_elt_hh->next = _elt; }             \\\n            if (dst == NULL) {                                                   \\\n              DECLTYPE_ASSIGN(dst,_elt);                                         \\\n              HASH_MAKE_TABLE(hh_dst,dst);                                       \\\n            } else {                                                             \\\n              _dst_hh->tbl = (dst)->hh_dst.tbl;                                  \\\n            }                                                                    \\\n            HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt);    \\\n            HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh);            \\\n            (dst)->hh_dst.tbl->num_items++;                                      \\\n            _last_elt = _elt;                                                    \\\n            _last_elt_hh = _dst_hh;                                              \\\n          }                                                                      \\\n      }                                                                          \\\n    }                                                                            \\\n  }                                                                              \\\n  HASH_FSCK(hh_dst,dst);                                                         \\\n} while (0)\n\n#define HASH_CLEAR(hh,head)                                                      \\\ndo {                                                                             \\\n  if (head != NULL) {                                                            \\\n    uthash_free((head)->hh.tbl->buckets,                                         \\\n                (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket));      \\\n    HASH_BLOOM_FREE((head)->hh.tbl);                                             \\\n    uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                          \\\n    (head)=NULL;                                                                 \\\n  }                                                                              \\\n} while (0)\n\n#define HASH_OVERHEAD(hh,head)                                                   \\\n ((head != NULL) ? (                                                             \\\n (size_t)(((head)->hh.tbl->num_items   * sizeof(UT_hash_handle))   +             \\\n          ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket))   +             \\\n           sizeof(UT_hash_table)                                   +             \\\n           (HASH_BLOOM_BYTELEN))) : 0U)\n\n#ifdef NO_DECLTYPE\n#define HASH_ITER(hh,head,el,tmp)                                                \\\nfor(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \\\n  (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL)))\n#else\n#define HASH_ITER(hh,head,el,tmp)                                                \\\nfor(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL));      \\\n  (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL)))\n#endif\n\n/* obtain a count of items in the hash */\n#define HASH_COUNT(head) HASH_CNT(hh,head)\n#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U)\n\ntypedef struct UT_hash_bucket {\n   struct UT_hash_handle *hh_head;\n   unsigned count;\n\n   /* expand_mult is normally set to 0. In this situation, the max chain length\n    * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If\n    * the bucket's chain exceeds this length, bucket expansion is triggered).\n    * However, setting expand_mult to a non-zero value delays bucket expansion\n    * (that would be triggered by additions to this particular bucket)\n    * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.\n    * (The multiplier is simply expand_mult+1). The whole idea of this\n    * multiplier is to reduce bucket expansions, since they are expensive, in\n    * situations where we know that a particular bucket tends to be overused.\n    * It is better to let its chain length grow to a longer yet-still-bounded\n    * value, than to do an O(n) bucket expansion too often.\n    */\n   unsigned expand_mult;\n\n} UT_hash_bucket;\n\n/* random signature used only to find hash tables in external analysis */\n#define HASH_SIGNATURE 0xa0111fe1u\n#define HASH_BLOOM_SIGNATURE 0xb12220f2u\n\ntypedef struct UT_hash_table {\n   UT_hash_bucket *buckets;\n   unsigned num_buckets, log2_num_buckets;\n   unsigned num_items;\n   struct UT_hash_handle *tail; /* tail hh in app order, for fast append    */\n   ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */\n\n   /* in an ideal situation (all buckets used equally), no bucket would have\n    * more than ceil(#items/#buckets) items. that's the ideal chain length. */\n   unsigned ideal_chain_maxlen;\n\n   /* nonideal_items is the number of items in the hash whose chain position\n    * exceeds the ideal chain maxlen. these items pay the penalty for an uneven\n    * hash distribution; reaching them in a chain traversal takes >ideal steps */\n   unsigned nonideal_items;\n\n   /* ineffective expands occur when a bucket doubling was performed, but\n    * afterward, more than half the items in the hash had nonideal chain\n    * positions. If this happens on two consecutive expansions we inhibit any\n    * further expansion, as it's not helping; this happens when the hash\n    * function isn't a good fit for the key domain. When expansion is inhibited\n    * the hash will still work, albeit no longer in constant time. */\n   unsigned ineff_expands, noexpand;\n\n   uint32_t signature; /* used only to find hash tables in external analysis */\n#ifdef HASH_BLOOM\n   uint32_t bloom_sig; /* used only to test bloom exists in external analysis */\n   uint8_t *bloom_bv;\n   uint8_t bloom_nbits;\n#endif\n\n} UT_hash_table;\n\ntypedef struct UT_hash_handle {\n   struct UT_hash_table *tbl;\n   void *prev;                       /* prev element in app order      */\n   void *next;                       /* next element in app order      */\n   struct UT_hash_handle *hh_prev;   /* previous hh in bucket order    */\n   struct UT_hash_handle *hh_next;   /* next hh in bucket order        */\n   void *key;                        /* ptr to enclosing struct's key  */\n   unsigned keylen;                  /* enclosing struct's key len     */\n   unsigned hashv;                   /* result of hash-fcn(key)        */\n} UT_hash_handle;\n\n#endif /* UTHASH_H */\n"
  },
  {
    "path": "src/utils.c",
    "content": "/*\n * utils.c - Misc utilities\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <ctype.h>\n#ifndef __MINGW32__\n#include <unistd.h>\n#include <errno.h>\n#include <pwd.h>\n#include <grp.h>\n#else\n#include <malloc.h>\n#endif\n\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n\n#include <sodium.h>\n\n#include \"crypto.h\"\n#include \"utils.h\"\n\n#ifdef HAVE_SETRLIMIT\n#include <sys/time.h>\n#include <sys/resource.h>\n#endif\n\n#define INT_DIGITS 19           /* enough for 64 bit integer */\n\n#ifdef LIB_ONLY\nFILE *logfile;\n#endif\n\n#ifdef HAS_SYSLOG\nint use_syslog = 0;\n#endif\n\n#ifndef __MINGW32__\nvoid\nERROR(const char *s)\n{\n    char *msg = strerror(errno);\n    LOGE(\"%s: %s\", s, msg);\n}\n\n#endif\n\nint use_tty = 1;\n\nchar *\nss_itoa(int i)\n{\n    /* Room for INT_DIGITS digits, - and '\\0' */\n    static char buf[INT_DIGITS + 2];\n    char *p = buf + INT_DIGITS + 1;     /* points to terminating '\\0' */\n    if (i >= 0) {\n        do {\n            *--p = '0' + (i % 10);\n            i   /= 10;\n        } while (i != 0);\n        return p;\n    } else {                     /* i < 0 */\n        do {\n            *--p = '0' - (i % 10);\n            i   /= 10;\n        } while (i != 0);\n        *--p = '-';\n    }\n    return p;\n}\n\nint\nss_isnumeric(const char *s)\n{\n    if (!s || !*s)\n        return 0;\n    while (isdigit((unsigned char)*s))\n        ++s;\n    return *s == '\\0';\n}\n\n/*\n * setuid() and setgid() for a specified user.\n */\nint\nrun_as(const char *user)\n{\n#ifndef __MINGW32__\n    if (user[0]) {\n        /* Convert user to a long integer if it is a non-negative number.\n         * -1 means it is a user name. */\n        long uid = -1;\n        if (ss_isnumeric(user)) {\n            errno = 0;\n            char *endptr;\n            uid = strtol(user, &endptr, 10);\n            if (errno || endptr == user)\n                uid = -1;\n        }\n\n#ifdef HAVE_GETPWNAM_R\n        struct passwd pwdbuf, *pwd;\n        memset(&pwdbuf, 0, sizeof(struct passwd));\n        size_t buflen;\n        int err;\n\n        for (buflen = 128;; buflen *= 2) {\n            char buf[buflen];  /* variable length array */\n\n            /* Note that we use getpwnam_r() instead of getpwnam(),\n             * which returns its result in a statically allocated buffer and\n             * cannot be considered thread safe. */\n            err = uid >= 0 ? getpwuid_r((uid_t)uid, &pwdbuf, buf, buflen, &pwd)\n                  : getpwnam_r(user, &pwdbuf, buf, buflen, &pwd);\n\n            if (err == 0 && pwd) {\n                /* setgid first, because we may not be allowed to do it anymore after setuid */\n                if (setgid(pwd->pw_gid) != 0) {\n                    LOGE(\n                        \"Could not change group id to that of run_as user '%s': %s\",\n                        pwd->pw_name, strerror(errno));\n                    return 0;\n                }\n\n#ifndef __CYGWIN__\n                if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {\n                    LOGE(\"Could not change supplementary groups for user '%s'.\", pwd->pw_name);\n                    return 0;\n                }\n#endif\n\n                if (setuid(pwd->pw_uid) != 0) {\n                    LOGE(\n                        \"Could not change user id to that of run_as user '%s': %s\",\n                        pwd->pw_name, strerror(errno));\n                    return 0;\n                }\n                break;\n            } else if (err != ERANGE) {\n                if (err) {\n                    LOGE(\"run_as user '%s' could not be found: %s\", user,\n                         strerror(err));\n                } else {\n                    LOGE(\"run_as user '%s' could not be found.\", user);\n                }\n                return 0;\n            } else if (buflen >= 16 * 1024) {\n                /* If getpwnam_r() seems defective, call it quits rather than\n                 * keep on allocating ever larger buffers until we crash. */\n                LOGE(\n                    \"getpwnam_r() requires more than %u bytes of buffer space.\",\n                    (unsigned)buflen);\n                return 0;\n            }\n            /* Else try again with larger buffer. */\n        }\n#else\n        /* No getpwnam_r() :-(  We'll use getpwnam() and hope for the best. */\n        struct passwd *pwd;\n\n        if (!(pwd = uid >= 0 ? getpwuid((uid_t)uid) : getpwnam(user))) {\n            LOGE(\"run_as user %s could not be found.\", user);\n            return 0;\n        }\n        /* setgid first, because we may not allowed to do it anymore after setuid */\n        if (setgid(pwd->pw_gid) != 0) {\n            LOGE(\"Could not change group id to that of run_as user '%s': %s\",\n                 pwd->pw_name, strerror(errno));\n            return 0;\n        }\n        if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {\n            LOGE(\"Could not change supplementary groups for user '%s'.\", pwd->pw_name);\n            return 0;\n        }\n        if (setuid(pwd->pw_uid) != 0) {\n            LOGE(\"Could not change user id to that of run_as user '%s': %s\",\n                 pwd->pw_name, strerror(errno));\n            return 0;\n        }\n#endif\n    }\n#else\n    LOGE(\"run_as(): not implemented in MinGW port\");\n#endif\n\n    return 1;\n}\n\nchar *\nss_strndup(const char *s, size_t n)\n{\n    size_t len = strlen(s);\n    char *ret;\n\n    if (len <= n) {\n        return strdup(s);\n    }\n\n    ret = ss_malloc(n + 1);\n    strncpy(ret, s, n);\n    ret[n] = '\\0';\n    return ret;\n}\n\nvoid\nFATAL(const char *msg)\n{\n    LOGE(\"%s\", msg);\n    exit(-1);\n}\n\nvoid *\nss_malloc(size_t size)\n{\n    void *tmp = malloc(size);\n    if (tmp == NULL)\n        exit(EXIT_FAILURE);\n    return tmp;\n}\n\nvoid *\nss_aligned_malloc(size_t size)\n{\n    int err;\n    void *tmp = NULL;\n#ifdef HAVE_POSIX_MEMALIGN\n    /* ensure 16 byte alignment */\n    err = posix_memalign(&tmp, 16, size);\n#elif __MINGW32__\n    tmp = _aligned_malloc(size, 16);\n    err = tmp == NULL;\n#else\n    err = -1;\n#endif\n    if (err) {\n        return ss_malloc(size);\n    } else {\n        return tmp;\n    }\n}\n\nvoid *\nss_realloc(void *ptr, size_t new_size)\n{\n    void *new = realloc(ptr, new_size);\n    if (new == NULL) {\n        free(ptr);\n        ptr = NULL;\n        exit(EXIT_FAILURE);\n    }\n    return new;\n}\n\nint\nss_is_ipv6addr(const char *addr)\n{\n    return strcmp(addr, \":\") > 0;\n}\n\nvoid\nusage()\n{\n    printf(\"\\n\");\n    printf(\"shadowsocks-libev %s\\n\\n\", VERSION);\n    printf(\n        \"  maintained by Max Lv <max.c.lv@gmail.com> and Linus Yang <laokongzi@gmail.com>\\n\\n\");\n    printf(\"  usage:\\n\\n\");\n#ifdef MODULE_LOCAL\n    printf(\"    ss-local\\n\");\n#elif MODULE_REMOTE\n    printf(\"    ss-server\\n\");\n#elif MODULE_TUNNEL\n    printf(\"    ss-tunnel\\n\");\n#elif MODULE_REDIR\n    printf(\"    ss-redir\\n\");\n#elif MODULE_MANAGER\n    printf(\"    ss-manager\\n\");\n#endif\n    printf(\"\\n\");\n    printf(\n        \"       -s <server_host>           Host name or IP address of your remote server.\\n\");\n    printf(\n        \"       -p <server_port>           Port number of your remote server.\\n\");\n    printf(\n        \"       -l <local_port>            Port number of your local server.\\n\");\n    printf(\n        \"       -k <password>              Password of your remote server.\\n\");\n    printf(\n        \"       -m <encrypt_method>        Encrypt method: rc4-md5, \\n\");\n    printf(\n        \"                                  aes-128-gcm, aes-192-gcm, aes-256-gcm,\\n\");\n    printf(\n        \"                                  aes-128-cfb, aes-192-cfb, aes-256-cfb,\\n\");\n    printf(\n        \"                                  aes-128-ctr, aes-192-ctr, aes-256-ctr,\\n\");\n    printf(\n        \"                                  camellia-128-cfb, camellia-192-cfb,\\n\");\n    printf(\n        \"                                  camellia-256-cfb, bf-cfb,\\n\");\n    printf(\n        \"                                  chacha20-ietf-poly1305,\\n\");\n#ifdef FS_HAVE_XCHACHA20IETF\n    printf(\n        \"                                  xchacha20-ietf-poly1305,\\n\");\n#endif\n    printf(\n        \"                                  salsa20, chacha20 and chacha20-ietf.\\n\");\n    printf(\n        \"                                  The default cipher is chacha20-ietf-poly1305.\\n\");\n    printf(\"\\n\");\n    printf(\n        \"       [-a <user>]                Run as another user.\\n\");\n    printf(\n        \"       [-f <pid_file>]            The file path to store pid.\\n\");\n    printf(\n        \"       [-t <timeout>]             Socket timeout in seconds.\\n\");\n    printf(\n        \"       [-c <config_file>]         The path to config file.\\n\");\n#ifdef HAVE_SETRLIMIT\n    printf(\n        \"       [-n <number>]              Max number of open files.\\n\");\n#endif\n#ifndef MODULE_REDIR\n    printf(\n        \"       [-i <interface>]           Network interface to bind.\\n\");\n#endif\n    printf(\n        \"       [-b <local_address>]       Local address to bind.\\n\");\n    printf(\"\\n\");\n    printf(\n        \"       [-u]                       Enable UDP relay.\\n\");\n#ifdef MODULE_REDIR\n    printf(\n        \"                                  TPROXY is required in redir mode.\\n\");\n#endif\n    printf(\n        \"       [-U]                       Enable UDP relay and disable TCP relay.\\n\");\n#ifdef MODULE_REDIR\n    printf(\n        \"       [-T]                       Use tproxy instead of redirect (for tcp).\\n\");\n#endif\n#ifdef MODULE_REMOTE\n    printf(\n        \"       [-6]                       Resovle hostname to IPv6 address first.\\n\");\n#endif\n    printf(\"\\n\");\n#ifdef MODULE_TUNNEL\n    printf(\n        \"       [-L <addr>:<port>]         Destination server address and port\\n\");\n    printf(\n        \"                                  for local port forwarding.\\n\");\n#endif\n#ifdef MODULE_REMOTE\n    printf(\n        \"       [-d <addr>]                Name servers for internal DNS resolver.\\n\");\n#endif\n    printf(\n        \"       [--reuse-port]             Enable port reuse.\\n\");\n#if defined(MODULE_REMOTE) || defined(MODULE_LOCAL) || defined(MODULE_REDIR)\n    printf(\n        \"       [--fast-open]              Enable TCP fast open.\\n\");\n    printf(\n        \"                                  with Linux kernel > 3.7.0.\\n\");\n#endif\n    printf(\n        \"       [--tcp-incoming-sndbuf]    Size of the incoming connection TCP send buffer.\\n\");\n    printf(\n        \"       [--tcp-incoming-rcvbuf]    Size of the incoming connection TCP receive buffer.\\n\");\n    printf(\n        \"       [--tcp-outgoing-sndbuf]    Size of the outgoing connection TCP send buffer.\\n\");\n    printf(\n        \"       [--tcp-outgoing-rcvbuf]    Size of the outgoing connection TCP receive buffer.\\n\");\n#if defined(MODULE_REMOTE) || defined(MODULE_LOCAL)\n    printf(\n        \"       [--acl <acl_file>]         Path to ACL (Access Control List).\\n\");\n#endif\n#if defined(MODULE_REMOTE) || defined(MODULE_MANAGER)\n    printf(\n        \"       [--manager-address <addr>] UNIX domain socket address.\\n\");\n#endif\n#ifdef MODULE_MANAGER\n    printf(\n        \"       [--executable <path>]      Path to the executable of ss-server.\\n\");\n    printf(\n        \"       [-D <path>]                Path to the working directory of ss-manager.\\n\");\n#endif\n    printf(\n        \"       [--mtu <MTU>]              MTU of your network interface.\\n\");\n#ifdef __linux__\n    printf(\n        \"       [--mptcp]                  Enable Multipath TCP on MPTCP Kernel.\\n\");\n#ifdef USE_NFTABLES\n    printf(\n        \"       [--nftables-sets <sets>]   Add malicious IP into nftables sets.\\n\");\n    printf(\n        \"                                  sets spec: [<table1>:]<set1>[,[<table2>:]<set2>...]\\n\");\n#endif\n#endif\n#ifndef MODULE_MANAGER\n    printf(\n        \"       [--no-delay]               Enable TCP_NODELAY.\\n\");\n    printf(\n        \"       [--key <key_in_base64>]    Key of your remote server.\\n\");\n#endif\n    printf(\n        \"       [--plugin <name>]          Enable SIP003 plugin. (Experimental)\\n\");\n    printf(\n        \"       [--plugin-opts <options>]  Set SIP003 plugin options. (Experimental)\\n\");\n    printf(\"\\n\");\n    printf(\n        \"       [-v]                       Verbose mode.\\n\");\n    printf(\n        \"       [-h, --help]               Print this message.\\n\");\n    printf(\"\\n\");\n}\n\nvoid\ndaemonize(const char *path)\n{\n#ifndef __MINGW32__\n    /* Our process ID and Session ID */\n    pid_t pid, sid;\n\n    /* Fork off the parent process */\n    pid = fork();\n    if (pid < 0) {\n        exit(EXIT_FAILURE);\n    }\n\n    /* If we got a good PID, then\n     * we can exit the parent process. */\n    if (pid > 0) {\n        FILE *file = fopen(path, \"w\");\n        if (file == NULL) {\n            FATAL(\"Invalid pid file\\n\");\n        }\n\n        fprintf(file, \"%d\", (int)pid);\n        fclose(file);\n        exit(EXIT_SUCCESS);\n    }\n\n    /* Change the file mode mask */\n    umask(0);\n\n    /* Open any logs here */\n\n    /* Create a new SID for the child process */\n    sid = setsid();\n    if (sid < 0) {\n        /* Log the failure */\n        exit(EXIT_FAILURE);\n    }\n\n    /* Change the current working directory */\n    if ((chdir(\"/\")) < 0) {\n        /* Log the failure */\n        exit(EXIT_FAILURE);\n    }\n\n    int dev_null = open(\"/dev/null\", O_WRONLY);\n    if (dev_null > 0) {\n        /* Redirect to null device  */\n        dup2(dev_null, STDOUT_FILENO);\n        dup2(dev_null, STDERR_FILENO);\n    } else {\n        /* Close the standard file descriptors */\n        close(STDOUT_FILENO);\n        close(STDERR_FILENO);\n    }\n\n    /* Close the standard file descriptors */\n    close(STDIN_FILENO);\n#else\n    LOGE(\"daemonize(): not implemented in MinGW port\");\n#endif\n}\n\n#ifdef HAVE_SETRLIMIT\nint\nset_nofile(int nofile)\n{\n    struct rlimit limit = { nofile, nofile }; /* set both soft and hard limit */\n\n    if (nofile <= 0) {\n        FATAL(\"nofile must be greater than 0\\n\");\n    }\n\n    if (setrlimit(RLIMIT_NOFILE, &limit) < 0) {\n        if (errno == EPERM) {\n            LOGE(\n                \"insufficient permission to change NOFILE, not starting as root?\");\n            return -1;\n        } else if (errno == EINVAL) {\n            LOGE(\"invalid nofile, decrease nofile and try again\");\n            return -1;\n        } else {\n            LOGE(\"setrlimit failed: %s\", strerror(errno));\n            return -1;\n        }\n    }\n\n    return 0;\n}\n\n#endif\n\nchar *\nget_default_conf(void)\n{\n#ifndef __MINGW32__\n    static char sysconf[] = \"/etc/shadowsocks-libev/config.json\";\n    static char *userconf = NULL;\n    static int buf_size   = 0;\n    char *conf_home;\n\n    conf_home = getenv(\"XDG_CONFIG_HOME\");\n\n    // Memory of userconf only gets allocated once, and will not be\n    // freed. It is used as static buffer.\n    if (!conf_home) {\n        if (buf_size == 0) {\n            buf_size = 50 + strlen(getenv(\"HOME\"));\n            userconf = malloc(buf_size);\n        }\n        snprintf(userconf, buf_size, \"%s%s\", getenv(\"HOME\"),\n                 \"/.config/shadowsocks-libev/config.json\");\n    } else {\n        if (buf_size == 0) {\n            buf_size = 50 + strlen(conf_home);\n            userconf = malloc(buf_size);\n        }\n        snprintf(userconf, buf_size, \"%s%s\", conf_home,\n                 \"/shadowsocks-libev/config.json\");\n    }\n\n    // Check if the user-specific config exists.\n    if (access(userconf, F_OK) != -1)\n        return userconf;\n\n    // If not, fall back to the system-wide config.\n    free(userconf);\n    return sysconf;\n#else\n    return \"config.json\";\n#endif\n}\n\nuint16_t\nload16_be(const void *s)\n{\n    const uint8_t *in = (const uint8_t *)s;\n    return ((uint16_t)in[0] << 8)\n           | ((uint16_t)in[1]);\n}\n\nint\nget_mptcp(int enable)\n{\n    const char oldpath[] = \"/proc/sys/net/mptcp/mptcp_enabled\";\n\n    if (enable) {\n        // Check if kernel has out-of-tree MPTCP support.\n        if (access(oldpath, F_OK) != -1)\n            return 1;\n\n        // Otherwise, just use IPPROTO_MPTCP.\n        return -1;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "src/utils.h",
    "content": "/*\n * utils.h - Misc utilities\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _UTILS_H\n#define _UTILS_H\n\n#include <stddef.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <time.h>\n\n#define PORTSTRLEN 16\n#define SS_ADDRSTRLEN (INET6_ADDRSTRLEN + PORTSTRLEN + 1)\n\n#ifdef __ANDROID__\n\n#include <android/log.h>\n#define USE_TTY()\n#define USE_SYSLOG(ident, _cond)\n#define LOGI(...)                                                \\\n    ((void)__android_log_print(ANDROID_LOG_DEBUG, \"shadowsocks\", \\\n                               __VA_ARGS__))\n#define LOGE(...)                                                \\\n    ((void)__android_log_print(ANDROID_LOG_ERROR, \"shadowsocks\", \\\n                               __VA_ARGS__))\n\n#else // not __ANDROID__\n\n#define STR(x) # x\n#define TOSTR(x) STR(x)\n\n#ifdef LIB_ONLY\n\nextern FILE *logfile;\n#define TIME_FORMAT \"%Y-%m-%d %H:%M:%S\"\n#define USE_TTY()\n#define USE_SYSLOG(ident, _cond)\n#define USE_LOGFILE(ident)                                     \\\n    do {                                                       \\\n        if (ident != NULL) { logfile = fopen(ident, \"w+\"); } } \\\n    while (0)\n\n#define CLOSE_LOGFILE                               \\\n    do {                                            \\\n        if (logfile != NULL) { fclose(logfile); } } \\\n    while (0)\n#define LOGI(format, ...)                                                        \\\n    do {                                                                         \\\n        if (logfile != NULL) {                                                   \\\n            time_t now = time(NULL);                                             \\\n            char timestr[20];                                                    \\\n            strftime(timestr, 20, TIME_FORMAT, localtime(&now));                 \\\n            fprintf(logfile, \" %s INFO: \" format \"\\n\", timestr, ## __VA_ARGS__); \\\n            fflush(logfile); }                                                   \\\n    }                                                                            \\\n    while (0)\n#define LOGE(format, ...)                                        \\\n    do {                                                         \\\n        if (logfile != NULL) {                                   \\\n            time_t now = time(NULL);                             \\\n            char timestr[20];                                    \\\n            strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \\\n            fprintf(logfile, \" %s ERROR: \" format \"\\n\", timestr, \\\n                    ## __VA_ARGS__);                             \\\n            fflush(logfile); }                                   \\\n    }                                                            \\\n    while (0)\n\n#else // not LIB_ONLY\n\n#ifdef __MINGW32__\n\n#define USE_TTY()\n#define USE_SYSLOG(ident, _cond)\n#define USE_LOGFILE(ident)\n#define TIME_FORMAT \"%Y-%m-%d %H:%M:%S\"\n#define LOGI(format, ...)                                    \\\n    do {                                                     \\\n        time_t now = time(NULL);                             \\\n        char timestr[20];                                    \\\n        strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \\\n        ss_color_info();                                     \\\n        fprintf(stdout, \" %s INFO: \", timestr);              \\\n        ss_color_reset();                                    \\\n        fprintf(stdout, format \"\\n\", ## __VA_ARGS__);        \\\n        fflush(stdout);                                      \\\n    }                                                        \\\n    while (0)\n\n#define LOGE(format, ...)                                     \\\n    do {                                                      \\\n        time_t now = time(NULL);                              \\\n        char timestr[20];                                     \\\n        strftime(timestr, 20, TIME_FORMAT, localtime(&now));  \\\n        ss_color_error();                                     \\\n        fprintf(stderr, \" %s ERROR: \", timestr);              \\\n        ss_color_reset();                                     \\\n        fprintf(stderr, format \"\\n\", ## __VA_ARGS__);         \\\n        fflush(stderr);                                       \\\n    }                                                         \\\n    while (0)\n\n#else // not __MINGW32__\n\n#include <syslog.h>\nextern int use_tty;\nextern int use_syslog;\n\n#define HAS_SYSLOG\n#define TIME_FORMAT \"%F %T\"\n\n#define USE_TTY()                        \\\n    do {                                 \\\n        use_tty = isatty(STDERR_FILENO); \\\n    } while (0)\n\n#define USE_SYSLOG(_ident, _cond)                               \\\n    do {                                                        \\\n        if (!use_syslog && (_cond)) {                           \\\n            use_syslog = 1;                                     \\\n        }                                                       \\\n        if (use_syslog) {                                       \\\n            openlog((_ident), LOG_CONS | LOG_PID, LOG_DAEMON);  \\\n        }                                                       \\\n    } while (0)\n\n#define LOGI(format, ...)                                                        \\\n    do {                                                                         \\\n        if (use_syslog) {                                                        \\\n            syslog(LOG_INFO, format, ## __VA_ARGS__);                            \\\n        } else {                                                                 \\\n            time_t now = time(NULL);                                             \\\n            char timestr[20];                                                    \\\n            strftime(timestr, 20, TIME_FORMAT, localtime(&now));                 \\\n            if (use_tty) {                                                       \\\n                fprintf(stdout, \"\\e[01;32m %s INFO: \\e[0m\" format \"\\n\", timestr, \\\n                        ## __VA_ARGS__);                                         \\\n                fflush(stdout);                                                  \\\n            } else {                                                             \\\n                fprintf(stdout, \" %s INFO: \" format \"\\n\", timestr,               \\\n                        ## __VA_ARGS__);                                         \\\n                fflush(stdout);                                                  \\\n            }                                                                    \\\n        }                                                                        \\\n    }                                                                            \\\n    while (0)\n\n#define LOGE(format, ...)                                                         \\\n    do {                                                                          \\\n        if (use_syslog) {                                                         \\\n            syslog(LOG_ERR, format, ## __VA_ARGS__);                              \\\n        } else {                                                                  \\\n            time_t now = time(NULL);                                              \\\n            char timestr[20];                                                     \\\n            strftime(timestr, 20, TIME_FORMAT, localtime(&now));                  \\\n            if (use_tty) {                                                        \\\n                fprintf(stderr, \"\\e[01;35m %s ERROR: \\e[0m\" format \"\\n\", timestr, \\\n                        ## __VA_ARGS__);                                          \\\n                fflush(stderr);                                                   \\\n            } else {                                                              \\\n                fprintf(stderr, \" %s ERROR: \" format \"\\n\", timestr,               \\\n                        ## __VA_ARGS__);                                          \\\n                fflush(stderr);                                                   \\\n            }                                                                     \\\n        } }                                                                       \\\n    while (0)\n\n#endif // if __MINGW32__\n\n#endif // if LIB_ONLY\n\n#endif // if __ANDROID__\n\n// Workaround for \"%z\" in Windows printf\n#ifdef __MINGW32__\n#define SSIZE_FMT \"%Id\"\n#define SIZE_FMT \"%Iu\"\n#else\n#define SSIZE_FMT \"%zd\"\n#define SIZE_FMT \"%zu\"\n#endif\n\n#ifdef __MINGW32__\n// Override Windows built-in functions\n#ifdef ERROR\n#undef ERROR\n#endif\n#define ERROR(s) ss_error(s)\n\n// Implemented in winsock.c\nvoid ss_error(const char *s);\nvoid ss_color_info(void);\nvoid ss_color_error(void);\nvoid ss_color_reset(void);\n#else\nvoid ERROR(const char *s);\n#endif\n\nchar *ss_itoa(int i);\nint ss_isnumeric(const char *s);\nint run_as(const char *user);\nvoid FATAL(const char *msg);\nvoid usage(void);\nvoid daemonize(const char *path);\nchar *ss_strndup(const char *s, size_t n);\n#ifdef HAVE_SETRLIMIT\nint set_nofile(int nofile);\n#endif\n\nvoid *ss_malloc(size_t size);\nvoid *ss_aligned_malloc(size_t size);\nvoid *ss_realloc(void *ptr, size_t new_size);\n\n#define ss_free(ptr) \\\n    { \\\n        free(ptr); \\\n        ptr = NULL; \\\n    }\n\n#ifdef __MINGW32__\n#define ss_aligned_free(ptr) \\\n    { \\\n        _aligned_free(ptr); \\\n        ptr = NULL; \\\n    }\n#else\n#define ss_aligned_free(ptr) ss_free(ptr)\n#endif\n\nint ss_is_ipv6addr(const char *addr);\nchar *get_default_conf(void);\nuint16_t load16_be(const void *s);\nint get_mptcp(int enable);\n\n#endif // _UTILS_H\n"
  },
  {
    "path": "src/winsock.c",
    "content": "/*\n * winsock.c - Windows socket compatibility layer\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifdef __MINGW32__\n\n#include \"winsock.h\"\n#include \"utils.h\"\n\n#ifndef ENABLE_QUICK_EDIT\n#define ENABLE_QUICK_EDIT 0x0040\n#endif\n\n#ifndef STD_INPUT_HANDLE\n#define STD_INPUT_HANDLE ((DWORD)-10)\n#endif\n\n#ifndef ENABLE_EXTENDED_FLAGS\n#define ENABLE_EXTENDED_FLAGS 0x0080\n#endif\n\n#ifndef STD_OUTPUT_HANDLE\n#define STD_OUTPUT_HANDLE ((DWORD)-11)\n#endif\n\nstatic void\ndisable_quick_edit(void)\n{\n    DWORD mode     = 0;\n    HANDLE console = GetStdHandle(STD_INPUT_HANDLE);\n\n    // Get current console mode\n    if (console == NULL ||\n        console == INVALID_HANDLE_VALUE ||\n        !GetConsoleMode(console, &mode)) {\n        return;\n    }\n\n    // Clear the quick edit bit in the mode flags\n    mode &= ~ENABLE_QUICK_EDIT;\n    mode |= ENABLE_EXTENDED_FLAGS;\n    SetConsoleMode(console, mode);\n}\n\nvoid\nwinsock_init(void)\n{\n    int ret;\n    WSADATA wsa_data;\n    ret = WSAStartup(MAKEWORD(2, 2), &wsa_data);\n    if (ret != 0) {\n        FATAL(\"Failed to initialize winsock\");\n    }\n    // Disable quick edit mode to prevent stuck\n    disable_quick_edit();\n}\n\nvoid\nwinsock_cleanup(void)\n{\n    WSACleanup();\n}\n\nint\nsetnonblocking(SOCKET socket)\n{\n    u_long arg = 1;\n    return ioctlsocket(socket, FIONBIO, &arg);\n}\n\nvoid\nss_error(const char *s)\n{\n    char *msg = NULL;\n    DWORD err = WSAGetLastError();\n    FormatMessage(\n        FORMAT_MESSAGE_ALLOCATE_BUFFER |\n        FORMAT_MESSAGE_FROM_SYSTEM |\n        FORMAT_MESSAGE_IGNORE_INSERTS,\n        NULL, err,\n        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\n        (LPTSTR)&msg, 0, NULL);\n    if (msg != NULL) {\n        // Remove trailing newline character\n        ssize_t len = strlen(msg) - 1;\n        if (len >= 0 && msg[len] == '\\n') {\n            msg[len] = '\\0';\n        }\n        LOGE(\"%s: [%ld] %s\", s, err, msg);\n        LocalFree(msg);\n    }\n}\n\nchar *\nss_gai_strerror(int ecode)\n{\n    static TCHAR buff[GAI_STRERROR_BUFFER_SIZE + 1];\n    FormatMessage(\n        FORMAT_MESSAGE_FROM_SYSTEM |\n        FORMAT_MESSAGE_IGNORE_INSERTS |\n        FORMAT_MESSAGE_MAX_WIDTH_MASK,\n        NULL, ecode,\n        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\n        (LPTSTR)buff, GAI_STRERROR_BUFFER_SIZE, NULL);\n    return (char *)buff;\n}\n\nstatic BOOL\nget_conattr(HANDLE console, WORD *out_attr)\n{\n    static BOOL done       = FALSE;\n    static WORD saved_attr = 0;\n    if (!done) {\n        CONSOLE_SCREEN_BUFFER_INFO info;\n        if (GetConsoleScreenBufferInfo(console, &info)) {\n            saved_attr = info.wAttributes;\n            done       = TRUE;\n        }\n    }\n    if (out_attr != NULL) {\n        *out_attr = saved_attr;\n    }\n    return done;\n}\n\nstatic BOOL\nset_concolor(WORD color, BOOL reset)\n{\n    static HANDLE console = NULL;\n    if (console == NULL) {\n        console = GetStdHandle(STD_OUTPUT_HANDLE);\n    }\n    if (console == NULL ||\n        console == INVALID_HANDLE_VALUE) {\n        // If no console is available, we will not try again\n        console = INVALID_HANDLE_VALUE;\n        return FALSE;\n    }\n    WORD attr;\n    if (!get_conattr(console, &attr)) {\n        return FALSE;\n    }\n    if (!reset) {\n        // Only override foreground color without changing background\n        attr &= ~(FOREGROUND_RED | FOREGROUND_GREEN |\n                  FOREGROUND_BLUE | FOREGROUND_INTENSITY);\n        attr |= (color | FOREGROUND_INTENSITY);\n    }\n    return SetConsoleTextAttribute(console, attr);\n}\n\nvoid\nss_color_info(void)\n{\n    set_concolor(FOREGROUND_GREEN, FALSE);\n}\n\nvoid\nss_color_error(void)\n{\n    set_concolor(FOREGROUND_RED | FOREGROUND_BLUE, FALSE);\n}\n\nvoid\nss_color_reset(void)\n{\n    set_concolor(0, TRUE);\n}\n\n#ifdef TCP_FASTOPEN_WINSOCK\nLPFN_CONNECTEX\nwinsock_getconnectex(void)\n{\n    static LPFN_CONNECTEX pConnectEx = NULL;\n    if (pConnectEx != NULL) {\n        return pConnectEx;\n    }\n\n    // Dummy socket for WSAIoctl\n    SOCKET s = socket(AF_INET, SOCK_STREAM, 0);\n    if (s == INVALID_SOCKET) {\n        ERROR(\"socket\");\n        return NULL;\n    }\n\n    // Load ConnectEx function\n    GUID guid = WSAID_CONNECTEX;\n    DWORD numBytes;\n    int ret = -1;\n    ret = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,\n                   (void *)&guid, sizeof(guid),\n                   (void *)&pConnectEx, sizeof(pConnectEx),\n                   &numBytes, NULL, NULL);\n    if (ret != 0) {\n        ERROR(\"WSAIoctl\");\n        closesocket(s);\n        return NULL;\n    }\n    closesocket(s);\n    return pConnectEx;\n}\n\nint\nwinsock_dummybind(SOCKET fd, struct sockaddr *sa)\n{\n    struct sockaddr_storage ss;\n    memset(&ss, 0, sizeof(ss));\n    if (sa->sa_family == AF_INET) {\n        struct sockaddr_in *sin = (struct sockaddr_in *)&ss;\n        sin->sin_family      = AF_INET;\n        sin->sin_addr.s_addr = INADDR_ANY;\n    } else if (sa->sa_family == AF_INET6) {\n        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;\n        sin6->sin6_family = AF_INET6;\n        sin6->sin6_addr   = in6addr_any;\n    } else {\n        return -1;\n    }\n    if (bind(fd, (struct sockaddr *)&ss, sizeof(ss)) < 0 &&\n        WSAGetLastError() != WSAEINVAL) {\n        return -1;\n    }\n    return 0;\n}\n\n#endif\n\n#endif // __MINGW32__\n"
  },
  {
    "path": "src/winsock.h",
    "content": "/*\n * winsock.h - Windows socket compatibility layer\n *\n * Copyright (C) 2013 - 2019, Max Lv <max.c.lv@gmail.com>\n *\n * This file is part of the shadowsocks-libev.\n *\n * shadowsocks-libev is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3 of the License, or\n * (at your option) any later version.\n *\n * shadowsocks-libev is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with shadowsocks-libev; see the file COPYING. If not, see\n * <http://www.gnu.org/licenses/>.\n */\n\n#ifndef _WINSOCK_H\n#define _WINSOCK_H\n\n#ifdef __MINGW32__\n\n// Target NT6\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n\n#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600\n#undef _WIN32_WINNT\n#endif\n\n#ifndef _WIN32_WINNT\n#define _WIN32_WINNT 0x0600\n#endif\n\n// Winsock headers\n#include <windows.h>\n#include <winsock2.h>\n#include <ws2tcpip.h>\n#include <mswsock.h>\n\n// Override POSIX error number\n#ifdef errno\n#undef errno\n#endif\n#define errno WSAGetLastError()\n\n#ifdef EWOULDBLOCK\n#undef EWOULDBLOCK\n#endif\n#define EWOULDBLOCK WSAEWOULDBLOCK\n\n#ifdef CONNECT_IN_PROGRESS\n#undef CONNECT_IN_PROGRESS\n#endif\n#define CONNECT_IN_PROGRESS WSAEWOULDBLOCK\n\n#ifdef EOPNOTSUPP\n#undef EOPNOTSUPP\n#endif\n#define EOPNOTSUPP WSAEOPNOTSUPP\n\n#ifdef EPROTONOSUPPORT\n#undef EPROTONOSUPPORT\n#endif\n#define EPROTONOSUPPORT WSAEPROTONOSUPPORT\n\n#ifdef ENOPROTOOPT\n#undef ENOPROTOOPT\n#endif\n#define ENOPROTOOPT WSAENOPROTOOPT\n\n// Check if ConnectEx supported in header\n#ifdef WSAID_CONNECTEX\n// Hardcode TCP fast open option\n#ifndef TCP_FASTOPEN\n#define TCP_FASTOPEN 15\n#endif\n// Enable TFO support\n#define TCP_FASTOPEN_WINSOCK 1\n#endif\n\n// Override close function\n#define close(fd) closesocket(fd)\n\n// Override MinGW functions\n#define setsockopt(a, b, c, d, e) setsockopt(a, b, c, (const char *)(d), e)\n#define inet_ntop(a, b, c, d) inet_ntop(a, (void *)(b), c, d)\n\n// Override Windows built-in functions\n#ifdef ERROR\n#undef ERROR\n#endif\n#define ERROR(s) ss_error(s)\n\n#ifdef gai_strerror\n#undef gai_strerror\n#endif\n#define gai_strerror(e) ss_gai_strerror(e)\nchar *ss_gai_strerror(int ecode);\n\n// Missing Unix functions\n#define sleep(x) Sleep((x) * 1000)\n#define bzero(s, n) memset(s, 0, n)\n#define strndup(s, n) ss_strndup(s, n)\n\n// Winsock compatibility functions\nint setnonblocking(SOCKET socket);\nvoid winsock_init(void);\nvoid winsock_cleanup(void);\n#ifdef TCP_FASTOPEN_WINSOCK\nLPFN_CONNECTEX winsock_getconnectex(void);\nint winsock_dummybind(SOCKET fd, struct sockaddr *sa);\n#endif\n\n#endif // __MINGW32__\n\n#endif // _WINSOCK_H\n"
  },
  {
    "path": "tests/CMakeLists.txt",
    "content": "# Unit tests using CTest\ninclude_directories(BEFORE ${MBEDTLS_INCLUDE_DIRS})\ninclude_directories(${PROJECT_SOURCE_DIR}/src)\ninclude_directories(${PROJECT_BINARY_DIR}/src)\ninclude_directories(${SODIUM_INCLUDE_DIRS})\ninclude_directories(${PCRE2_INCLUDE_DIRS})\ninclude_directories(${CARES_INCLUDE_DIRS})\n\nif(WITH_EMBEDDED_SRC)\n    include_directories(${PROJECT_SOURCE_DIR}/libcork/include)\n    include_directories(${PROJECT_SOURCE_DIR}/libipset/include)\n    include_directories(${PROJECT_SOURCE_DIR}/libbloom/murmur2)\n    include_directories(${PROJECT_SOURCE_DIR}/libbloom)\nendif()\n\n# Helper function to add a unit test\nfunction(ss_add_test name sources libs)\n    add_executable(${name} ${sources})\n    target_compile_definitions(${name} PRIVATE -DHAVE_CONFIG_H)\n    target_link_libraries(${name} ${libs})\n    add_test(NAME ${name} COMMAND ${name})\nendfunction()\n\n# test_base64 - no external deps\nss_add_test(test_base64\n    \"test_base64.c;${PROJECT_SOURCE_DIR}/src/base64.c\"\n    \"\")\n\n# test_utils - needs sodium (for ss_malloc -> uses sodium in utils.c)\nss_add_test(test_utils\n    \"test_utils.c;${PROJECT_SOURCE_DIR}/src/utils.c\"\n    \"${LIBSODIUM_SHARED}\")\n\n# test_json - standalone json parser\nss_add_test(test_json\n    \"test_json.c;${PROJECT_SOURCE_DIR}/src/json.c\"\n    \"m\")\n\n# test_netutils - needs cork for ip address parsing\nset(TEST_NETUTILS_LIBS\n    ${LIBSODIUM_SHARED}\n    ${LIBEV_SHARED}\n    ${LIBUDNS_SHARED}\n)\nif(WITH_EMBEDDED_SRC)\n    list(APPEND TEST_NETUTILS_LIBS cork)\nelse()\n    list(APPEND TEST_NETUTILS_LIBS ${LIBCORK_SHARED})\nendif()\nss_add_test(test_netutils\n    \"test_netutils.c;${PROJECT_SOURCE_DIR}/src/netutils.c;${PROJECT_SOURCE_DIR}/src/utils.c\"\n    \"${TEST_NETUTILS_LIBS}\")\n\n# test_cache - needs libev for ev_time()\nss_add_test(test_cache\n    \"test_cache.c;${PROJECT_SOURCE_DIR}/src/cache.c;${PROJECT_SOURCE_DIR}/src/utils.c\"\n    \"${LIBEV_SHARED};${LIBSODIUM_SHARED}\")\n\n# test_ppbloom - needs bloom\nset(TEST_PPBLOOM_LIBS \"\")\nif(WITH_EMBEDDED_SRC)\n    list(APPEND TEST_PPBLOOM_LIBS bloom)\nelse()\n    list(APPEND TEST_PPBLOOM_LIBS ${LIBBLOOM_SHARED})\nendif()\nss_add_test(test_ppbloom\n    \"test_ppbloom.c;${PROJECT_SOURCE_DIR}/src/ppbloom.c;${PROJECT_SOURCE_DIR}/src/utils.c\"\n    \"${TEST_PPBLOOM_LIBS};${LIBSODIUM_SHARED};m\")\n\n# test_rule - needs pcre and cork\nset(TEST_RULE_LIBS\n    ${LIBPCRE2_SHARED}\n    ${LIBSODIUM_SHARED}\n)\nif(WITH_EMBEDDED_SRC)\n    list(APPEND TEST_RULE_LIBS cork)\nelse()\n    list(APPEND TEST_RULE_LIBS ${LIBCORK_SHARED})\nendif()\nss_add_test(test_rule\n    \"test_rule.c;${PROJECT_SOURCE_DIR}/src/rule.c;${PROJECT_SOURCE_DIR}/src/utils.c\"\n    \"${TEST_RULE_LIBS}\")\n\n# test_jconf - needs cork and json\nset(TEST_JCONF_LIBS\n    ${LIBSODIUM_SHARED}\n    ${LIBEV_SHARED}\n    ${LIBUDNS_SHARED}\n)\nif(WITH_EMBEDDED_SRC)\n    list(APPEND TEST_JCONF_LIBS cork)\nelse()\n    list(APPEND TEST_JCONF_LIBS ${LIBCORK_SHARED})\nendif()\nss_add_test(test_jconf\n    \"test_jconf.c;${PROJECT_SOURCE_DIR}/src/jconf.c;${PROJECT_SOURCE_DIR}/src/json.c;${PROJECT_SOURCE_DIR}/src/utils.c;${PROJECT_SOURCE_DIR}/src/netutils.c\"\n    \"${TEST_JCONF_LIBS};m\")\n\n# test_buffer - needs sodium and mbedtls for crypto.c buffer functions\nss_add_test(test_buffer\n    \"test_buffer.c;${PROJECT_SOURCE_DIR}/src/crypto.c;${PROJECT_SOURCE_DIR}/src/utils.c;${PROJECT_SOURCE_DIR}/src/base64.c;${PROJECT_SOURCE_DIR}/src/aead.c;${PROJECT_SOURCE_DIR}/src/stream.c;${PROJECT_SOURCE_DIR}/src/ppbloom.c;${PROJECT_SOURCE_DIR}/src/cache.c\"\n    \"${LIBSODIUM_SHARED};${LIBMBEDTLS_SHARED};${LIBMBEDCRYPTO_SHARED};${LIBEV_SHARED};${TEST_PPBLOOM_LIBS};m\")\n\n# test_crypto - full crypto test\nset(TEST_CRYPTO_LIBS\n    ${LIBSODIUM_SHARED}\n    ${LIBMBEDTLS_SHARED}\n    ${LIBMBEDCRYPTO_SHARED}\n    ${LIBEV_SHARED}\n)\nif(WITH_EMBEDDED_SRC)\n    list(APPEND TEST_CRYPTO_LIBS bloom)\nelse()\n    list(APPEND TEST_CRYPTO_LIBS ${LIBBLOOM_SHARED})\nendif()\nss_add_test(test_crypto\n    \"test_crypto.c;${PROJECT_SOURCE_DIR}/src/crypto.c;${PROJECT_SOURCE_DIR}/src/aead.c;${PROJECT_SOURCE_DIR}/src/stream.c;${PROJECT_SOURCE_DIR}/src/ppbloom.c;${PROJECT_SOURCE_DIR}/src/cache.c;${PROJECT_SOURCE_DIR}/src/base64.c;${PROJECT_SOURCE_DIR}/src/utils.c\"\n    \"${TEST_CRYPTO_LIBS};m\")\n\n# test_ss_setup - bash unit tests for the ss-setup TUI tool\nadd_test(NAME test_ss_setup\n    COMMAND bash \"${PROJECT_SOURCE_DIR}/tests/test_ss_setup.sh\"\n    WORKING_DIRECTORY \"${PROJECT_SOURCE_DIR}\")\n"
  },
  {
    "path": "tests/aes-ctr.json",
    "content": "{\n    \"server\":\"127.0.0.1\",\n    \"server_port\":8389,\n    \"local_port\":1081,\n    \"password\":\"aes_password\",\n    \"timeout\":60,\n    \"method\":\"aes-256-ctr\",\n    \"local\":\"127.0.0.1\",\n    \"fast_open\":false\n}\n"
  },
  {
    "path": "tests/aes-gcm.json",
    "content": "{\n    \"server\":\"127.0.0.1\",\n    \"server_port\":8389,\n    \"local_port\":1081,\n    \"password\":\"aes_password\",\n    \"timeout\":60,\n    \"method\":\"aes-256-gcm\",\n    \"local\":\"127.0.0.1\",\n    \"fast_open\":false\n}\n"
  },
  {
    "path": "tests/aes.json",
    "content": "{\n    \"server\":\"127.0.0.1\",\n    \"server_port\":8389,\n    \"local_port\":1081,\n    \"password\":\"aes_password\",\n    \"timeout\":60,\n    \"method\":\"aes-256-cfb\",\n    \"local\":\"127.0.0.1\",\n    \"fast_open\":false\n}\n"
  },
  {
    "path": "tests/chacha20-ietf-poly1305.json",
    "content": "{\n    \"server\":\"127.0.0.1\",\n    \"server_port\":8389,\n    \"local_port\":1081,\n    \"password\":\"salsa20_password\",\n    \"timeout\":60,\n    \"method\":\"chacha20-ietf-poly1305\",\n    \"local\":\"127.0.0.1\",\n    \"fast_open\":false\n}\n"
  },
  {
    "path": "tests/chacha20-ietf.json",
    "content": "{\n    \"server\":\"127.0.0.1\",\n    \"server_port\":8389,\n    \"local_port\":1081,\n    \"password\":\"salsa20_password\",\n    \"timeout\":60,\n    \"method\":\"chacha20-ietf\",\n    \"local\":\"127.0.0.1\",\n    \"fast_open\":false\n}\n"
  },
  {
    "path": "tests/chacha20.json",
    "content": "{\n    \"server\":\"127.0.0.1\",\n    \"server_port\":8389,\n    \"local_port\":1081,\n    \"password\":\"chacha20_password\",\n    \"timeout\":60,\n    \"method\":\"chacha20\",\n    \"local\":\"127.0.0.1\",\n    \"fast_open\":false\n}\n"
  },
  {
    "path": "tests/qemu/guest-init.sh",
    "content": "#!/bin/bash\n#\n# Guest init script (PID 1) for ss-redir transparent proxy test.\n# Runs inside a QEMU Alpine Linux VM.\n#\n# Flow:\n#   1. Mount filesystems and load kernel modules\n#   2. Configure networking (QEMU user-mode: guest 10.0.2.15, host 10.0.2.2)\n#   3. Start ss-redir pointing at ss-server on the host\n#   4. Run ss-nat to set up iptables REDIRECT rules\n#   5. Test with curl through the transparent proxy\n#   6. Print REDIR_TEST_PASS or REDIR_TEST_FAIL to serial console\n#\n\nset -e\n\n# --- helpers ----------------------------------------------------------------\n\npass() {\n    echo \"\"\n    echo \"=========================================\"\n    echo \"REDIR_TEST_PASS\"\n    echo \"=========================================\"\n    sync\n    echo o > /proc/sysrq-trigger\n    sleep 10\n}\n\nfail() {\n    local msg=\"${1:-unknown error}\"\n    echo \"\"\n    echo \"=========================================\"\n    echo \"REDIR_TEST_FAIL: $msg\"\n    echo \"=========================================\"\n    sync\n    echo o > /proc/sysrq-trigger\n    sleep 10\n}\n\n# --- mount filesystems ------------------------------------------------------\n\nmount -t proc     proc     /proc\nmount -t sysfs    sysfs    /sys\nmount -t devtmpfs devtmpfs /dev\nmkdir -p /dev/pts /tmp /run\nmount -t devpts   devpts   /dev/pts\nmount -t tmpfs    tmpfs    /tmp\nmount -t tmpfs    tmpfs    /run\n\n# Enable sysrq for clean poweroff\necho 1 > /proc/sys/kernel/sysrq\n\necho \"=== Guest init starting ===\"\n\n# --- load kernel modules ----------------------------------------------------\n\nfor mod in \\\n    virtio_net \\\n    ip_tables iptable_nat iptable_filter \\\n    nf_nat nf_conntrack \\\n    xt_REDIRECT xt_set xt_tcpudp \\\n    ip_set ip_set_hash_net; do\n    modprobe \"$mod\" 2>/dev/null || echo \"WARN: failed to load $mod (may be built-in)\"\ndone\n\necho \"=== Kernel modules loaded ===\"\n\n# --- configure network ------------------------------------------------------\n\n# Find the non-lo network interface\nIFACE=\"\"\nfor f in /sys/class/net/*/type; do\n    iface=$(basename \"$(dirname \"$f\")\")\n    if [ \"$iface\" != \"lo\" ]; then\n        IFACE=\"$iface\"\n        break\n    fi\ndone\n\nif [ -z \"$IFACE\" ]; then\n    fail \"no network interface found\"\nfi\n\necho \"=== Using network interface: $IFACE ===\"\n\nip link set lo up\nip link set \"$IFACE\" up\nip addr add 10.0.2.15/24 dev \"$IFACE\"\nip route add default via 10.0.2.2\n\n# DNS (QEMU user-mode DNS forwarder)\necho \"nameserver 10.0.2.3\" > /etc/resolv.conf\n\n# Wait for link to come up\nsleep 2\n\n# Connectivity check\necho \"=== Checking connectivity to host ===\"\nif ! ping -c 2 -W 5 10.0.2.2; then\n    fail \"cannot reach host at 10.0.2.2\"\nfi\n\necho \"=== Host reachable ===\"\n\n# --- start ss-redir ---------------------------------------------------------\n\necho \"=== Starting ss-redir ===\"\n/usr/bin/ss-redir -c /etc/ss-redir.json -v &\nSS_REDIR_PID=$!\nsleep 3\n\nif ! kill -0 \"$SS_REDIR_PID\" 2>/dev/null; then\n    fail \"ss-redir died immediately\"\nfi\n\necho \"=== ss-redir running (PID $SS_REDIR_PID) ===\"\n\n# --- run ss-nat (set up iptables REDIRECT) ----------------------------------\n\necho \"=== Running ss-nat ===\"\nif ! /usr/bin/ss-nat -s 10.0.2.2 -l 1080 -o; then\n    fail \"ss-nat failed\"\nfi\n\necho \"=== ss-nat rules applied ===\"\n\n# Show iptables state for debugging\necho \"=== iptables -t nat -L -n ===\"\niptables -t nat -L -n 2>&1 || true\necho \"=== ipset list ===\"\nipset list 2>&1 || true\n\n# --- test with curl ---------------------------------------------------------\n\necho \"=== Testing transparent proxy with curl ===\"\n\n# Try multiple URLs for reliability (captive portal detection endpoints\n# are lightweight and highly available)\n\n# Test 1: Mozilla captive portal\necho \"--- Test 1: detectportal.firefox.com ---\"\nBODY=$(curl -s --connect-timeout 15 -m 30 http://detectportal.firefox.com/success.txt 2>&1) || true\necho \"Response: $BODY\"\nif echo \"$BODY\" | grep -q \"success\"; then\n    echo \"Test 1 PASSED\"\n    pass\nfi\n\n# Test 2: Google (expect redirect or 200)\necho \"--- Test 2: www.google.com ---\"\nHTTP_CODE=$(curl -s -o /dev/null -w \"%{http_code}\" --connect-timeout 15 -m 30 http://www.google.com/ 2>&1) || true\necho \"HTTP code: $HTTP_CODE\"\nif [ \"$HTTP_CODE\" = \"200\" ] || [ \"$HTTP_CODE\" = \"301\" ] || [ \"$HTTP_CODE\" = \"302\" ]; then\n    echo \"Test 2 PASSED\"\n    pass\nfi\n\n# Test 3: Apple captive portal\necho \"--- Test 3: captive.apple.com ---\"\nBODY=$(curl -s --connect-timeout 15 -m 30 http://captive.apple.com/ 2>&1) || true\necho \"Response: $BODY\"\nif echo \"$BODY\" | grep -qi \"success\"; then\n    echo \"Test 3 PASSED\"\n    pass\nfi\n\n# If we get here, all tests failed\nfail \"all curl tests failed\"\n"
  },
  {
    "path": "tests/rc4-md5.json",
    "content": "{\n    \"server\":\"127.0.0.1\",\n    \"server_port\":8389,\n    \"local_port\":1081,\n    \"password\":\"aes_password\",\n    \"timeout\":60,\n    \"method\":\"rc4-md5\",\n    \"local\":\"127.0.0.1\",\n    \"fast_open\":false\n}\n"
  },
  {
    "path": "tests/redir.json",
    "content": "{\n    \"server\":\"10.0.2.2\",\n    \"server_port\":8389,\n    \"local_port\":1080,\n    \"password\":\"test_redir_password\",\n    \"timeout\":60,\n    \"method\":\"aes-256-gcm\"\n}\n"
  },
  {
    "path": "tests/salsa20.json",
    "content": "{\n    \"server\":\"127.0.0.1\",\n    \"server_port\":8389,\n    \"local_port\":1081,\n    \"password\":\"salsa20_password\",\n    \"timeout\":60,\n    \"method\":\"salsa20\",\n    \"local\":\"127.0.0.1\",\n    \"fast_open\":false\n}\n"
  },
  {
    "path": "tests/stress_test.py",
    "content": "#!/usr/bin/env python3\n\"\"\"\nStress test for shadowsocks-libev: measures bandwidth on loopback\nwith different ciphers using ss-server and ss-tunnel, and monitors\nfor memory leaks.\n\nUsage:\n    python3 tests/stress_test.py --bin build/bin/\n    python3 tests/stress_test.py --bin build/bin/ --size 50 --duration 10\n    python3 tests/stress_test.py --bin build/bin/ --cipher aes-256-gcm\n\"\"\"\n\nfrom __future__ import print_function\nimport argparse\nimport json\nimport os\nimport platform\nimport signal\nimport socket\nimport sys\nimport threading\nimport time\nfrom subprocess import Popen\n\n# Ciphers to test: AEAD (recommended) + common stream ciphers\nAEAD_CIPHERS = [\n    \"aes-128-gcm\",\n    \"aes-256-gcm\",\n    \"chacha20-ietf-poly1305\",\n]\n\nSTREAM_CIPHERS = [\n    \"aes-128-cfb\",\n    \"aes-256-cfb\",\n    \"aes-256-ctr\",\n    \"chacha20-ietf\",\n]\n\nALL_CIPHERS = AEAD_CIPHERS + STREAM_CIPHERS\n\n# Ports (picked high to avoid conflicts)\nSERVER_PORT = 18388\nTUNNEL_LOCAL_PORT = 18389\nSINK_PORT = 18390\n\n\ndef get_rss_kb(pid):\n    \"\"\"Get resident set size in KB for a process.\"\"\"\n    system = platform.system()\n    try:\n        if system == \"Linux\":\n            with open(\"/proc/%d/status\" % pid) as f:\n                for line in f:\n                    if line.startswith(\"VmRSS:\"):\n                        return int(line.split()[1])\n        elif system == \"Darwin\":\n            import subprocess\n            out = subprocess.check_output(\n                [\"ps\", \"-o\", \"rss=\", \"-p\", str(pid)],\n                stderr=subprocess.DEVNULL\n            ).decode().strip()\n            if out:\n                return int(out)\n    except (IOError, OSError, ValueError):\n        pass\n    return None\n\n\nclass SinkServer:\n    \"\"\"A simple TCP server that accepts connections and discards all data.\n    Sends back a small acknowledgement per chunk so the sender knows\n    data was received (for accurate bandwidth measurement).\"\"\"\n\n    def __init__(self, port):\n        self.port = port\n        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        self.sock.bind((\"127.0.0.1\", port))\n        self.sock.listen(5)\n        self.sock.settimeout(1.0)\n        self.running = True\n        self.bytes_received = 0\n        self.thread = threading.Thread(target=self._run, daemon=True)\n        self.thread.start()\n\n    def _run(self):\n        while self.running:\n            try:\n                conn, addr = self.sock.accept()\n                t = threading.Thread(\n                    target=self._handle, args=(conn,), daemon=True\n                )\n                t.start()\n            except socket.timeout:\n                continue\n            except OSError:\n                break\n\n    def _handle(self, conn):\n        conn.settimeout(5.0)\n        try:\n            while self.running:\n                data = conn.recv(65536)\n                if not data:\n                    break\n                self.bytes_received += len(data)\n        except (socket.timeout, OSError):\n            pass\n        finally:\n            conn.close()\n\n    def stop(self):\n        self.running = False\n        self.sock.close()\n        self.thread.join(timeout=3)\n\n\ndef server_args(ss_server, cipher, password, server_port):\n    \"\"\"Build command-line args for ss-server.\"\"\"\n    return [\n        ss_server,\n        \"-s\", \"127.0.0.1\",\n        \"-p\", str(server_port),\n        \"-k\", password,\n        \"-m\", cipher,\n    ]\n\n\ndef tunnel_args(ss_tunnel, cipher, password, server_port, local_port, fwd_host, fwd_port):\n    \"\"\"Build command-line args for ss-tunnel.\"\"\"\n    return [\n        ss_tunnel,\n        \"-s\", \"127.0.0.1\",\n        \"-p\", str(server_port),\n        \"-l\", str(local_port),\n        \"-k\", password,\n        \"-m\", cipher,\n        \"-L\", \"%s:%d\" % (fwd_host, fwd_port),\n    ]\n\n\ndef kill_proc(proc):\n    \"\"\"Kill a process gracefully.\"\"\"\n    if proc and proc.poll() is None:\n        try:\n            proc.send_signal(signal.SIGTERM)\n            proc.wait(timeout=5)\n        except Exception:\n            try:\n                proc.kill()\n                proc.wait(timeout=3)\n            except Exception:\n                pass\n\n\ndef run_bandwidth_test(bin_dir, cipher, data_size_mb, password=\"stress_test_pw\"):\n    \"\"\"Run a single bandwidth test with the given cipher.\n\n    Returns dict with: cipher, bandwidth_mbps, duration_sec,\n    server_rss_before_kb, server_rss_after_kb, tunnel_rss_before_kb,\n    tunnel_rss_after_kb, bytes_transferred, error\n    \"\"\"\n    result = {\n        \"cipher\": cipher,\n        \"bandwidth_mbps\": 0,\n        \"duration_sec\": 0,\n        \"bytes_transferred\": 0,\n        \"server_rss_before_kb\": None,\n        \"server_rss_after_kb\": None,\n        \"tunnel_rss_before_kb\": None,\n        \"tunnel_rss_after_kb\": None,\n        \"error\": None,\n    }\n\n    ss_server_bin = os.path.join(bin_dir, \"ss-server\")\n    ss_tunnel_bin = os.path.join(bin_dir, \"ss-tunnel\")\n\n    if not os.path.isfile(ss_server_bin) or not os.path.isfile(ss_tunnel_bin):\n        result[\"error\"] = \"binaries not found in %s\" % bin_dir\n        return result\n\n    server_proc = None\n    tunnel_proc = None\n    sink = None\n    devnull = open(os.devnull, \"w\")\n\n    try:\n        # Start sink server (the destination ss-tunnel forwards to)\n        sink = SinkServer(SINK_PORT)\n\n        # Start ss-server\n        server_proc = Popen(\n            server_args(ss_server_bin, cipher, password, SERVER_PORT),\n            stdout=devnull, stderr=devnull, close_fds=True\n        )\n\n        # Start ss-tunnel forwarding to the sink\n        tunnel_proc = Popen(\n            tunnel_args(ss_tunnel_bin, cipher, password, SERVER_PORT,\n                        TUNNEL_LOCAL_PORT, \"127.0.0.1\", SINK_PORT),\n            stdout=devnull, stderr=devnull, close_fds=True\n        )\n\n        # Wait for processes to start and bind ports\n        # Don't probe the ports as ss-tunnel crashes on empty connections\n        time.sleep(3.0)\n\n        if server_proc.poll() is not None:\n            result[\"error\"] = \"ss-server exited prematurely (code %d)\" % server_proc.returncode\n            return result\n\n        if tunnel_proc.poll() is not None:\n            result[\"error\"] = \"ss-tunnel exited prematurely (code %d)\" % tunnel_proc.returncode\n            return result\n\n        # Record RSS before\n        result[\"server_rss_before_kb\"] = get_rss_kb(server_proc.pid)\n        result[\"tunnel_rss_before_kb\"] = get_rss_kb(tunnel_proc.pid)\n\n        # Send data through the tunnel\n        chunk_size = 64 * 1024  # 64KB chunks\n        total_bytes = data_size_mb * 1024 * 1024\n        data_chunk = b\"\\x00\" * chunk_size\n\n        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        sock.settimeout(30)\n        try:\n            sock.connect((\"127.0.0.1\", TUNNEL_LOCAL_PORT))\n        except (socket.error, OSError) as e:\n            result[\"error\"] = \"connect to tunnel failed: %s\" % e\n            return result\n\n        sent = 0\n        start_time = time.time()\n\n        try:\n            while sent < total_bytes:\n                remaining = total_bytes - sent\n                to_send = min(chunk_size, remaining)\n                if to_send < chunk_size:\n                    data_chunk = b\"\\x00\" * to_send\n                sock.sendall(data_chunk)\n                sent += to_send\n        except (socket.error, OSError) as e:\n            result[\"error\"] = \"send error at %d bytes: %s\" % (sent, e)\n        finally:\n            elapsed = time.time() - start_time\n            try:\n                sock.shutdown(socket.SHUT_WR)\n            except OSError:\n                pass\n            sock.close()\n\n        # Wait a bit for data to flow through\n        time.sleep(0.5)\n\n        result[\"bytes_transferred\"] = sent\n        result[\"duration_sec\"] = elapsed\n        if elapsed > 0:\n            result[\"bandwidth_mbps\"] = (sent * 8) / (elapsed * 1e6)\n\n        # Record RSS after\n        result[\"server_rss_after_kb\"] = get_rss_kb(server_proc.pid)\n        result[\"tunnel_rss_after_kb\"] = get_rss_kb(tunnel_proc.pid)\n\n    except Exception as e:\n        result[\"error\"] = str(e)\n    finally:\n        kill_proc(tunnel_proc)\n        kill_proc(server_proc)\n        if sink:\n            sink.stop()\n        devnull.close()\n\n    return result\n\n\ndef format_size(nbytes):\n    if nbytes >= 1024 * 1024 * 1024:\n        return \"%.1f GB\" % (nbytes / (1024 * 1024 * 1024))\n    elif nbytes >= 1024 * 1024:\n        return \"%.1f MB\" % (nbytes / (1024 * 1024))\n    elif nbytes >= 1024:\n        return \"%.1f KB\" % (nbytes / 1024)\n    return \"%d B\" % nbytes\n\n\ndef format_rss(kb):\n    if kb is None:\n        return \"N/A\"\n    if kb >= 1024:\n        return \"%.1f MB\" % (kb / 1024.0)\n    return \"%d KB\" % kb\n\n\ndef main():\n    parser = argparse.ArgumentParser(\n        description=\"Stress test ss-server + ss-tunnel bandwidth on loopback\"\n    )\n    parser.add_argument(\n        \"--bin\", type=str, required=True,\n        help=\"Path to directory containing ss-server and ss-tunnel binaries\"\n    )\n    parser.add_argument(\n        \"--size\", type=int, default=100,\n        help=\"Data size to transfer per cipher in MB (default: 100)\"\n    )\n    parser.add_argument(\n        \"--cipher\", type=str, default=None,\n        help=\"Test only this specific cipher\"\n    )\n    parser.add_argument(\n        \"--repeat\", type=int, default=1,\n        help=\"Number of times to repeat each cipher test (default: 1)\"\n    )\n    parser.add_argument(\n        \"--stream\", action=\"store_true\",\n        help=\"Include stream ciphers (deprecated, insecure)\"\n    )\n    parser.add_argument(\n        \"--leak-threshold\", type=int, default=10240,\n        help=\"RSS growth threshold in KB to flag as potential leak (default: 10240)\"\n    )\n    parser.add_argument(\n        \"--json\", type=str, default=None,\n        help=\"Write results as JSON to this file\"\n    )\n    args = parser.parse_args()\n\n    # Determine ciphers to test\n    if args.cipher:\n        ciphers = [args.cipher]\n    elif args.stream:\n        ciphers = ALL_CIPHERS\n    else:\n        ciphers = AEAD_CIPHERS\n\n    print(\"=\" * 72)\n    print(\"shadowsocks-libev stress test\")\n    print(\"=\" * 72)\n    print(\"  Binaries : %s\" % os.path.abspath(args.bin))\n    print(\"  Data size: %d MB per cipher\" % args.size)\n    print(\"  Ciphers  : %s\" % \", \".join(ciphers))\n    print(\"  Repeats  : %d\" % args.repeat)\n    print(\"=\" * 72)\n    print()\n\n    all_results = []\n    leak_warnings = []\n\n    for cipher in ciphers:\n        for run in range(args.repeat):\n            label = cipher\n            if args.repeat > 1:\n                label = \"%s (run %d/%d)\" % (cipher, run + 1, args.repeat)\n\n            sys.stdout.write(\"Testing %-35s ... \" % label)\n            sys.stdout.flush()\n\n            result = run_bandwidth_test(args.bin, cipher, args.size)\n            all_results.append(result)\n\n            if result[\"error\"]:\n                print(\"FAILED: %s\" % result[\"error\"])\n                continue\n\n            bw = result[\"bandwidth_mbps\"]\n            dur = result[\"duration_sec\"]\n            print(\"%8.1f Mbps  (%5.2fs, %s)\" % (\n                bw, dur, format_size(result[\"bytes_transferred\"])\n            ))\n\n            # Check for memory leaks\n            for role in [\"server\", \"tunnel\"]:\n                before = result[\"%s_rss_before_kb\" % role]\n                after = result[\"%s_rss_after_kb\" % role]\n                if before is not None and after is not None:\n                    growth = after - before\n                    if growth > args.leak_threshold:\n                        msg = (\n                            \"  WARNING: ss-%s RSS grew by %s \"\n                            \"(%s -> %s) during %s test\"\n                            % (role, format_rss(growth),\n                               format_rss(before), format_rss(after), cipher)\n                        )\n                        print(msg)\n                        leak_warnings.append(msg)\n\n    # Summary\n    print()\n    print(\"=\" * 72)\n    print(\"RESULTS SUMMARY\")\n    print(\"=\" * 72)\n    print()\n    print(\"%-30s %10s %8s %12s %12s\" % (\n        \"Cipher\", \"Bandwidth\", \"Time\", \"Server RSS\", \"Tunnel RSS\"\n    ))\n    print(\"-\" * 72)\n\n    for r in all_results:\n        if r[\"error\"]:\n            print(\"%-30s %10s\" % (r[\"cipher\"], \"FAILED\"))\n            continue\n\n        srv_rss = \"\"\n        tun_rss = \"\"\n        if r[\"server_rss_before_kb\"] and r[\"server_rss_after_kb\"]:\n            srv_rss = \"%s->%s\" % (\n                format_rss(r[\"server_rss_before_kb\"]),\n                format_rss(r[\"server_rss_after_kb\"])\n            )\n        if r[\"tunnel_rss_before_kb\"] and r[\"tunnel_rss_after_kb\"]:\n            tun_rss = \"%s->%s\" % (\n                format_rss(r[\"tunnel_rss_before_kb\"]),\n                format_rss(r[\"tunnel_rss_after_kb\"])\n            )\n        print(\"%-30s %7.1f Mbps %6.2fs %12s %12s\" % (\n            r[\"cipher\"], r[\"bandwidth_mbps\"], r[\"duration_sec\"],\n            srv_rss or \"N/A\", tun_rss or \"N/A\"\n        ))\n\n    if leak_warnings:\n        print()\n        print(\"MEMORY LEAK WARNINGS:\")\n        for w in leak_warnings:\n            print(w)\n        print()\n        sys.exit(1)\n\n    print()\n    passed = [r for r in all_results if not r[\"error\"]]\n    failed = [r for r in all_results if r[\"error\"]]\n    print(\"%d passed, %d failed\" % (len(passed), len(failed)))\n\n    if args.json:\n        with open(args.json, \"w\") as f:\n            json.dump(all_results, f, indent=2)\n        print(\"Results written to %s\" % args.json)\n\n    if failed:\n        sys.exit(1)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "tests/test.py",
    "content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\n#\n# Copyright 2015 clowwindy\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\nfrom __future__ import absolute_import, division, print_function, \\\n    with_statement\n\nimport sys\nimport os\nimport signal\nimport select\nimport time\nimport argparse\nfrom subprocess import Popen, PIPE\n\ndefault_url = 'http://www.google.com/'\n\nparser = argparse.ArgumentParser(description='test Shadowsocks')\nparser.add_argument('-c', '--client-conf', type=str, default=None)\nparser.add_argument('-s', '--server-conf', type=str, default=None)\nparser.add_argument('-a', '--client-args', type=str, default=None)\nparser.add_argument('-b', '--server-args', type=str, default=None)\nparser.add_argument('--should-fail', action='store_true', default=None)\nparser.add_argument('--url', type=str, default=default_url)\nparser.add_argument('--dns', type=str, default='8.8.8.8')\nparser.add_argument('--bin', type=str, default='')\n\nconfig = parser.parse_args()\n\nclient_args = ['%s%s' % (config.bin, 'ss-local'), '-v']\nserver_args = ['%s%s' % (config.bin, 'ss-server'), '-v', '-u']\ntunnel_args = ['%s%s' % (config.bin, 'ss-tunnel'), '-v', '-u', '-l1082', '-L%s:53' % config.dns]\n\nif config.client_conf:\n    client_args.extend(['-c', config.client_conf])\n    tunnel_args.extend(['-c', config.client_conf])\n    if config.server_conf:\n        server_args.extend(['-c', config.server_conf])\n    else:\n        server_args.extend(['-c', config.client_conf])\n\nif config.client_args:\n    client_args.extend(config.client_args.split())\n    tunnel_args.extend(config.client_args.split())\n    if config.server_args:\n        server_args.extend(config.server_args.split())\n    else:\n        server_args.extend(config.client_args.split())\n\np1 = Popen(server_args, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)\np2 = Popen(client_args, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)\np5 = Popen(tunnel_args, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)\np3 = None\np4 = None\np3_fin = False\np4_fin = False\n\n# 1 shadowsocks started\n# 2 curl started\n# 3 curl finished\n# 4 dig started\n# 5 dig finished\nstage = 1\n\ntry:\n    fdset = []\n    time.sleep(2)\n\n    p3 = Popen(['curl', config.url, '-v', '-L',\n        '--socks5-hostname', '127.0.0.1:1081',\n        '-m', '15', '--connect-timeout', '10'],\n        stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)\n    if p3 is not None:\n        fdset.append(p3.stdout)\n        fdset.append(p3.stderr)\n        stage = 2\n    else:\n        sys.exit(1)\n\n    while True:\n        r, w, e = select.select(fdset, [], fdset)\n        if e:\n            break\n\n        for fd in r:\n            line = fd.readline()\n            if not line:\n                if stage == 2 and fd == p3.stdout:\n                    stage = 3\n                if stage == 4 and fd == p4.stdout:\n                    stage = 5\n            if bytes != str:\n                line = bytes(line)\n                sys.stderr.buffer.write(line)\n            else:\n                sys.stderr.write(line)\n\n        if stage == 3 and p3 is not None:\n            fdset.remove(p3.stdout)\n            fdset.remove(p3.stderr)\n            r = p3.wait()\n            if config.should_fail:\n                if r == 0:\n                    sys.exit(1)\n            else:\n                if r != 0:\n                    sys.exit(1)\n            p4 = Popen(['dig', '@127.0.0.1', '-p1082',\n                        'www.google.com'],\n                       stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)\n            if p4 is not None:\n                fdset.append(p4.stdout)\n                fdset.append(p4.stderr)\n                stage = 4\n            else:\n                sys.exit(1)\n\n        if stage == 5:\n            r = p4.wait()\n            if config.should_fail:\n                if r == 0:\n                    sys.exit(1)\n                print('test passed (expecting failure)')\n            else:\n                if r != 0:\n                    sys.exit(1)\n                print('test passed')\n            break\nfinally:\n    for p in [p1, p2, p5]:\n        try:\n            os.kill(p.pid, signal.SIGINT)\n            os.waitpid(p.pid, 0)\n        except OSError:\n            pass\n"
  },
  {
    "path": "tests/test.sh",
    "content": "#!/bin/bash\n\nresult=0\n\nfunction run_test {\n    printf '\\e[0;36m'\n    echo \"running test: $command $@\"\n    printf '\\e[0m'\n\n    $command \"$@\"\n    status=$?\n    if [ $status -ne 0 ]; then\n        printf '\\e[0;31m'\n        echo \"test failed: $command $@\"\n        printf '\\e[0m'\n        echo\n        result=1\n    else\n        printf '\\e[0;32m'\n        echo OK\n        printf '\\e[0m'\n        echo\n    fi\n    return 0\n}\n\n[ -d src -a -x src/ss-local ] &&\n    BIN=\"--bin src/\"\n\nif [ \"$http_proxy\" ]; then\n    echo \"SKIP: shadowsocks-libev does not support an upstream HTTP proxy\"\n    exit 0\nfi\n\nrun_test python tests/test.py $BIN -c tests/aes.json\nrun_test python tests/test.py $BIN -c tests/aes-gcm.json\nrun_test python tests/test.py $BIN -c tests/aes-ctr.json\nrun_test python tests/test.py $BIN -c tests/rc4-md5.json\nrun_test python tests/test.py $BIN -c tests/salsa20.json\nrun_test python tests/test.py $BIN -c tests/chacha20.json\nrun_test python tests/test.py $BIN -c tests/chacha20-ietf.json\nrun_test python tests/test.py $BIN -c tests/chacha20-ietf-poly1305.json\n\nexit $result\n"
  },
  {
    "path": "tests/test_base64.c",
    "content": "#include <assert.h>\n#include <string.h>\n#include <stdint.h>\n\n#include \"base64.h\"\n\nstatic void\ntest_encode_decode(void)\n{\n    /* Known test vector: \"Hello\" */\n    const uint8_t input[] = \"Hello\";\n    char encoded[BASE64_SIZE(5)];\n    uint8_t decoded[5];\n\n    char *ret = base64_encode(encoded, sizeof(encoded), input, 5);\n    assert(ret != NULL);\n    assert(strlen(encoded) > 0);\n\n    int decoded_len = base64_decode(decoded, encoded, sizeof(decoded));\n    assert(decoded_len == 5);\n    assert(memcmp(decoded, input, 5) == 0);\n}\n\nstatic void\ntest_empty_input(void)\n{\n    char encoded[BASE64_SIZE(0)];\n    char *ret = base64_encode(encoded, sizeof(encoded), (const uint8_t *)\"\", 0);\n    assert(ret != NULL);\n    assert(strlen(encoded) == 0);\n}\n\nstatic void\ntest_single_byte(void)\n{\n    const uint8_t input[] = { 0x41 }; /* 'A' */\n    char encoded[BASE64_SIZE(1)];\n    uint8_t decoded[1];\n\n    char *ret = base64_encode(encoded, sizeof(encoded), input, 1);\n    assert(ret != NULL);\n\n    int decoded_len = base64_decode(decoded, encoded, sizeof(decoded));\n    assert(decoded_len == 1);\n    assert(decoded[0] == 0x41);\n}\n\nstatic void\ntest_two_bytes(void)\n{\n    const uint8_t input[] = { 0x41, 0x42 }; /* \"AB\" */\n    char encoded[BASE64_SIZE(2)];\n    uint8_t decoded[2];\n\n    char *ret = base64_encode(encoded, sizeof(encoded), input, 2);\n    assert(ret != NULL);\n\n    int decoded_len = base64_decode(decoded, encoded, sizeof(decoded));\n    assert(decoded_len == 2);\n    assert(decoded[0] == 0x41);\n    assert(decoded[1] == 0x42);\n}\n\nstatic void\ntest_three_bytes(void)\n{\n    const uint8_t input[] = { 0x00, 0xFF, 0x80 };\n    char encoded[BASE64_SIZE(3)];\n    uint8_t decoded[3];\n\n    char *ret = base64_encode(encoded, sizeof(encoded), input, 3);\n    assert(ret != NULL);\n\n    int decoded_len = base64_decode(decoded, encoded, sizeof(decoded));\n    assert(decoded_len == 3);\n    assert(decoded[0] == 0x00);\n    assert(decoded[1] == 0xFF);\n    assert(decoded[2] == 0x80);\n}\n\nstatic void\ntest_roundtrip_binary(void)\n{\n    const uint8_t input[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,\n                              10, 11, 12, 13, 14, 15, 16 };\n    char encoded[BASE64_SIZE(17)];\n    uint8_t decoded[17];\n\n    char *ret = base64_encode(encoded, sizeof(encoded), input, 17);\n    assert(ret != NULL);\n\n    int decoded_len = base64_decode(decoded, encoded, sizeof(decoded));\n    assert(decoded_len == 17);\n    assert(memcmp(decoded, input, 17) == 0);\n}\n\nstatic void\ntest_invalid_chars(void)\n{\n    /* Character '!' (ASCII 33) is below the base64 range start ('+' = 43) */\n    int decoded_len = base64_decode((uint8_t[4]){}, \"!!!!\", 4);\n    assert(decoded_len == -1);\n}\n\nint\nmain(void)\n{\n    test_encode_decode();\n    test_empty_input();\n    test_single_byte();\n    test_two_bytes();\n    test_three_bytes();\n    test_roundtrip_binary();\n    test_invalid_chars();\n    return 0;\n}\n"
  },
  {
    "path": "tests/test_buffer.c",
    "content": "#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <assert.h>\n#include <string.h>\n#include <stdlib.h>\n\nint verbose = 0;\n\n#include \"crypto.h\"\n\n/* Provide nonce_cache symbol needed by crypto.c */\nstruct cache *nonce_cache = NULL;\n\nstatic void\ntest_balloc(void)\n{\n    buffer_t buf;\n    memset(&buf, 0, sizeof(buf));\n\n    int ret = balloc(&buf, 100);\n    assert(ret == 0);\n    (void)ret;\n    assert(buf.data != NULL);\n    assert(buf.capacity >= 100);\n    assert(buf.len == 0);\n    assert(buf.idx == 0);\n\n    bfree(&buf);\n    assert(buf.data == NULL);\n    assert(buf.capacity == 0);\n}\n\nstatic void\ntest_brealloc(void)\n{\n    buffer_t buf;\n    memset(&buf, 0, sizeof(buf));\n\n    balloc(&buf, 50);\n    buf.len = 10;\n\n    /* Grow the buffer */\n    int ret = brealloc(&buf, 10, 200);\n    assert(ret == 0);\n    (void)ret;\n    assert(buf.capacity >= 200);\n    assert(buf.len == 10);\n\n    bfree(&buf);\n}\n\nstatic void\ntest_bprepend(void)\n{\n    buffer_t dst, src;\n    memset(&dst, 0, sizeof(dst));\n    memset(&src, 0, sizeof(src));\n\n    balloc(&dst, 100);\n    balloc(&src, 100);\n\n    /* Put some data in src */\n    memcpy(src.data, \"HEADER\", 6);\n    src.len = 6;\n\n    /* Put some data in dst */\n    memcpy(dst.data, \"BODY\", 4);\n    dst.len = 4;\n\n    int ret = bprepend(&dst, &src, 200);\n    assert(ret == 0);\n    (void)ret;\n    assert(dst.len == 10);\n    assert(memcmp(dst.data, \"HEADERBODY\", 10) == 0);\n\n    bfree(&dst);\n    bfree(&src);\n}\n\nstatic void\ntest_balloc_zero(void)\n{\n    buffer_t buf;\n    memset(&buf, 0, sizeof(buf));\n\n    int ret = balloc(&buf, 0);\n    assert(ret == 0);\n    (void)ret;\n    /* A zero-capacity buffer should still succeed */\n    bfree(&buf);\n}\n\nint\nmain(void)\n{\n    test_balloc();\n    test_brealloc();\n    test_bprepend();\n    test_balloc_zero();\n    return 0;\n}\n"
  },
  {
    "path": "tests/test_cache.c",
    "content": "#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <assert.h>\n#include <string.h>\n#include <stdlib.h>\n#include <errno.h>\n\nint verbose = 0;\n\n#include \"cache.h\"\n\nstatic void\ntest_create_delete(void)\n{\n    struct cache *c = NULL;\n    int ret = cache_create(&c, 100, NULL);\n    assert(ret == 0);\n    assert(c != NULL);\n\n    ret = cache_delete(c, 0);\n    assert(ret == 0);\n    (void)ret;\n}\n\nstatic void\ntest_create_null(void)\n{\n    int ret = cache_create(NULL, 100, NULL);\n    assert(ret == EINVAL);\n    (void)ret;\n}\n\nstatic void\ntest_insert_lookup(void)\n{\n    struct cache *c = NULL;\n    cache_create(&c, 100, NULL);\n\n    char *data = strdup(\"test_data\");\n    cache_insert(c, \"key1\", 4, data);\n\n    char *result = NULL;\n    cache_lookup(c, \"key1\", 4, &result);\n    assert(result != NULL);\n    assert(strcmp(result, \"test_data\") == 0);\n\n    cache_delete(c, 0);\n}\n\nstatic void\ntest_key_exist(void)\n{\n    struct cache *c = NULL;\n    cache_create(&c, 100, NULL);\n\n    char *data = strdup(\"value\");\n    cache_insert(c, \"mykey\", 5, data);\n\n    assert(cache_key_exist(c, \"mykey\", 5) == 1);\n    assert(cache_key_exist(c, \"nokey\", 5) == 0);\n\n    cache_delete(c, 0);\n}\n\nstatic void\ntest_remove(void)\n{\n    struct cache *c = NULL;\n    cache_create(&c, 100, NULL);\n\n    char *data = strdup(\"to_remove\");\n    cache_insert(c, \"rmkey\", 5, data);\n    assert(cache_key_exist(c, \"rmkey\", 5) == 1);\n\n    cache_remove(c, \"rmkey\", 5);\n    assert(cache_key_exist(c, \"rmkey\", 5) == 0);\n\n    cache_delete(c, 0);\n}\n\nstatic void\ntest_lookup_missing(void)\n{\n    struct cache *c = NULL;\n    cache_create(&c, 100, NULL);\n\n    char *result = (char *)0xdeadbeef;\n    cache_lookup(c, \"missing\", 7, &result);\n    assert(result == NULL);\n\n    cache_delete(c, 0);\n}\n\nstatic void\ntest_eviction(void)\n{\n    struct cache *c = NULL;\n    cache_create(&c, 3, NULL);\n\n    /* Insert 3 entries to fill cache */\n    cache_insert(c, \"k1\", 2, strdup(\"v1\"));\n    cache_insert(c, \"k2\", 2, strdup(\"v2\"));\n    cache_insert(c, \"k3\", 2, strdup(\"v3\"));\n\n    /* This should trigger eviction of the oldest entry */\n    cache_insert(c, \"k4\", 2, strdup(\"v4\"));\n\n    /* k1 should have been evicted */\n    assert(cache_key_exist(c, \"k1\", 2) == 0);\n    /* k4 should exist */\n    assert(cache_key_exist(c, \"k4\", 2) == 1);\n\n    cache_delete(c, 0);\n}\n\nint\nmain(void)\n{\n    test_create_delete();\n    test_create_null();\n    test_insert_lookup();\n    test_key_exist();\n    test_remove();\n    test_lookup_missing();\n    test_eviction();\n    return 0;\n}\n"
  },
  {
    "path": "tests/test_crypto.c",
    "content": "#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <assert.h>\n#include <string.h>\n#include <stdlib.h>\n#include <sodium.h>\n\nint verbose = 0;\n\n#include \"crypto.h\"\n\n/* Provide nonce_cache symbol needed by crypto.c */\nstruct cache *nonce_cache = NULL;\n\nstatic void\ntest_crypto_md5(void)\n{\n    /* MD5(\"\") = d41d8cd98f00b204e9800998ecf8427e */\n    unsigned char result[16];\n    crypto_md5((const unsigned char *)\"\", 0, result);\n\n    unsigned char expected[] = {\n        0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,\n        0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e\n    };\n    assert(memcmp(result, expected, 16) == 0);\n    (void)expected;\n\n    /* MD5(\"abc\") = 900150983cd24fb0d6963f7d28e17f72 */\n    crypto_md5((const unsigned char *)\"abc\", 3, result);\n    unsigned char expected_abc[] = {\n        0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,\n        0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72\n    };\n    assert(memcmp(result, expected_abc, 16) == 0);\n    (void)expected_abc;\n}\n\nstatic void\ntest_crypto_derive_key(void)\n{\n    uint8_t key[32];\n\n    /* derive_key should produce deterministic output from a password */\n    int ret = crypto_derive_key(\"password\", key, 32);\n    assert(ret == 32);\n\n    /* Same password should produce same key */\n    uint8_t key2[32];\n    ret = crypto_derive_key(\"password\", key2, 32);\n    assert(ret == 32);\n    assert(memcmp(key, key2, 32) == 0);\n\n    /* Different password should produce different key */\n    uint8_t key3[32];\n    ret = crypto_derive_key(\"different\", key3, 32);\n    assert(ret == 32);\n    assert(memcmp(key, key3, 32) != 0);\n    (void)ret;\n}\n\nstatic void\ntest_crypto_hkdf(void)\n{\n    /* RFC 5869 Test Case 1 */\n    const mbedtls_md_info_t *md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);\n    assert(md != NULL);\n\n    unsigned char ikm[22];\n    memset(ikm, 0x0b, 22);\n\n    unsigned char salt[] = {\n        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n        0x08, 0x09, 0x0a, 0x0b, 0x0c\n    };\n\n    unsigned char info[] = {\n        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,\n        0xf8, 0xf9\n    };\n\n    unsigned char okm[42];\n    int ret = crypto_hkdf(md, salt, sizeof(salt), ikm, sizeof(ikm),\n                          info, sizeof(info), okm, sizeof(okm));\n    assert(ret == 0);\n    (void)ret;\n\n    unsigned char expected_okm[] = {\n        0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a,\n        0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,\n        0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,\n        0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,\n        0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,\n        0x58, 0x65\n    };\n    assert(memcmp(okm, expected_okm, 42) == 0);\n    (void)expected_okm;\n}\n\nstatic void\ntest_crypto_hkdf_extract(void)\n{\n    const mbedtls_md_info_t *md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);\n    assert(md != NULL);\n\n    unsigned char ikm[22];\n    memset(ikm, 0x0b, 22);\n\n    unsigned char salt[] = {\n        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n        0x08, 0x09, 0x0a, 0x0b, 0x0c\n    };\n\n    unsigned char prk[32];\n    int ret = crypto_hkdf_extract(md, salt, sizeof(salt), ikm, sizeof(ikm), prk);\n    assert(ret == 0);\n    (void)ret;\n\n    /* RFC 5869 Test Case 1 PRK */\n    unsigned char expected_prk[] = {\n        0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf,\n        0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63,\n        0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31,\n        0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5\n    };\n    assert(memcmp(prk, expected_prk, 32) == 0);\n    (void)expected_prk;\n}\n\nstatic void\ntest_crypto_parse_key(void)\n{\n    /* base64_encode uses URL-safe base64 with -_ instead of +/ */\n    uint8_t key[32];\n\n    /* A known base64-encoded 32-byte key (all zeros) */\n    /* 32 zero bytes = \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\" in standard base64 */\n    /* With URL-safe: same since no +/ needed */\n    int ret = crypto_parse_key(\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\", key, 32);\n    assert(ret == 32);\n    (void)ret;\n\n    /* All bytes should be 0 */\n    for (int i = 0; i < 32; i++) {\n        assert(key[i] == 0);\n    }\n}\n\nint\nmain(void)\n{\n    if (sodium_init() < 0) {\n        return 1;\n    }\n\n    test_crypto_md5();\n    test_crypto_derive_key();\n    test_crypto_hkdf();\n    test_crypto_hkdf_extract();\n    test_crypto_parse_key();\n    return 0;\n}\n"
  },
  {
    "path": "tests/test_deb_build.sh",
    "content": "#!/bin/bash\n#\n# Test that Debian packages build, contain expected files, install, and work.\n#\n# Usage: bash tests/test_deb_build.sh\n#\n# Requirements (Linux only):\n#   - dpkg-buildpackage, debhelper, fakeroot\n#   - Build dependencies listed in debian/control\n#   - sudo (for install phase)\n#\n\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_DIR=\"$(cd \"$SCRIPT_DIR/..\" && pwd)\"\n\n# --- helpers ----------------------------------------------------------------\n\nPASS_COUNT=0\nFAIL_COUNT=0\nFAILURES=\"\"\n\nlog() {\n    echo \"=== [test_deb_build] $* ===\"\n}\n\ncheck_pass() {\n    PASS_COUNT=$((PASS_COUNT + 1))\n    echo \"  PASS: $*\"\n}\n\ncheck_fail() {\n    FAIL_COUNT=$((FAIL_COUNT + 1))\n    FAILURES=\"${FAILURES}  FAIL: $*\"$'\\n'\n    echo \"  FAIL: $*\"\n}\n\n# check_file_in_deb DEB_FILE PATTERN DESCRIPTION\n# Verifies that at least one file matching PATTERN exists in the .deb\ncheck_file_in_deb() {\n    local deb=\"$1\" pattern=\"$2\" desc=\"$3\"\n    # Avoid grep -q: with pipefail, early grep exit causes SIGPIPE on dpkg-deb\n    if dpkg-deb -c \"$deb\" | grep -E \"$pattern\" >/dev/null; then\n        check_pass \"$desc\"\n    else\n        check_fail \"$desc\"\n    fi\n}\n\n# check_command CMD DESCRIPTION\n# Verifies that a command runs successfully (exit 0)\ncheck_command() {\n    local desc=\"$2\"\n    if eval \"$1\" >/dev/null 2>&1; then\n        check_pass \"$desc\"\n    else\n        check_fail \"$desc\"\n    fi\n}\n\nsummary() {\n    echo \"\"\n    log \"Results: $PASS_COUNT passed, $FAIL_COUNT failed\"\n    if [ \"$FAIL_COUNT\" -gt 0 ]; then\n        echo \"\"\n        echo \"Failures:\"\n        printf '%s' \"$FAILURES\"\n        exit 1\n    fi\n}\n\n# --- phase 1: build --------------------------------------------------------\n\nlog \"Phase 1: Build Debian packages\"\n\ncd \"$PROJECT_DIR\"\n\n# dpkg-buildpackage -b builds binary-only packages (no .orig.tar.gz needed)\ndpkg-buildpackage -b -us -uc -j\"$(nproc)\"\n\n# .deb files are placed in the parent directory\nPARENT_DIR=\"$(dirname \"$PROJECT_DIR\")\"\n\nDEB_MAIN=\"\"\nDEB_LIB=\"\"\nDEB_DEV=\"\"\nfor f in \"$PARENT_DIR\"/shadowsocks-libev_*.deb; do\n    [ -f \"$f\" ] && DEB_MAIN=\"$f\" && break\ndone\nfor f in \"$PARENT_DIR\"/libshadowsocks-libev2_*.deb; do\n    [ -f \"$f\" ] && DEB_LIB=\"$f\" && break\ndone\nfor f in \"$PARENT_DIR\"/libshadowsocks-libev-dev_*.deb; do\n    [ -f \"$f\" ] && DEB_DEV=\"$f\" && break\ndone\n\n# --- phase 2: verify contents ----------------------------------------------\n\nlog \"Phase 2: Verify package contents\"\n\n# Check all three .deb files exist\nif [ -n \"$DEB_MAIN\" ] && [ -f \"$DEB_MAIN\" ]; then\n    check_pass \"shadowsocks-libev .deb exists: $(basename \"$DEB_MAIN\")\"\nelse\n    check_fail \"shadowsocks-libev .deb not found\"\nfi\n\nif [ -n \"$DEB_LIB\" ] && [ -f \"$DEB_LIB\" ]; then\n    check_pass \"libshadowsocks-libev2 .deb exists: $(basename \"$DEB_LIB\")\"\nelse\n    check_fail \"libshadowsocks-libev2 .deb not found\"\nfi\n\nif [ -n \"$DEB_DEV\" ] && [ -f \"$DEB_DEV\" ]; then\n    check_pass \"libshadowsocks-libev-dev .deb exists: $(basename \"$DEB_DEV\")\"\nelse\n    check_fail \"libshadowsocks-libev-dev .deb not found\"\nfi\n\n# Bail early if any .deb is missing - remaining checks would all fail\nif [ \"$FAIL_COUNT\" -gt 0 ]; then\n    summary\nfi\n\n# Main package: binaries\nfor bin in ss-local ss-server ss-redir ss-tunnel ss-manager; do\n    check_file_in_deb \"$DEB_MAIN\" \"usr/bin/${bin}\" \"$bin binary in main package\"\ndone\n\n# Main package: man pages\nfor bin in ss-local ss-server ss-redir ss-tunnel ss-manager; do\n    check_file_in_deb \"$DEB_MAIN\" \"usr/share/man/man1/$bin\\\\.1\" \"$bin man page in main package\"\ndone\n\n# Shared library package\ncheck_file_in_deb \"$DEB_LIB\" \"usr/lib/.*/libshadowsocks-libev\\\\.so\\\\.\" \"shared library in lib package\"\n\n# Dev package: header\ncheck_file_in_deb \"$DEB_DEV\" \"usr/include/shadowsocks\\\\.h\" \"shadowsocks.h header in dev package\"\n\n# Dev package: pkg-config\ncheck_file_in_deb \"$DEB_DEV\" \"usr/lib/.*/pkgconfig/shadowsocks-libev\\\\.pc\" \"pkg-config file in dev package\"\n\n# Dev package: unversioned .so symlink\ncheck_file_in_deb \"$DEB_DEV\" \"usr/lib/.*/libshadowsocks-libev\\\\.so[^.]\" \"unversioned .so symlink in dev package\"\n\n# --- phase 3: install -------------------------------------------------------\n\nlog \"Phase 3: Install packages\"\n\nsudo dpkg -i \"$DEB_LIB\" \"$DEB_DEV\" \"$DEB_MAIN\" || true\nsudo apt-get -f install -y\n\n# Verify dpkg thinks they are installed\nfor pkg in shadowsocks-libev libshadowsocks-libev2 libshadowsocks-libev-dev; do\n    if dpkg -s \"$pkg\" >/dev/null 2>&1; then\n        check_pass \"$pkg installed\"\n    else\n        check_fail \"$pkg not installed\"\n    fi\ndone\n\n# --- phase 4: smoke-test ----------------------------------------------------\n\nlog \"Phase 4: Smoke-test installed binaries\"\n\n# Each binary should respond to --help\nfor bin in ss-local ss-server ss-redir ss-tunnel ss-manager; do\n    check_command \"$bin --help\" \"$bin --help runs\"\ndone\n\n# Shared library should be findable by ldconfig\nsudo ldconfig\nif ldconfig -p | grep -q libshadowsocks-libev; then\n    check_pass \"libshadowsocks-libev found by ldconfig\"\nelse\n    check_fail \"libshadowsocks-libev not found by ldconfig\"\nfi\n\n# Header should be in the include path\nif [ -f /usr/include/shadowsocks.h ]; then\n    check_pass \"shadowsocks.h installed in /usr/include\"\nelse\n    check_fail \"shadowsocks.h not installed in /usr/include\"\nfi\n\n# --- summary ----------------------------------------------------------------\n\nsummary\n"
  },
  {
    "path": "tests/test_jconf.c",
    "content": "#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <assert.h>\n#include <string.h>\n#include <stdlib.h>\n\nint verbose = 0;\n\n#include \"netutils.h\"\n#include \"jconf.h\"\n\nstatic void\ntest_parse_addr_ipv4_with_port(void)\n{\n    ss_addr_t addr;\n    memset(&addr, 0, sizeof(addr));\n    parse_addr(\"192.168.1.1:8080\", &addr);\n    assert(addr.host != NULL);\n    assert(addr.port != NULL);\n    assert(strcmp(addr.host, \"192.168.1.1\") == 0);\n    assert(strcmp(addr.port, \"8080\") == 0);\n    free_addr(&addr);\n}\n\nstatic void\ntest_parse_addr_ipv6_with_port(void)\n{\n    ss_addr_t addr;\n    memset(&addr, 0, sizeof(addr));\n    parse_addr(\"[::1]:443\", &addr);\n    assert(addr.host != NULL);\n    assert(addr.port != NULL);\n    assert(strcmp(addr.host, \"::1\") == 0);\n    assert(strcmp(addr.port, \"443\") == 0);\n    free_addr(&addr);\n}\n\nstatic void\ntest_parse_addr_hostname_with_port(void)\n{\n    ss_addr_t addr;\n    memset(&addr, 0, sizeof(addr));\n    parse_addr(\"example.com:1234\", &addr);\n    assert(addr.host != NULL);\n    assert(addr.port != NULL);\n    assert(strcmp(addr.host, \"example.com\") == 0);\n    assert(strcmp(addr.port, \"1234\") == 0);\n    free_addr(&addr);\n}\n\nstatic void\ntest_parse_addr_no_port(void)\n{\n    ss_addr_t addr;\n    memset(&addr, 0, sizeof(addr));\n    parse_addr(\"10.0.0.1\", &addr);\n    assert(addr.host != NULL);\n    assert(strcmp(addr.host, \"10.0.0.1\") == 0);\n    /* Port may be NULL when no port is specified */\n    free_addr(&addr);\n}\n\nstatic void\ntest_parse_addr_ipv6_no_port(void)\n{\n    ss_addr_t addr;\n    memset(&addr, 0, sizeof(addr));\n    parse_addr(\"::1\", &addr);\n    assert(addr.host != NULL);\n    assert(strcmp(addr.host, \"::1\") == 0);\n    free_addr(&addr);\n}\n\nint\nmain(void)\n{\n    test_parse_addr_ipv4_with_port();\n    test_parse_addr_ipv6_with_port();\n    test_parse_addr_hostname_with_port();\n    test_parse_addr_no_port();\n    test_parse_addr_ipv6_no_port();\n    return 0;\n}\n"
  },
  {
    "path": "tests/test_json.c",
    "content": "#include <assert.h>\n#include <string.h>\n#include <stdlib.h>\n\n#include \"json.h\"\n\nstatic void\ntest_parse_simple_object(void)\n{\n    const char *json_str = \"{\\\"key\\\": \\\"value\\\", \\\"num\\\": 42}\";\n    json_value *val = json_parse(json_str, strlen(json_str));\n    assert(val != NULL);\n    assert(val->type == json_object);\n    assert(val->u.object.length == 2);\n\n    /* Check first entry */\n    assert(strcmp(val->u.object.values[0].name, \"key\") == 0);\n    assert(val->u.object.values[0].value->type == json_string);\n    assert(strcmp(val->u.object.values[0].value->u.string.ptr, \"value\") == 0);\n\n    /* Check second entry */\n    assert(strcmp(val->u.object.values[1].name, \"num\") == 0);\n    assert(val->u.object.values[1].value->type == json_integer);\n    assert(val->u.object.values[1].value->u.integer == 42);\n\n    json_value_free(val);\n}\n\nstatic void\ntest_parse_array(void)\n{\n    const char *json_str = \"[1, 2, 3]\";\n    json_value *val = json_parse(json_str, strlen(json_str));\n    assert(val != NULL);\n    assert(val->type == json_array);\n    assert(val->u.array.length == 3);\n    assert(val->u.array.values[0]->type == json_integer);\n    assert(val->u.array.values[0]->u.integer == 1);\n    assert(val->u.array.values[1]->u.integer == 2);\n    assert(val->u.array.values[2]->u.integer == 3);\n\n    json_value_free(val);\n}\n\nstatic void\ntest_parse_nested(void)\n{\n    const char *json_str = \"{\\\"outer\\\": {\\\"inner\\\": true}}\";\n    json_value *val = json_parse(json_str, strlen(json_str));\n    assert(val != NULL);\n    assert(val->type == json_object);\n    assert(val->u.object.length == 1);\n\n    json_value *outer = val->u.object.values[0].value;\n    assert(outer->type == json_object);\n    assert(outer->u.object.length == 1);\n\n    assert(outer->u.object.values[0].value->type == json_boolean);\n    assert(outer->u.object.values[0].value->u.boolean != 0);\n\n    json_value_free(val);\n}\n\nstatic void\ntest_parse_types(void)\n{\n    const char *json_str = \"{\\\"s\\\": \\\"hello\\\", \\\"i\\\": -5, \\\"d\\\": 3.14, \\\"b\\\": false, \\\"n\\\": null}\";\n    json_value *val = json_parse(json_str, strlen(json_str));\n    assert(val != NULL);\n    assert(val->type == json_object);\n    assert(val->u.object.length == 5);\n\n    assert(val->u.object.values[0].value->type == json_string);\n    assert(val->u.object.values[1].value->type == json_integer);\n    assert(val->u.object.values[1].value->u.integer == -5);\n    assert(val->u.object.values[2].value->type == json_double);\n    assert(val->u.object.values[3].value->type == json_boolean);\n    assert(val->u.object.values[3].value->u.boolean == 0);\n    assert(val->u.object.values[4].value->type == json_null);\n\n    json_value_free(val);\n}\n\nstatic void\ntest_parse_invalid(void)\n{\n    /* Missing closing brace */\n    assert(json_parse(\"{\\\"key\\\": 1\", 9) == NULL);\n\n    /* Empty string */\n    assert(json_parse(\"\", 0) == NULL);\n\n    /* Just garbage */\n    assert(json_parse(\"not json\", 8) == NULL);\n}\n\nstatic void\ntest_parse_empty_object(void)\n{\n    const char *json_str = \"{}\";\n    json_value *val = json_parse(json_str, strlen(json_str));\n    assert(val != NULL);\n    assert(val->type == json_object);\n    assert(val->u.object.length == 0);\n    json_value_free(val);\n}\n\nstatic void\ntest_parse_empty_array(void)\n{\n    const char *json_str = \"[]\";\n    json_value *val = json_parse(json_str, strlen(json_str));\n    assert(val != NULL);\n    assert(val->type == json_array);\n    assert(val->u.array.length == 0);\n    json_value_free(val);\n}\n\nint\nmain(void)\n{\n    test_parse_simple_object();\n    test_parse_array();\n    test_parse_nested();\n    test_parse_types();\n    test_parse_invalid();\n    test_parse_empty_object();\n    test_parse_empty_array();\n    return 0;\n}\n"
  },
  {
    "path": "tests/test_netutils.c",
    "content": "#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <assert.h>\n#include <string.h>\n#include <stdlib.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\n\nint verbose = 0;\n\n#include \"netutils.h\"\n\nstatic void\ntest_get_sockaddr_len(void)\n{\n    struct sockaddr_in addr4;\n    struct sockaddr_in6 addr6;\n    struct sockaddr_storage unknown;\n\n    memset(&addr4, 0, sizeof(addr4));\n    addr4.sin_family = AF_INET;\n    assert(get_sockaddr_len((struct sockaddr *)&addr4) == sizeof(struct sockaddr_in));\n\n    memset(&addr6, 0, sizeof(addr6));\n    addr6.sin6_family = AF_INET6;\n    assert(get_sockaddr_len((struct sockaddr *)&addr6) == sizeof(struct sockaddr_in6));\n\n    memset(&unknown, 0, sizeof(unknown));\n    unknown.ss_family = AF_UNSPEC;\n    assert(get_sockaddr_len((struct sockaddr *)&unknown) == 0);\n}\n\nstatic void\ntest_sockaddr_cmp(void)\n{\n    struct sockaddr_storage a, b;\n    struct sockaddr_in *a4 = (struct sockaddr_in *)&a;\n    struct sockaddr_in *b4 = (struct sockaddr_in *)&b;\n\n    /* Same address and port */\n    memset(&a, 0, sizeof(a));\n    memset(&b, 0, sizeof(b));\n    a4->sin_family = AF_INET;\n    b4->sin_family = AF_INET;\n    a4->sin_port = htons(80);\n    b4->sin_port = htons(80);\n    inet_pton(AF_INET, \"127.0.0.1\", &a4->sin_addr);\n    inet_pton(AF_INET, \"127.0.0.1\", &b4->sin_addr);\n    assert(sockaddr_cmp(&a, &b, sizeof(struct sockaddr_in)) == 0);\n\n    /* Different port */\n    b4->sin_port = htons(81);\n    assert(sockaddr_cmp(&a, &b, sizeof(struct sockaddr_in)) != 0);\n}\n\nstatic void\ntest_sockaddr_cmp_addr(void)\n{\n    struct sockaddr_storage a, b;\n    struct sockaddr_in *a4 = (struct sockaddr_in *)&a;\n    struct sockaddr_in *b4 = (struct sockaddr_in *)&b;\n\n    memset(&a, 0, sizeof(a));\n    memset(&b, 0, sizeof(b));\n    a4->sin_family = AF_INET;\n    b4->sin_family = AF_INET;\n    a4->sin_port = htons(80);\n    b4->sin_port = htons(443);\n    inet_pton(AF_INET, \"10.0.0.1\", &a4->sin_addr);\n    inet_pton(AF_INET, \"10.0.0.1\", &b4->sin_addr);\n\n    /* Same address, different port - should be equal */\n    assert(sockaddr_cmp_addr(&a, &b, sizeof(struct sockaddr_in)) == 0);\n\n    /* Different address */\n    inet_pton(AF_INET, \"10.0.0.2\", &b4->sin_addr);\n    assert(sockaddr_cmp_addr(&a, &b, sizeof(struct sockaddr_in)) != 0);\n}\n\nstatic void\ntest_validate_hostname(void)\n{\n    /* Valid hostnames */\n    assert(validate_hostname(\"example.com\", 11) == 1);\n    assert(validate_hostname(\"sub.example.com\", 15) == 1);\n    assert(validate_hostname(\"a\", 1) == 1);\n    assert(validate_hostname(\"a-b\", 3) == 1);\n    assert(validate_hostname(\"123.456\", 7) == 1);\n\n    /* Invalid hostnames */\n    assert(validate_hostname(NULL, 0) == 0);\n    assert(validate_hostname(\"\", 0) == 0);\n    assert(validate_hostname(\".example.com\", 12) == 0);     /* starts with dot */\n    assert(validate_hostname(\"-example.com\", 12) == 0);     /* label starts with hyphen */\n    assert(validate_hostname(\"example-.com\", 12) == 0);     /* label ends with hyphen */\n\n    /* Too long hostname (> 255) */\n    char long_name[260];\n    memset(long_name, 'a', 259);\n    long_name[259] = '\\0';\n    assert(validate_hostname(long_name, 259) == 0);\n}\n\nint\nmain(void)\n{\n    test_get_sockaddr_len();\n    test_sockaddr_cmp();\n    test_sockaddr_cmp_addr();\n    test_validate_hostname();\n    return 0;\n}\n"
  },
  {
    "path": "tests/test_ppbloom.c",
    "content": "#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <assert.h>\n#include <stdint.h>\n#include <string.h>\n#include <stdlib.h>\n\nint verbose = 0;\n\n#include \"ppbloom.h\"\n\nstatic void\ntest_init_free(void)\n{\n    int ret = ppbloom_init(1000, 0.01);\n    assert(ret == 0);\n    (void)ret;\n    ppbloom_free();\n}\n\nstatic void\ntest_add_check(void)\n{\n    ppbloom_init(1000, 0.01);\n\n    const char *item1 = \"hello\";\n    const char *item2 = \"world\";\n    const char *item3 = \"missing\";\n\n    /* Not in filter initially */\n    assert(ppbloom_check(item1, strlen(item1)) == 0);\n    assert(ppbloom_check(item2, strlen(item2)) == 0);\n\n    /* Add items */\n    ppbloom_add(item1, strlen(item1));\n    ppbloom_add(item2, strlen(item2));\n\n    /* Should be found */\n    assert(ppbloom_check(item1, strlen(item1)) == 1);\n    assert(ppbloom_check(item2, strlen(item2)) == 1);\n\n    /* Should not be found */\n    assert(ppbloom_check(item3, strlen(item3)) == 0);\n    (void)item3;\n\n    ppbloom_free();\n}\n\nstatic void\ntest_binary_data(void)\n{\n    ppbloom_init(1000, 0.01);\n\n    const uint8_t data1[] = { 0x00, 0x01, 0x02, 0x03 };\n    const uint8_t data2[] = { 0xFF, 0xFE, 0xFD, 0xFC };\n\n    ppbloom_add(data1, sizeof(data1));\n    assert(ppbloom_check(data1, sizeof(data1)) == 1);\n    assert(ppbloom_check(data2, sizeof(data2)) == 0);\n    (void)data2;\n\n    ppbloom_free();\n}\n\nint\nmain(void)\n{\n    test_init_free();\n    test_add_check();\n    test_binary_data();\n    return 0;\n}\n"
  },
  {
    "path": "tests/test_redir_qemu.sh",
    "content": "#!/bin/bash\n#\n# End-to-end test for ss-redir transparent proxy using QEMU.\n#\n# Architecture:\n#   Host: ss-server listens on 0.0.0.0:8389\n#   QEMU guest (Alpine Linux):\n#     - ss-redir connects to host ss-server via 10.0.2.2:8389\n#     - ss-nat sets up iptables OUTPUT chain REDIRECT to ss-redir\n#     - curl through the transparent proxy verifies the full chain\n#\n# Usage: bash tests/test_redir_qemu.sh [BIN_DIR]\n#   BIN_DIR: directory containing ss-server and ss-redir binaries\n#            (default: build/shared/bin/)\n#\n# Requirements (Linux only):\n#   - qemu-system-x86_64\n#   - Internet access (for Alpine download and curl test targets)\n#\n\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_DIR=\"$(cd \"$SCRIPT_DIR/..\" && pwd)\"\nBIN_DIR=\"${1:-$PROJECT_DIR/build/shared/bin}\"\n\n# Resolve to absolute path\nBIN_DIR=\"$(cd \"$BIN_DIR\" && pwd)\"\n\nWORK_DIR=\"\"\nSS_SERVER_PID=\"\"\nQEMU_PID=\"\"\n\nALPINE_VERSION=\"3.21\"\nALPINE_ARCH=\"x86_64\"\nALPINE_MIRROR=\"https://dl-cdn.alpinelinux.org/alpine\"\nALPINE_MINIROOTFS=\"alpine-minirootfs-${ALPINE_VERSION}.0-${ALPINE_ARCH}.tar.gz\"\nALPINE_URL=\"${ALPINE_MIRROR}/v${ALPINE_VERSION}/releases/${ALPINE_ARCH}/${ALPINE_MINIROOTFS}\"\n\nTIMEOUT=240\nSS_SERVER_PORT=8389\nSS_PASSWORD=\"test_redir_password\"\nSS_METHOD=\"aes-256-gcm\"\n\n# --- helpers ----------------------------------------------------------------\n\nlog() {\n    echo \"=== [test_redir_qemu] $* ===\"\n}\n\ndie() {\n    echo \"FATAL: $*\" >&2\n    exit 1\n}\n\ncleanup() {\n    log \"Cleaning up\"\n    if [ -n \"$SS_SERVER_PID\" ] && kill -0 \"$SS_SERVER_PID\" 2>/dev/null; then\n        kill \"$SS_SERVER_PID\" 2>/dev/null || true\n        wait \"$SS_SERVER_PID\" 2>/dev/null || true\n    fi\n    if [ -n \"$QEMU_PID\" ] && kill -0 \"$QEMU_PID\" 2>/dev/null; then\n        kill \"$QEMU_PID\" 2>/dev/null || true\n        wait \"$QEMU_PID\" 2>/dev/null || true\n    fi\n    if [ -n \"$WORK_DIR\" ] && [ -d \"$WORK_DIR\" ]; then\n        sudo rm -rf \"$WORK_DIR\"\n    fi\n}\n\ntrap cleanup EXIT\n\n# --- pre-flight checks ------------------------------------------------------\n\nif [ \"$(uname -s)\" != \"Linux\" ]; then\n    die \"This test requires Linux (iptables, QEMU)\"\nfi\n\nif ! command -v qemu-system-x86_64 >/dev/null 2>&1; then\n    die \"qemu-system-x86_64 not found. Install with: sudo apt-get install qemu-system-x86\"\nfi\n\nif [ ! -x \"$BIN_DIR/ss-server\" ]; then\n    die \"ss-server not found at $BIN_DIR/ss-server\"\nfi\n\nif [ ! -x \"$BIN_DIR/ss-redir\" ]; then\n    die \"ss-redir not found at $BIN_DIR/ss-redir\"\nfi\n\n# --- create work directory --------------------------------------------------\n\nWORK_DIR=\"$(mktemp -d /tmp/ss-redir-test.XXXXXX)\"\nlog \"Work directory: $WORK_DIR\"\n\n# --- phase 1: collect ss-redir and its shared library dependencies ----------\n\nlog \"Collecting ss-redir shared library dependencies\"\n\n# Copy ss-redir binary\nSYSROOT=\"$WORK_DIR/sysroot\"\nmkdir -p \"$SYSROOT/usr/bin\"\ncp \"$BIN_DIR/ss-redir\" \"$SYSROOT/usr/bin/ss-redir\"\n\n# Copy all shared library dependencies (including the dynamic linker)\nldd \"$BIN_DIR/ss-redir\" | while read -r line; do\n    # Parse lines like: libev.so.4 => /lib/x86_64-linux-gnu/libev.so.4 (0x...)\n    # or: /lib64/ld-linux-x86-64.so.2 (0x...)\n    lib_path=\"\"\n    if echo \"$line\" | grep -q \"=>\"; then\n        lib_path=$(echo \"$line\" | awk '{print $3}')\n    elif echo \"$line\" | grep -qE \"^\\s*/\"; then\n        lib_path=$(echo \"$line\" | awk '{print $1}')\n    fi\n    if [ -n \"$lib_path\" ] && [ -f \"$lib_path\" ]; then\n        dest=\"$SYSROOT$lib_path\"\n        mkdir -p \"$(dirname \"$dest\")\"\n        cp \"$lib_path\" \"$dest\"\n    fi\ndone\n\nlog \"Shared libraries collected into sysroot\"\n\n# --- phase 2: assemble Alpine rootfs ----------------------------------------\n\nlog \"Downloading Alpine minirootfs\"\n\nROOTFS=\"$WORK_DIR/rootfs\"\nmkdir -p \"$ROOTFS\"\n\ncurl -sSL \"$ALPINE_URL\" -o \"$WORK_DIR/$ALPINE_MINIROOTFS\"\nsudo tar xzf \"$WORK_DIR/$ALPINE_MINIROOTFS\" -C \"$ROOTFS\"\n\nlog \"Installing packages in Alpine rootfs\"\n\n# Set up DNS for chroot\nsudo cp /etc/resolv.conf \"$ROOTFS/etc/resolv.conf\"\n\n# Mount necessary filesystems for chroot\nsudo mount --bind /dev \"$ROOTFS/dev\"\nsudo mount --bind /proc \"$ROOTFS/proc\"\nsudo mount --bind /sys \"$ROOTFS/sys\"\n\n# Install packages inside chroot\nsudo chroot \"$ROOTFS\" /sbin/apk add --no-cache \\\n    iptables ipset curl iproute2 kmod bash linux-virt\n\n# Unmount after package installation\nsudo umount \"$ROOTFS/sys\" 2>/dev/null || true\nsudo umount \"$ROOTFS/proc\" 2>/dev/null || true\nsudo umount \"$ROOTFS/dev\" 2>/dev/null || true\n\n# Extract kernel\nVMLINUZ=$(find \"$ROOTFS/boot\" -name 'vmlinuz-*' -type f | head -1)\nif [ -z \"$VMLINUZ\" ]; then\n    die \"No vmlinuz found in Alpine rootfs\"\nfi\ncp \"$VMLINUZ\" \"$WORK_DIR/vmlinuz\"\nlog \"Kernel: $(basename \"$VMLINUZ\")\"\n\n# --- phase 3: inject artifacts into rootfs ----------------------------------\n\nlog \"Injecting test artifacts into rootfs\"\n\n# ss-redir binary and its glibc shared library dependencies\n# These go into the rootfs at their original absolute paths so the\n# ELF dynamic linker (PT_INTERP) can find everything.\nsudo cp -a \"$SYSROOT/.\" \"$ROOTFS/\"\n\n# ss-nat script\nsudo cp \"$PROJECT_DIR/src/ss-nat\" \"$ROOTFS/usr/bin/ss-nat\"\nsudo chmod 755 \"$ROOTFS/usr/bin/ss-nat\"\n\n# Config file\nsudo cp \"$SCRIPT_DIR/redir.json\" \"$ROOTFS/etc/ss-redir.json\"\n\n# Guest init script (becomes PID 1)\nsudo cp \"$SCRIPT_DIR/qemu/guest-init.sh\" \"$ROOTFS/init\"\nsudo chmod 755 \"$ROOTFS/init\"\n\n# --- phase 4: pack initramfs -----------------------------------------------\n\nlog \"Packing initramfs\"\n\n(cd \"$ROOTFS\" && sudo find . | sudo cpio -o -H newc 2>/dev/null | gzip -1 > \"$WORK_DIR/initramfs.gz\")\n\nlog \"Initramfs size: $(du -h \"$WORK_DIR/initramfs.gz\" | cut -f1)\"\n\n# --- phase 5: start ss-server on host --------------------------------------\n\nlog \"Starting ss-server on host\"\n\n\"$BIN_DIR/ss-server\" \\\n    -s 0.0.0.0 \\\n    -p \"$SS_SERVER_PORT\" \\\n    -k \"$SS_PASSWORD\" \\\n    -m \"$SS_METHOD\" \\\n    -v &\nSS_SERVER_PID=$!\n\nsleep 2\n\nif ! kill -0 \"$SS_SERVER_PID\" 2>/dev/null; then\n    die \"ss-server failed to start\"\nfi\n\nlog \"ss-server running (PID $SS_SERVER_PID)\"\n\n# --- phase 6: boot QEMU ----------------------------------------------------\n\nlog \"Booting QEMU\"\n\nKVM_FLAG=\"\"\nif [ -e /dev/kvm ] && [ -r /dev/kvm ] && [ -w /dev/kvm ]; then\n    KVM_FLAG=\"-enable-kvm\"\n    log \"KVM acceleration available\"\nelse\n    log \"KVM not available, using TCG (slower)\"\nfi\n\nSERIAL_LOG=\"$WORK_DIR/serial.log\"\n\nqemu-system-x86_64 \\\n    $KVM_FLAG \\\n    -m 512 \\\n    -kernel \"$WORK_DIR/vmlinuz\" \\\n    -initrd \"$WORK_DIR/initramfs.gz\" \\\n    -append \"console=ttyS0 init=/init panic=1\" \\\n    -nographic \\\n    -serial \"file:$SERIAL_LOG\" \\\n    -monitor none \\\n    -net nic,model=virtio \\\n    -net user \\\n    -no-reboot &\nQEMU_PID=$!\n\nlog \"QEMU running (PID $QEMU_PID)\"\n\n# --- phase 7: monitor serial log -------------------------------------------\n\nlog \"Waiting for test result (timeout: ${TIMEOUT}s)\"\n\nELAPSED=0\nPOLL_INTERVAL=2\nRESULT=\"\"\n\nwhile [ $ELAPSED -lt $TIMEOUT ]; do\n    if [ -f \"$SERIAL_LOG\" ]; then\n        if grep -q \"REDIR_TEST_PASS\" \"$SERIAL_LOG\" 2>/dev/null; then\n            RESULT=\"PASS\"\n            break\n        fi\n        if grep -q \"REDIR_TEST_FAIL\" \"$SERIAL_LOG\" 2>/dev/null; then\n            RESULT=\"FAIL\"\n            break\n        fi\n    fi\n\n    # Check if QEMU is still running\n    if ! kill -0 \"$QEMU_PID\" 2>/dev/null; then\n        RESULT=\"QEMU_DIED\"\n        break\n    fi\n\n    sleep $POLL_INTERVAL\n    ELAPSED=$((ELAPSED + POLL_INTERVAL))\ndone\n\n# --- phase 8: report -------------------------------------------------------\n\necho \"\"\necho \"============================================================\"\necho \"Serial console output:\"\necho \"============================================================\"\nif [ -f \"$SERIAL_LOG\" ]; then\n    cat \"$SERIAL_LOG\"\nelse\n    echo \"(no serial log file)\"\nfi\necho \"============================================================\"\necho \"\"\n\ncase \"$RESULT\" in\n    PASS)\n        log \"TEST PASSED\"\n        exit 0\n        ;;\n    FAIL)\n        FAIL_MSG=$(grep \"REDIR_TEST_FAIL\" \"$SERIAL_LOG\" 2>/dev/null || echo \"unknown\")\n        log \"TEST FAILED: $FAIL_MSG\"\n        exit 1\n        ;;\n    QEMU_DIED)\n        log \"TEST FAILED: QEMU exited unexpectedly\"\n        exit 1\n        ;;\n    *)\n        log \"TEST FAILED: timeout after ${TIMEOUT}s\"\n        # Kill QEMU if still running\n        if kill -0 \"$QEMU_PID\" 2>/dev/null; then\n            kill \"$QEMU_PID\" 2>/dev/null || true\n        fi\n        exit 1\n        ;;\nesac\n"
  },
  {
    "path": "tests/test_rule.c",
    "content": "#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <assert.h>\n#include <string.h>\n#include <stdlib.h>\n\nint verbose = 0;\n\n#include \"rule.h\"\n#include \"utils.h\"\n\nstatic void\ntest_new_rule(void)\n{\n    rule_t *rule = new_rule();\n    assert(rule != NULL);\n    assert(rule->pattern == NULL);\n    assert(rule->pattern_re == NULL);\n    free(rule);\n}\n\nstatic void\ntest_accept_rule_arg(void)\n{\n    rule_t *rule = new_rule();\n    assert(rule != NULL);\n\n    int ret = accept_rule_arg(rule, \"^example\\\\.com$\");\n    assert(ret == 1);\n    assert(rule->pattern != NULL);\n    assert(strcmp(rule->pattern, \"^example\\\\.com$\") == 0);\n\n    /* Second call should fail - pattern already set */\n    ret = accept_rule_arg(rule, \"another\");\n    assert(ret == -1);\n    (void)ret;\n\n    free(rule->pattern);\n    free(rule);\n}\n\nstatic void\ntest_init_rule(void)\n{\n    rule_t *rule = new_rule();\n    accept_rule_arg(rule, \"^test.*$\");\n\n    int ret = init_rule(rule);\n    assert(ret == 1);\n    (void)ret;\n    assert(rule->pattern_re != NULL);\n\n    if (rule->match_data)\n        pcre2_match_data_free(rule->match_data);\n    if (rule->pattern_re)\n        pcre2_code_free(rule->pattern_re);\n    free(rule->pattern);\n    free(rule);\n}\n\nstatic void\ntest_init_rule_invalid(void)\n{\n    rule_t *rule = new_rule();\n    accept_rule_arg(rule, \"[invalid\");  /* Unclosed bracket */\n\n    int ret = init_rule(rule);\n    assert(ret == 0);  /* Should fail */\n    (void)ret;\n\n    free(rule->pattern);\n    free(rule);\n}\n\nstatic void\ntest_lookup_rule(void)\n{\n    struct cork_dllist rules;\n    cork_dllist_init(&rules);\n\n    rule_t *rule1 = new_rule();\n    accept_rule_arg(rule1, \"^google\\\\.com$\");\n    init_rule(rule1);\n    add_rule(&rules, rule1);\n\n    rule_t *rule2 = new_rule();\n    accept_rule_arg(rule2, \".*\\\\.example\\\\.com$\");\n    init_rule(rule2);\n    add_rule(&rules, rule2);\n\n    /* Should match rule1 */\n    rule_t *found = lookup_rule(&rules, \"google.com\", 10);\n    assert(found == rule1);\n\n    /* Should match rule2 */\n    found = lookup_rule(&rules, \"sub.example.com\", 15);\n    assert(found == rule2);\n\n    /* Should not match */\n    found = lookup_rule(&rules, \"other.net\", 9);\n    assert(found == NULL);\n    (void)found;\n\n    /* Clean up */\n    if (rule1->match_data) pcre2_match_data_free(rule1->match_data);\n    if (rule1->pattern_re) pcre2_code_free(rule1->pattern_re);\n    free(rule1->pattern);\n    free(rule1);\n    if (rule2->match_data) pcre2_match_data_free(rule2->match_data);\n    if (rule2->pattern_re) pcre2_code_free(rule2->pattern_re);\n    free(rule2->pattern);\n    free(rule2);\n}\n\nint\nmain(void)\n{\n    test_new_rule();\n    test_accept_rule_arg();\n    test_init_rule();\n    test_init_rule_invalid();\n    test_lookup_rule();\n    return 0;\n}\n"
  },
  {
    "path": "tests/test_ss_setup.sh",
    "content": "#!/usr/bin/env bash\n###############################################################################\n# test_ss_setup.sh -- Unit tests for ss-setup.sh utility functions\n#\n# Sources ss-setup.sh (which skips main() due to BASH_SOURCE guard) and\n# exercises every pure/utility function that doesn't require a TUI backend.\n###############################################################################\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_ROOT=\"$(cd \"$SCRIPT_DIR/..\" && pwd)\"\nSS_SETUP=\"${PROJECT_ROOT}/scripts/ss-setup.sh\"\n\nPASS=0\nFAIL=0\nTMPDIR_TEST=\"\"\n\ncleanup_test() {\n    if [[ -n \"$TMPDIR_TEST\" && -d \"$TMPDIR_TEST\" ]]; then\n        rm -rf \"$TMPDIR_TEST\"\n    fi\n}\ntrap cleanup_test EXIT\n\nTMPDIR_TEST=$(mktemp -d)\n\n# Source the script under test (main() won't run due to BASH_SOURCE guard)\n# shellcheck source=../scripts/ss-setup.sh\nsource \"$SS_SETUP\"\n\n###############################################################################\n# Test helpers\n###############################################################################\n\nassert_eq() {\n    local test_name=\"$1\" expected=\"$2\" actual=\"$3\"\n    if [[ \"$expected\" == \"$actual\" ]]; then\n        PASS=$((PASS + 1))\n    else\n        FAIL=$((FAIL + 1))\n        echo \"FAIL: ${test_name}\" >&2\n        echo \"  expected: '${expected}'\" >&2\n        echo \"  actual:   '${actual}'\" >&2\n    fi\n}\n\nassert_match() {\n    local test_name=\"$1\" pattern=\"$2\" actual=\"$3\"\n    if [[ \"$actual\" =~ $pattern ]]; then\n        PASS=$((PASS + 1))\n    else\n        FAIL=$((FAIL + 1))\n        echo \"FAIL: ${test_name}\" >&2\n        echo \"  expected match: '${pattern}'\" >&2\n        echo \"  actual:         '${actual}'\" >&2\n    fi\n}\n\nassert_ok() {\n    local test_name=\"$1\"\n    shift\n    if \"$@\" 2>/dev/null; then\n        PASS=$((PASS + 1))\n    else\n        FAIL=$((FAIL + 1))\n        echo \"FAIL: ${test_name} (command returned non-zero)\" >&2\n    fi\n}\n\nassert_fail() {\n    local test_name=\"$1\"\n    shift\n    if \"$@\" 2>/dev/null; then\n        FAIL=$((FAIL + 1))\n        echo \"FAIL: ${test_name} (expected failure but got success)\" >&2\n    else\n        PASS=$((PASS + 1))\n    fi\n}\n\nassert_contains() {\n    local test_name=\"$1\" needle=\"$2\" haystack=\"$3\"\n    if [[ \"$haystack\" == *\"$needle\"* ]]; then\n        PASS=$((PASS + 1))\n    else\n        FAIL=$((FAIL + 1))\n        echo \"FAIL: ${test_name}\" >&2\n        echo \"  expected to contain: '${needle}'\" >&2\n        echo \"  actual:              '${haystack}'\" >&2\n    fi\n}\n\nassert_not_contains() {\n    local test_name=\"$1\" needle=\"$2\" haystack=\"$3\"\n    if [[ \"$haystack\" != *\"$needle\"* ]]; then\n        PASS=$((PASS + 1))\n    else\n        FAIL=$((FAIL + 1))\n        echo \"FAIL: ${test_name}\" >&2\n        echo \"  expected NOT to contain: '${needle}'\" >&2\n        echo \"  actual:                  '${haystack}'\" >&2\n    fi\n}\n\n###############################################################################\n# Tests: AEAD_CIPHERS constant\n###############################################################################\n\ntest_aead_ciphers_count() {\n    assert_eq \"AEAD_CIPHERS has 5 entries\" \"5\" \"${#AEAD_CIPHERS[@]}\"\n}\n\ntest_aead_ciphers_contains_chacha20() {\n    local found=0\n    for c in \"${AEAD_CIPHERS[@]}\"; do\n        [[ \"$c\" == \"chacha20-ietf-poly1305\" ]] && found=1\n    done\n    assert_eq \"AEAD_CIPHERS contains chacha20-ietf-poly1305\" \"1\" \"$found\"\n}\n\ntest_aead_ciphers_contains_aes256gcm() {\n    local found=0\n    for c in \"${AEAD_CIPHERS[@]}\"; do\n        [[ \"$c\" == \"aes-256-gcm\" ]] && found=1\n    done\n    assert_eq \"AEAD_CIPHERS contains aes-256-gcm\" \"1\" \"$found\"\n}\n\ntest_aead_ciphers_contains_aes128gcm() {\n    local found=0\n    for c in \"${AEAD_CIPHERS[@]}\"; do\n        [[ \"$c\" == \"aes-128-gcm\" ]] && found=1\n    done\n    assert_eq \"AEAD_CIPHERS contains aes-128-gcm\" \"1\" \"$found\"\n}\n\n###############################################################################\n# Tests: validate_port\n###############################################################################\n\ntest_validate_port_valid() {\n    assert_ok \"validate_port 1\" validate_port \"1\"\n    assert_ok \"validate_port 80\" validate_port \"80\"\n    assert_ok \"validate_port 443\" validate_port \"443\"\n    assert_ok \"validate_port 8388\" validate_port \"8388\"\n    assert_ok \"validate_port 65535\" validate_port \"65535\"\n}\n\ntest_validate_port_invalid() {\n    assert_fail \"validate_port 0\" validate_port \"0\"\n    assert_fail \"validate_port 65536\" validate_port \"65536\"\n    assert_fail \"validate_port -1\" validate_port \"-1\"\n    assert_fail \"validate_port abc\" validate_port \"abc\"\n    assert_fail \"validate_port empty\" validate_port \"\"\n    assert_fail \"validate_port 99999\" validate_port \"99999\"\n    assert_fail \"validate_port 8.8\" validate_port \"8.8\"\n}\n\n###############################################################################\n# Tests: validate_instance_name\n###############################################################################\n\ntest_validate_instance_name_valid() {\n    assert_ok \"instance: config\" validate_instance_name \"config\"\n    assert_ok \"instance: my-server\" validate_instance_name \"my-server\"\n    assert_ok \"instance: server_1\" validate_instance_name \"server_1\"\n    assert_ok \"instance: Test123\" validate_instance_name \"Test123\"\n    assert_ok \"instance: a\" validate_instance_name \"a\"\n    assert_ok \"instance: A-B_c-1\" validate_instance_name \"A-B_c-1\"\n}\n\ntest_validate_instance_name_invalid() {\n    assert_fail \"instance: empty\" validate_instance_name \"\"\n    assert_fail \"instance: has space\" validate_instance_name \"has space\"\n    assert_fail \"instance: has.dot\" validate_instance_name \"has.dot\"\n    assert_fail \"instance: has/slash\" validate_instance_name \"has/slash\"\n    assert_fail \"instance: has@at\" validate_instance_name \"has@at\"\n    assert_fail \"instance: has:colon\" validate_instance_name \"has:colon\"\n}\n\n###############################################################################\n# Tests: generate_password\n###############################################################################\n\ntest_generate_password_nonempty() {\n    local pw\n    pw=$(generate_password 32)\n    assert_match \"password is non-empty\" \".+\" \"$pw\"\n}\n\ntest_generate_password_length() {\n    # base64 of 16 bytes = 24 chars (before newline strip)\n    local pw\n    pw=$(generate_password 16)\n    # Should be at least 20 chars (base64 encoding of 16 bytes)\n    local len=${#pw}\n    if (( len >= 20 )); then\n        PASS=$((PASS + 1))\n    else\n        FAIL=$((FAIL + 1))\n        echo \"FAIL: password length too short: ${len} chars\" >&2\n    fi\n}\n\ntest_generate_password_no_newlines() {\n    local pw\n    pw=$(generate_password 32)\n    assert_not_contains \"password has no newline\" $'\\n' \"$pw\"\n}\n\ntest_generate_password_different() {\n    local pw1 pw2\n    pw1=$(generate_password 32)\n    pw2=$(generate_password 32)\n    if [[ \"$pw1\" != \"$pw2\" ]]; then\n        PASS=$((PASS + 1))\n    else\n        FAIL=$((FAIL + 1))\n        echo \"FAIL: two passwords are identical: '${pw1}'\" >&2\n    fi\n}\n\n###############################################################################\n# Tests: generate_random_port\n###############################################################################\n\ntest_generate_random_port_range() {\n    local port\n    for _ in $(seq 1 10); do\n        port=$(generate_random_port)\n        if (( port >= 10000 && port <= 65000 )); then\n            PASS=$((PASS + 1))\n        else\n            FAIL=$((FAIL + 1))\n            echo \"FAIL: random port ${port} out of range 10000-65000\" >&2\n        fi\n    done\n}\n\ntest_generate_random_port_numeric() {\n    local port\n    port=$(generate_random_port)\n    assert_match \"random port is numeric\" \"^[0-9]+$\" \"$port\"\n}\n\n###############################################################################\n# Tests: json_escape\n###############################################################################\n\ntest_json_escape_plain() {\n    local result\n    result=$(json_escape \"hello world\")\n    assert_eq \"json_escape plain\" \"hello world\" \"$result\"\n}\n\ntest_json_escape_quotes() {\n    local result\n    result=$(json_escape 'say \"hi\"')\n    assert_eq \"json_escape quotes\" 'say \\\"hi\\\"' \"$result\"\n}\n\ntest_json_escape_backslash() {\n    local result\n    result=$(json_escape 'path\\to\\file')\n    assert_eq \"json_escape backslash\" 'path\\\\to\\\\file' \"$result\"\n}\n\ntest_json_escape_tab() {\n    local result\n    result=$(json_escape \"col1\tcol2\")\n    assert_eq \"json_escape tab\" 'col1\\tcol2' \"$result\"\n}\n\ntest_json_escape_newline() {\n    local result\n    result=$(json_escape \"line1\nline2\")\n    assert_eq \"json_escape newline\" 'line1\\nline2' \"$result\"\n}\n\ntest_json_escape_empty() {\n    local result\n    result=$(json_escape \"\")\n    assert_eq \"json_escape empty\" \"\" \"$result\"\n}\n\n###############################################################################\n# Tests: urlencode\n###############################################################################\n\ntest_urlencode_plain() {\n    local result\n    result=$(urlencode \"hello\")\n    assert_eq \"urlencode plain\" \"hello\" \"$result\"\n}\n\ntest_urlencode_space() {\n    local result\n    result=$(urlencode \"hello world\")\n    assert_eq \"urlencode space\" \"hello%20world\" \"$result\"\n}\n\ntest_urlencode_special() {\n    local result\n    result=$(urlencode \"a=b&c=d\")\n    assert_eq \"urlencode special\" \"a%3Db%26c%3Dd\" \"$result\"\n}\n\ntest_urlencode_semicolon() {\n    local result\n    result=$(urlencode \"obfs-local;obfs=http\")\n    assert_eq \"urlencode semicolon\" \"obfs-local%3Bobfs%3Dhttp\" \"$result\"\n}\n\ntest_urlencode_safe_chars() {\n    local result\n    result=$(urlencode \"a-b_c.d~e\")\n    assert_eq \"urlencode safe chars\" \"a-b_c.d~e\" \"$result\"\n}\n\ntest_urlencode_empty() {\n    local result\n    result=$(urlencode \"\")\n    assert_eq \"urlencode empty\" \"\" \"$result\"\n}\n\n###############################################################################\n# Tests: generate_ss_uri\n###############################################################################\n\ntest_ss_uri_basic() {\n    local uri\n    uri=$(generate_ss_uri \"aes-256-gcm\" \"testpass\" \"1.2.3.4\" \"8388\" \"\" \"\")\n    # Should start with ss://\n    assert_match \"ss uri starts with ss://\" \"^ss://\" \"$uri\"\n    # Should contain @host:port\n    assert_contains \"ss uri has host:port\" \"@1.2.3.4:8388\" \"$uri\"\n    # Should NOT have plugin query\n    assert_not_contains \"ss uri no plugin query\" \"/?plugin=\" \"$uri\"\n}\n\ntest_ss_uri_with_plugin() {\n    local uri\n    uri=$(generate_ss_uri \"chacha20-ietf-poly1305\" \"mypass\" \"example.com\" \"443\" \"v2ray-plugin\" \"server;tls;host=example.com\")\n    assert_match \"ss uri+plugin starts with ss://\" \"^ss://\" \"$uri\"\n    assert_contains \"ss uri+plugin has host:port\" \"@example.com:443\" \"$uri\"\n    assert_contains \"ss uri+plugin has plugin param\" \"/?plugin=\" \"$uri\"\n    # v2ray-plugin should be URL-encoded with the opts\n    assert_contains \"ss uri+plugin has v2ray\" \"v2ray-plugin\" \"$uri\"\n}\n\ntest_ss_uri_with_plugin_no_opts() {\n    local uri\n    uri=$(generate_ss_uri \"aes-128-gcm\" \"pw\" \"10.0.0.1\" \"9000\" \"obfs-local\" \"\")\n    assert_contains \"ss uri plugin-no-opts has plugin\" \"/?plugin=\" \"$uri\"\n    assert_contains \"ss uri plugin-no-opts has obfs-local\" \"obfs-local\" \"$uri\"\n}\n\ntest_ss_uri_base64_encoding() {\n    # Verify the userinfo part is valid base64url\n    local uri\n    uri=$(generate_ss_uri \"aes-256-gcm\" \"test\" \"1.2.3.4\" \"8388\" \"\" \"\")\n    # Extract the base64 part between ss:// and @\n    local b64_part\n    b64_part=$(echo \"$uri\" | sed 's|^ss://\\([^@]*\\)@.*|\\1|')\n    # base64url should only contain [A-Za-z0-9_-]\n    assert_match \"ss uri base64url valid chars\" \"^[A-Za-z0-9_-]+$\" \"$b64_part\"\n}\n\n###############################################################################\n# Tests: write_json_config (server)\n###############################################################################\n\ntest_write_json_config_basic() {\n    local outfile=\"${TMPDIR_TEST}/server_basic.json\"\n    CFG_SERVER=\"0.0.0.0\"\n    CFG_SERVER_PORT=\"8388\"\n    CFG_PASSWORD=\"testpassword123\"\n    CFG_TIMEOUT=\"300\"\n    CFG_METHOD=\"aes-256-gcm\"\n    CFG_MODE=\"tcp_and_udp\"\n    CFG_FAST_OPEN=\"false\"\n    CFG_PLUGIN=\"\"\n    CFG_PLUGIN_OPTS=\"\"\n\n    write_json_config \"$outfile\"\n\n    local content\n    content=$(cat \"$outfile\")\n\n    assert_contains \"server json has server\" '\"server\": \"0.0.0.0\"' \"$content\"\n    assert_contains \"server json has port\" '\"server_port\": 8388' \"$content\"\n    assert_contains \"server json has password\" '\"password\": \"testpassword123\"' \"$content\"\n    assert_contains \"server json has timeout\" '\"timeout\": 300' \"$content\"\n    assert_contains \"server json has method\" '\"method\": \"aes-256-gcm\"' \"$content\"\n    assert_contains \"server json has mode\" '\"mode\": \"tcp_and_udp\"' \"$content\"\n    assert_contains \"server json has fast_open false\" '\"fast_open\": false' \"$content\"\n    assert_not_contains \"server json no plugin\" '\"plugin\"' \"$content\"\n    # No trailing comma before closing brace\n    assert_not_contains \"server json no trailing comma\" ',\n}' \"$content\"\n}\n\ntest_write_json_config_fast_open_true() {\n    local outfile=\"${TMPDIR_TEST}/server_tfo.json\"\n    CFG_SERVER=\"0.0.0.0\"\n    CFG_SERVER_PORT=\"443\"\n    CFG_PASSWORD=\"pw\"\n    CFG_TIMEOUT=\"60\"\n    CFG_METHOD=\"chacha20-ietf-poly1305\"\n    CFG_MODE=\"tcp_only\"\n    CFG_FAST_OPEN=\"true\"\n    CFG_PLUGIN=\"\"\n    CFG_PLUGIN_OPTS=\"\"\n\n    write_json_config \"$outfile\"\n\n    local content\n    content=$(cat \"$outfile\")\n\n    assert_contains \"server json fast_open true\" '\"fast_open\": true' \"$content\"\n    assert_not_contains \"server json fast_open not quoted\" '\"fast_open\": \"true\"' \"$content\"\n}\n\ntest_write_json_config_with_plugin() {\n    local outfile=\"${TMPDIR_TEST}/server_plugin.json\"\n    CFG_SERVER=\"0.0.0.0\"\n    CFG_SERVER_PORT=\"443\"\n    CFG_PASSWORD=\"pw\"\n    CFG_TIMEOUT=\"300\"\n    CFG_METHOD=\"aes-256-gcm\"\n    CFG_MODE=\"tcp_and_udp\"\n    CFG_FAST_OPEN=\"false\"\n    CFG_PLUGIN=\"v2ray-plugin\"\n    CFG_PLUGIN_OPTS=\"server;tls;host=example.com\"\n\n    write_json_config \"$outfile\"\n\n    local content\n    content=$(cat \"$outfile\")\n\n    assert_contains \"server json has plugin\" '\"plugin\": \"v2ray-plugin\"' \"$content\"\n    assert_contains \"server json has plugin_opts\" '\"plugin_opts\": \"server;tls;host=example.com\"' \"$content\"\n}\n\ntest_write_json_config_with_plugin_no_opts() {\n    local outfile=\"${TMPDIR_TEST}/server_plugin_noopts.json\"\n    CFG_SERVER=\"0.0.0.0\"\n    CFG_SERVER_PORT=\"8388\"\n    CFG_PASSWORD=\"pw\"\n    CFG_TIMEOUT=\"300\"\n    CFG_METHOD=\"aes-256-gcm\"\n    CFG_MODE=\"tcp_and_udp\"\n    CFG_FAST_OPEN=\"false\"\n    CFG_PLUGIN=\"obfs-local\"\n    CFG_PLUGIN_OPTS=\"\"\n\n    write_json_config \"$outfile\"\n\n    local content\n    content=$(cat \"$outfile\")\n\n    assert_contains \"server json plugin no opts has plugin\" '\"plugin\": \"obfs-local\"' \"$content\"\n    assert_not_contains \"server json plugin no opts has no plugin_opts\" '\"plugin_opts\"' \"$content\"\n}\n\ntest_write_json_config_password_special_chars() {\n    local outfile=\"${TMPDIR_TEST}/server_special.json\"\n    CFG_SERVER=\"0.0.0.0\"\n    CFG_SERVER_PORT=\"8388\"\n    CFG_PASSWORD='pass\"word\\with/special'\n    CFG_TIMEOUT=\"300\"\n    CFG_METHOD=\"aes-256-gcm\"\n    CFG_MODE=\"tcp_and_udp\"\n    CFG_FAST_OPEN=\"false\"\n    CFG_PLUGIN=\"\"\n    CFG_PLUGIN_OPTS=\"\"\n\n    write_json_config \"$outfile\"\n\n    local content\n    content=$(cat \"$outfile\")\n\n    # Quotes and backslashes should be escaped\n    assert_contains \"special password escaped quote\" '\\\"' \"$content\"\n    assert_contains \"special password escaped backslash\" '\\\\' \"$content\"\n}\n\n###############################################################################\n# Tests: write_client_json_config\n###############################################################################\n\ntest_write_client_json_config_basic() {\n    local outfile=\"${TMPDIR_TEST}/client_basic.json\"\n    CFG_CLIENT_SERVER=\"1.2.3.4\"\n    CFG_CLIENT_SERVER_PORT=\"8388\"\n    CFG_CLIENT_LOCAL_PORT=\"1080\"\n    CFG_CLIENT_PASSWORD=\"clientpw\"\n    CFG_CLIENT_METHOD=\"aes-256-gcm\"\n    CFG_CLIENT_PLUGIN=\"\"\n    CFG_CLIENT_PLUGIN_OPTS=\"\"\n\n    write_client_json_config \"$outfile\"\n\n    local content\n    content=$(cat \"$outfile\")\n\n    assert_contains \"client json has server\" '\"server\": \"1.2.3.4\"' \"$content\"\n    assert_contains \"client json has server_port\" '\"server_port\": 8388' \"$content\"\n    assert_contains \"client json has local_address\" '\"local_address\": \"127.0.0.1\"' \"$content\"\n    assert_contains \"client json has local_port\" '\"local_port\": 1080' \"$content\"\n    assert_contains \"client json has password\" '\"password\": \"clientpw\"' \"$content\"\n    assert_contains \"client json has method\" '\"method\": \"aes-256-gcm\"' \"$content\"\n    assert_contains \"client json has timeout\" '\"timeout\": 300' \"$content\"\n    assert_contains \"client json has mode\" '\"mode\": \"tcp_and_udp\"' \"$content\"\n    assert_not_contains \"client json no plugin\" '\"plugin\"' \"$content\"\n}\n\ntest_write_client_json_config_with_plugin() {\n    local outfile=\"${TMPDIR_TEST}/client_plugin.json\"\n    CFG_CLIENT_SERVER=\"example.com\"\n    CFG_CLIENT_SERVER_PORT=\"443\"\n    CFG_CLIENT_LOCAL_PORT=\"1080\"\n    CFG_CLIENT_PASSWORD=\"pw\"\n    CFG_CLIENT_METHOD=\"chacha20-ietf-poly1305\"\n    CFG_CLIENT_PLUGIN=\"v2ray-plugin\"\n    CFG_CLIENT_PLUGIN_OPTS=\"tls;host=example.com\"\n\n    write_client_json_config \"$outfile\"\n\n    local content\n    content=$(cat \"$outfile\")\n\n    assert_contains \"client json plugin\" '\"plugin\": \"v2ray-plugin\"' \"$content\"\n    assert_contains \"client json plugin_opts\" '\"plugin_opts\": \"tls;host=example.com\"' \"$content\"\n}\n\n###############################################################################\n# Tests: parse_existing_config (round-trip)\n###############################################################################\n\ntest_parse_existing_config_roundtrip() {\n    local outfile=\"${TMPDIR_TEST}/roundtrip.json\"\n\n    # Set known values\n    CFG_SERVER=\"10.20.30.40\"\n    CFG_SERVER_PORT=\"9999\"\n    CFG_PASSWORD=\"roundtrip_pw\"\n    CFG_TIMEOUT=\"600\"\n    CFG_METHOD=\"aes-128-gcm\"\n    CFG_MODE=\"udp_only\"\n    CFG_FAST_OPEN=\"true\"\n    CFG_PLUGIN=\"obfs-local\"\n    CFG_PLUGIN_OPTS=\"obfs=http;obfs-host=example.com\"\n\n    write_json_config \"$outfile\"\n\n    # Reset globals\n    CFG_SERVER=\"\"\n    CFG_SERVER_PORT=\"\"\n    CFG_PASSWORD=\"\"\n    CFG_TIMEOUT=\"\"\n    CFG_METHOD=\"\"\n    CFG_MODE=\"\"\n    CFG_FAST_OPEN=\"\"\n    CFG_PLUGIN=\"\"\n    CFG_PLUGIN_OPTS=\"\"\n\n    # Parse back\n    parse_existing_config \"$outfile\"\n\n    assert_eq \"roundtrip server\" \"10.20.30.40\" \"$CFG_SERVER\"\n    assert_eq \"roundtrip port\" \"9999\" \"$CFG_SERVER_PORT\"\n    assert_eq \"roundtrip password\" \"roundtrip_pw\" \"$CFG_PASSWORD\"\n    assert_eq \"roundtrip timeout\" \"600\" \"$CFG_TIMEOUT\"\n    assert_eq \"roundtrip method\" \"aes-128-gcm\" \"$CFG_METHOD\"\n    assert_eq \"roundtrip mode\" \"udp_only\" \"$CFG_MODE\"\n    assert_eq \"roundtrip fast_open\" \"true\" \"$CFG_FAST_OPEN\"\n    assert_eq \"roundtrip plugin\" \"obfs-local\" \"$CFG_PLUGIN\"\n    assert_eq \"roundtrip plugin_opts\" \"obfs=http;obfs-host=example.com\" \"$CFG_PLUGIN_OPTS\"\n}\n\ntest_parse_existing_config_no_plugin() {\n    local outfile=\"${TMPDIR_TEST}/roundtrip_noplugin.json\"\n\n    CFG_SERVER=\"0.0.0.0\"\n    CFG_SERVER_PORT=\"8388\"\n    CFG_PASSWORD=\"simplepw\"\n    CFG_TIMEOUT=\"300\"\n    CFG_METHOD=\"aes-256-gcm\"\n    CFG_MODE=\"tcp_and_udp\"\n    CFG_FAST_OPEN=\"false\"\n    CFG_PLUGIN=\"\"\n    CFG_PLUGIN_OPTS=\"\"\n\n    write_json_config \"$outfile\"\n\n    # Reset and parse\n    CFG_SERVER=\"\"\n    CFG_SERVER_PORT=\"\"\n    CFG_PASSWORD=\"\"\n    CFG_METHOD=\"\"\n    CFG_MODE=\"\"\n    CFG_PLUGIN=\"should_be_cleared_if_found\"\n\n    parse_existing_config \"$outfile\"\n\n    assert_eq \"roundtrip-noplugin server\" \"0.0.0.0\" \"$CFG_SERVER\"\n    assert_eq \"roundtrip-noplugin port\" \"8388\" \"$CFG_SERVER_PORT\"\n    assert_eq \"roundtrip-noplugin password\" \"simplepw\" \"$CFG_PASSWORD\"\n    assert_eq \"roundtrip-noplugin method\" \"aes-256-gcm\" \"$CFG_METHOD\"\n    assert_eq \"roundtrip-noplugin mode\" \"tcp_and_udp\" \"$CFG_MODE\"\n}\n\n###############################################################################\n# Tests: detect_os\n###############################################################################\n\ntest_detect_os() {\n    local os\n    os=$(detect_os)\n    # Should be one of the known values\n    assert_match \"detect_os returns known value\" \"^(linux|darwin|freebsd|openbsd|netbsd)$\" \"$os\"\n}\n\n###############################################################################\n# Tests: detect_arch\n###############################################################################\n\ntest_detect_arch() {\n    local arch\n    arch=$(detect_arch)\n    # Should be one of the known mapped values or raw uname -m\n    assert_match \"detect_arch returns a value\" \".+\" \"$arch\"\n}\n\n###############################################################################\n# Tests: KNOWN_PLUGINS constant\n###############################################################################\n\ntest_known_plugins_count() {\n    assert_eq \"KNOWN_PLUGINS has 4 entries\" \"4\" \"${#KNOWN_PLUGINS[@]}\"\n}\n\ntest_known_plugins_entries() {\n    local found_simpleobfs=0 found_v2ray=0 found_xray=0 found_kcptun=0\n    for p in \"${KNOWN_PLUGINS[@]}\"; do\n        case \"$p\" in\n            simple-obfs)    found_simpleobfs=1 ;;\n            v2ray-plugin)   found_v2ray=1 ;;\n            xray-plugin)    found_xray=1 ;;\n            kcptun)         found_kcptun=1 ;;\n        esac\n    done\n    assert_eq \"KNOWN_PLUGINS has simple-obfs\" \"1\" \"$found_simpleobfs\"\n    assert_eq \"KNOWN_PLUGINS has v2ray-plugin\" \"1\" \"$found_v2ray\"\n    assert_eq \"KNOWN_PLUGINS has xray-plugin\" \"1\" \"$found_xray\"\n    assert_eq \"KNOWN_PLUGINS has kcptun\" \"1\" \"$found_kcptun\"\n}\n\n###############################################################################\n# Tests: plugin_repo function\n###############################################################################\n\ntest_plugin_repos() {\n    assert_eq \"plugin_repo simple-obfs\" \"shadowsocks/simple-obfs\" \"$(plugin_repo simple-obfs)\"\n    assert_eq \"plugin_repo v2ray-plugin\" \"shadowsocks/v2ray-plugin\" \"$(plugin_repo v2ray-plugin)\"\n    assert_eq \"plugin_repo xray-plugin\" \"teddysun/xray-plugin\" \"$(plugin_repo xray-plugin)\"\n    assert_eq \"plugin_repo kcptun\" \"xtaci/kcptun\" \"$(plugin_repo kcptun)\"\n    assert_eq \"plugin_repo unknown\" \"\" \"$(plugin_repo unknown)\"\n}\n\n###############################################################################\n# Tests: SS_SETUP_VERSION\n###############################################################################\n\ntest_version_set() {\n    assert_match \"SS_SETUP_VERSION is semver\" \"^[0-9]+\\.[0-9]+\\.[0-9]+$\" \"$SS_SETUP_VERSION\"\n}\n\n###############################################################################\n# Tests: Config directory constant\n###############################################################################\n\ntest_config_dir() {\n    assert_eq \"CONFIG_DIR\" \"/etc/shadowsocks-libev\" \"$CONFIG_DIR\"\n}\n\n###############################################################################\n# Tests: JSON output is valid (no trailing commas, booleans unquoted)\n###############################################################################\n\ntest_json_no_trailing_comma() {\n    local outfile=\"${TMPDIR_TEST}/no_trailing.json\"\n    CFG_SERVER=\"0.0.0.0\"\n    CFG_SERVER_PORT=\"8388\"\n    CFG_PASSWORD=\"pw\"\n    CFG_TIMEOUT=\"300\"\n    CFG_METHOD=\"aes-256-gcm\"\n    CFG_MODE=\"tcp_and_udp\"\n    CFG_FAST_OPEN=\"false\"\n    CFG_PLUGIN=\"\"\n    CFG_PLUGIN_OPTS=\"\"\n\n    write_json_config \"$outfile\"\n\n    # Check that the file doesn't have \",\\n}\" pattern (trailing comma)\n    if grep -qP ',\\s*\\}' \"$outfile\" 2>/dev/null || grep -q ',$' \"$outfile\" 2>/dev/null; then\n        # Try a more portable check\n        local last_data_line\n        last_data_line=$(grep -v '^[[:space:]]*[{}]' \"$outfile\" | tail -1)\n        if [[ \"$last_data_line\" == *\",\" ]]; then\n            FAIL=$((FAIL + 1))\n            echo \"FAIL: JSON has trailing comma on last data line: ${last_data_line}\" >&2\n        else\n            PASS=$((PASS + 1))\n        fi\n    else\n        PASS=$((PASS + 1))\n    fi\n}\n\ntest_json_booleans_unquoted() {\n    local outfile=\"${TMPDIR_TEST}/bool_check.json\"\n    CFG_SERVER=\"0.0.0.0\"\n    CFG_SERVER_PORT=\"8388\"\n    CFG_PASSWORD=\"pw\"\n    CFG_TIMEOUT=\"300\"\n    CFG_METHOD=\"aes-256-gcm\"\n    CFG_MODE=\"tcp_and_udp\"\n    CFG_FAST_OPEN=\"true\"\n    CFG_PLUGIN=\"\"\n    CFG_PLUGIN_OPTS=\"\"\n\n    write_json_config \"$outfile\"\n\n    local content\n    content=$(cat \"$outfile\")\n\n    assert_not_contains \"boolean not quoted string\" '\"fast_open\": \"true\"' \"$content\"\n    assert_contains \"boolean is unquoted true\" '\"fast_open\": true' \"$content\"\n}\n\ntest_json_integers_unquoted() {\n    local outfile=\"${TMPDIR_TEST}/int_check.json\"\n    CFG_SERVER=\"0.0.0.0\"\n    CFG_SERVER_PORT=\"8388\"\n    CFG_PASSWORD=\"pw\"\n    CFG_TIMEOUT=\"300\"\n    CFG_METHOD=\"aes-256-gcm\"\n    CFG_MODE=\"tcp_and_udp\"\n    CFG_FAST_OPEN=\"false\"\n    CFG_PLUGIN=\"\"\n    CFG_PLUGIN_OPTS=\"\"\n\n    write_json_config \"$outfile\"\n\n    local content\n    content=$(cat \"$outfile\")\n\n    assert_contains \"server_port is unquoted int\" '\"server_port\": 8388' \"$content\"\n    assert_not_contains \"server_port not quoted string\" '\"server_port\": \"8388\"' \"$content\"\n    assert_contains \"timeout is unquoted int\" '\"timeout\": 300' \"$content\"\n    assert_not_contains \"timeout not quoted string\" '\"timeout\": \"300\"' \"$content\"\n}\n\n###############################################################################\n# Tests: Client JSON integers unquoted\n###############################################################################\n\ntest_client_json_integers_unquoted() {\n    local outfile=\"${TMPDIR_TEST}/client_int_check.json\"\n    CFG_CLIENT_SERVER=\"1.2.3.4\"\n    CFG_CLIENT_SERVER_PORT=\"443\"\n    CFG_CLIENT_LOCAL_PORT=\"1080\"\n    CFG_CLIENT_PASSWORD=\"pw\"\n    CFG_CLIENT_METHOD=\"aes-256-gcm\"\n    CFG_CLIENT_PLUGIN=\"\"\n    CFG_CLIENT_PLUGIN_OPTS=\"\"\n\n    write_client_json_config \"$outfile\"\n\n    local content\n    content=$(cat \"$outfile\")\n\n    assert_contains \"client server_port unquoted\" '\"server_port\": 443' \"$content\"\n    assert_contains \"client local_port unquoted\" '\"local_port\": 1080' \"$content\"\n    assert_contains \"client timeout unquoted\" '\"timeout\": 300' \"$content\"\n}\n\n###############################################################################\n# Run all tests\n###############################################################################\n\necho \"Running ss-setup unit tests...\"\necho\n\n# Constants\ntest_aead_ciphers_count\ntest_aead_ciphers_contains_chacha20\ntest_aead_ciphers_contains_aes256gcm\ntest_aead_ciphers_contains_aes128gcm\ntest_known_plugins_count\ntest_known_plugins_entries\ntest_plugin_repos\ntest_version_set\ntest_config_dir\n\n# Validation\ntest_validate_port_valid\ntest_validate_port_invalid\n\ntest_validate_instance_name_valid\ntest_validate_instance_name_invalid\n\n# Password generation\ntest_generate_password_nonempty\ntest_generate_password_length\ntest_generate_password_no_newlines\ntest_generate_password_different\n\n# Random port\ntest_generate_random_port_range\ntest_generate_random_port_numeric\n\n# JSON escaping\ntest_json_escape_plain\ntest_json_escape_quotes\ntest_json_escape_backslash\ntest_json_escape_tab\ntest_json_escape_newline\ntest_json_escape_empty\n\n# URL encoding\ntest_urlencode_plain\ntest_urlencode_space\ntest_urlencode_special\ntest_urlencode_semicolon\ntest_urlencode_safe_chars\ntest_urlencode_empty\n\n# ss:// URI\ntest_ss_uri_basic\ntest_ss_uri_with_plugin\ntest_ss_uri_with_plugin_no_opts\ntest_ss_uri_base64_encoding\n\n# Server JSON config\ntest_write_json_config_basic\ntest_write_json_config_fast_open_true\ntest_write_json_config_with_plugin\ntest_write_json_config_with_plugin_no_opts\ntest_write_json_config_password_special_chars\n\n# Client JSON config\ntest_write_client_json_config_basic\ntest_write_client_json_config_with_plugin\ntest_client_json_integers_unquoted\n\n# Parse existing config (round-trip)\ntest_parse_existing_config_roundtrip\ntest_parse_existing_config_no_plugin\n\n# Platform detection\ntest_detect_os\ntest_detect_arch\n\n# JSON validity\ntest_json_no_trailing_comma\ntest_json_booleans_unquoted\ntest_json_integers_unquoted\n\necho\necho \"=================================\"\necho \"Results: ${PASS} passed, ${FAIL} failed\"\necho \"=================================\"\n\nif [[ $FAIL -gt 0 ]]; then\n    exit 1\nfi\nexit 0\n"
  },
  {
    "path": "tests/test_utils.c",
    "content": "#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <assert.h>\n#include <string.h>\n#include <stdlib.h>\n\nint verbose = 0;\n\n#include \"utils.h\"\n\nstatic void\ntest_ss_itoa(void)\n{\n    char *s;\n\n    s = ss_itoa(0);\n    assert(s != NULL);\n    assert(strcmp(s, \"0\") == 0);\n\n    s = ss_itoa(42);\n    assert(s != NULL);\n    assert(strcmp(s, \"42\") == 0);\n\n    s = ss_itoa(-1);\n    assert(s != NULL);\n    assert(strcmp(s, \"-1\") == 0);\n\n    s = ss_itoa(12345);\n    assert(s != NULL);\n    assert(strcmp(s, \"12345\") == 0);\n    (void)s;\n}\n\nstatic void\ntest_ss_isnumeric(void)\n{\n    assert(ss_isnumeric(\"12345\") == 1);\n    assert(ss_isnumeric(\"0\") == 1);\n    assert(ss_isnumeric(\"\") == 0);\n    assert(ss_isnumeric(\"abc\") == 0);\n    assert(ss_isnumeric(\"123abc\") == 0);\n    assert(ss_isnumeric(\"12.34\") == 0);\n}\n\nstatic void\ntest_ss_strndup(void)\n{\n    char *s;\n\n    s = ss_strndup(\"hello world\", 5);\n    assert(s != NULL);\n    assert(strcmp(s, \"hello\") == 0);\n    assert(strlen(s) == 5);\n    free(s);\n\n    s = ss_strndup(\"short\", 10);\n    assert(s != NULL);\n    assert(strcmp(s, \"short\") == 0);\n    free(s);\n\n    s = ss_strndup(\"\", 0);\n    assert(s != NULL);\n    assert(strcmp(s, \"\") == 0);\n    free(s);\n}\n\nint\nmain(void)\n{\n    test_ss_itoa();\n    test_ss_isnumeric();\n    test_ss_strndup();\n    return 0;\n}\n"
  }
]