1
0
mirror of https://github.com/kenzok8/small-package synced 2025-09-18 18:51:16 +08:00

update-09.24

This commit is contained in:
github-actions[bot]
2021-09-24 23:37:27 +08:00
parent f9585b6e58
commit 16a922f897
1458 changed files with 321464 additions and 7622 deletions

View File

@ -0,0 +1,63 @@
#
# Copyright (C) 2014-2015 KyleRicardo
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=mentohust
PKG_VERSION:=0.3.1
PKG_RELEASE:=1
PKG_FIXUP:=autoreconf
PKG_INSTALL:=1
include $(INCLUDE_DIR)/package.mk
define Package/mentohust
SECTION:=net
CATEGORY:=Network
DEPENDS:=+libpcap
TITLE:=A Ruijie Client Daemon
URL:=https://github.com/KyleRicardo/MentoHUST-OpenWrt-ipk.git
SUBMENU:=Ruijie
endef
define Package/mentohust/description
A Ruijie Client Daemon,
Most usually used in China collages.
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
$(SED) 's/dhclient/udhcpc -i/g' $(PKG_BUILD_DIR)/myconfig.c
endef
define Package/mentohust/conffiles
/etc/mentohust.conf
endef
define Build/Compile
#$(Build/Compile/$(PKG_NAME))
$(MAKE) -C $(PKG_BUILD_DIR)/ \
$(TARGET_CONFIGURE_OPTS) \
CFLAGS="$(TARGET_CFLAGS)" \
CPPFLAGS="$(TARGET_CPPFLAGS)" \
LDFLAGS="$(TARGET_LDFLAGS) -ldl"
endef
define Package/mentohust/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/mentohust $(1)/usr/sbin/
$(INSTALL_DIR) $(1)/etc
$(INSTALL_CONF) $(PKG_BUILD_DIR)/mentohust.conf $(1)/etc/mentohust.conf
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@ -0,0 +1,276 @@
# MentoHUST-OpenWrt-ipk
这是一个积累了很长时间的项目。从2014年起就陆续在折腾这些东西期间还自己写了一个基于OpenWrt的神州数码客户端[802.1X Evasi0n](https://github.com/KyleRicardo/802.1X-Evasi0n)服役了大半年的时间表现良好内存占用小工作效率高。后来学校所有神州数码服务器全部换成了锐捷导致我的项目失去了光彩我又翻出了大名鼎鼎的MentoHUST在反复折腾交叉编译和功能性修补过程中有了这样一个版本。该版本非常适合于在OpenWrt的SDK环境下编译出MentoHUST的ipk包。
## 特点
- 修复了原MentoHUST在shell下由于libiconv库编译或工作不正常导致的反馈信息乱码问题
- 去除了libiconv库的依赖加入了轻量级的strnormalize库GBK to UTF-8转换良好
- 去除configure等冗余文件仅保留核心src源码文件
- ./src/Makefile中使用通配符`*`指代libpcap版本通用性更强
- 无需手动配置环境变量无需使用automake和configure生成所需Makefile
- 重新完全手动编写./和./src/目录下的Makefile保证编译的有效性
-`--disable-notify --disable-encodepass`等配置,保证原汁原味
- 无手动`#define NO_DYLOAD`补丁使用动态加载库函数ipk包更小并且更容易编译
## PreOperation
### 预备知识
> 这里的编译是指交叉编译。所谓交叉编译,简单地说,就是在一个平台上生成另一个平台上的可执行代码。这里需要注意的是所谓 平台实际上包含两个概念体系结构Architecture、操作系统Operating System。同一个体系结构可以运行不同的操作系统同样同一个操作系统也可以在不同的体系结构上运行。
> 交叉编译通常是不得已而为之,有时是因为目的平台上不允许或不能够安装我们所需要的编译器,而我们又需要这个编译器的某些特征;有时是因为目的平台上的资源贫乏,无法运行我们所需要编译器;有时又是因为目的平台还没有建立,连操作系统都没有,根本谈不上运行什么编译器。
> OpenWrt系统是基于Linux平台的操作系统故我们需要用到Linux的操作系统平台进行交叉编译。但由于种种原因我们的电脑不可能使用Linux操作系统但又要交叉编译怎么办呢这时候就需要用到虚拟机了。
### 需要的工具
- VMWare Workstation虚拟机工具
- 一个Ubuntu Linux镜像版本无所谓笔者用的是15.04版本 x86
- OpenWrt SDK**不建议**自行从网上下载建议直接在Ubuntu中用git clone
- 本项目的源码
### 虚拟机的安装Tips
关于虚拟机在这里不多赘述仅提供一些Tips。如果对虚拟机完全不了解建议不要继续观看本教程先找百度谷歌充充电。
- 推荐新手使用**Ubuntu**
> 虚拟机的Linux系统推荐使用Ubuntu对于我们新手来说这无疑是最适合于我们的系统图形化的界面很贴心基本操作上和Windows相差不大可以较快的熟悉起来。
- 务必安装VMWare Tools工具
> 使用VMWare Workstation装Ubuntu的时候千万不要选择简易安装这样在后面安装VMware Tools会非常麻烦。先建立一个空虚拟机然后再用镜像引导安装这样就比较好系统安装好了之后再安装上VMWare Tools你会发现这个Tools有多么方便。其中最大的好处有二系统分辨率的自动调整和剪贴板的无缝连接。就是说不管文字或者文件你在windows里面使用Ctrl+C复制后可以直接在Ubuntu里面粘贴反之亦然。这在后面将给我们提供非常大的方便。所以VMWare Tools必须安装切记。
- 务必关闭Ubuntu系统屏保
> 还有一点需要提醒的是安装好后在右上角“系统”菜单的“首选项”中选择“屏幕保护程序”然后去掉左下角的“计算机空闲时激活屏幕保护程序”然后按“关闭”这个窗口是没有“应用”或“确定”之类的直接关闭它就会保存。用惯了WINDOWS的用户注意了。为什么要做这步呢因为整个编译过程中有些步骤要等一段时间的老是自动启用屏幕保护程序然后还要重新输密码才能退出也是麻烦事。开始的时候我忘了设置这一步后来有一次把黑屏状态的虚拟机唤醒的时候显卡瞬间崩溃了虚拟机直接死机然后编译了好久的数据丢失了白白浪费了几个小时。这个教训也希望大家引起重视。
## PreCompile
现在进入正题了首先要做的是配置好SDK的交叉编译环境。
### 获取OpenWrt SDK
首先安装 subversion 和 git两个应用广泛的源代码管理方案在此需要这两个工具下载源代码也就是`svn``git`命令。其方法如下:
使用`Ctrl+Alt+T`组合快捷键打开终端然后在左侧的Dock中右键单击将其锁定方便以后打开。如下图
![terminal](https://ws1.sinaimg.cn/large/8832d37agy1fxkp9lt8qbj215p0q8adn.jpg)打开终端后,在其中输入如下命令:
```
$ sudo apt-get update
$ sudo apt-get install git
```
其中,`sudo`是linux系统管理指令是允许系统管理员让普通用户执行一些或者全部的root命令的一个工具`halt``reboot``su`等等。这样不仅减少了root用户的登录和管理时间同样也提高了安全性。sudo不是对shell的一个代替它是面向每个命令的。
`apt-get`是一条linux命令适用于deb包管理式的操作系统主要用于自动从互联网的软件仓库中搜索、安装、升级、卸载软件或操作系统。其简写为`apt`
这两条命令执行后,我们就可以用`git`命令获取所需要的源代码了。
但是,编译源代码还有一些必须的工具和依赖,在这里我们一并安上,这种东西不怕安多了,就怕安少了。执行如下命令:
```bash
$ sudo apt install curl build-essential libncurses5-dev zlib1g-dev gawk flex quilt libssl-dev xsltproc libxml-parser-perl mercurial bzr ecj cvs unzip
```
下面就是来获取trunk版本的SDK了执行命令
```bash
$ git clone https://git.openwrt.org/openwrt/openwrt.git
```
cd到我们的SDK目录下这就是OpenWrt开发环境的根目录。后面几乎所有的操作都是在这个目录下进行
```bash
$ cd openwrt/
```
可以利用Ubuntu的自动填充就是输入`cd op`然后按一下Tab键就会自动填充为上面的命令。记住这一点以后会经常用到熟练使用自动填充会节约不少时间。
### 更新feeds
Feeds也就是软件包列表是在OpenWrt中共用位置的包的集合。运行以下命令即可更新内置软件包列表并链接到编译工具中
```
$ ./scripts/feeds update
$ ./scripts/feeds install
```
如果网速不快可能需要等待一段时间。静待其完成后我们的feeds就被更新了。
从github上下载我已经开源的evasi0n软件包。
将我们的evasi0n文件夹直接放入trunk/package/目录下即可。
### 添加需要编译的第三方软件包也就是我们的MentoHUST-OpenWrt-ipk指定目标架构
首先要在GitHub上clone此repo至package/mentohust目录下。执行命令
```bash
$ git clone https://github.com/KyleRicardo/MentoHUST-OpenWrt-ipk.git package/mentohust
```
这里说一下我的Makefile。
一个工程中的源文件不计其数其按类型、功能、模块分别放在若干个目录中Makefile定义了一系列的规则来指定哪些文件需要先编译哪些文件需要后编译哪些文件需要重新编译甚至于进行更复杂的功能操作因为 Makefile就像一个Shell脚本一样其中也可以执行操作系统的命令。
Makefile的语法规则并不算复杂但是新手研究起来也很头大也不能静下心来去花时间学习Makefile的写法。我虽然起初不会写Makefile但是折腾了这么久之后对于一个Makefile已经不算什么了。于是github上包含了我写的Makefile同学们可以直接编译。下个版本可能会发布自动从网上下载源码并编译的Makefile。
原始的mentohust编码转换是使用的libiconv库这个库问题特别多效率低不方便编译受802.1X Evasi0n项目的启发我干脆摒弃了libiconv库使用了strnormalize这个文件代替了它一次性解决了编码转换问题。所以现在Makefile里面再也找不到iconv的依赖了现在mentohust唯一依赖的库就是libpcap编译起来也是相当轻松了。
Makefile既然已经包括在源码中那么我们可以开始配置我们的编译器了。使用命令
```
$ make menuconfig
```
这个命令会启用图形化的选项,我们在其中进行调节即可。
我们一共要调整三个选项:
> Target System
> Subtarget
> Target Profile
对于极壹,调整好后应该如下图所示:
![HiWiFi](https://ws1.sinaimg.cn/large/8832d37agy1fxkpauo1zyj215p0q8wk7.jpg)
对于小米Mini调整好应该如下图所示
![XiaoMi Mini](https://wx4.sinaimg.cn/large/8832d37agy1fxkpbdkdezj215p0q8teh.jpg)
下面一步,就是把我们要编译的软件包含进去。
在Makefile里面我们已经知道这个软件包是属于Network里的Ruijie所以我们在主菜单中找到Network回车进入然后找到Ruijie这一项
![Ruijie](https://ws3.sinaimg.cn/large/8832d37agy1fxkpcgym9xj215p0q8afx.jpg)
然后到这里
![mentohust](https://ws2.sinaimg.cn/large/8832d37agy1fxkpcox4yvj215p0q8tcv.jpg)
这里不要按Y选中Y选中是将其编译到固件中去我们在这里不是要编译固件而是要神州数码单独作为一个软件编译出来。所以我们按M键选中将其编译为一个组件模块(Module)。
用M键选中后我们用光标键右几次选中Save保存后再多次Exit最终退出这个界面。
### 更新编译必需工具与工具链(编译依赖)
这一步是从官网上获取我们编译所需的工具(如编译器、链接器等),十分关键。不过,命令却十分简单:
```
$ make tools/install
```
即可编译并安装好我们所需的工具。
```
$ make toolchain/install
```
即可编译并安装好我们所需的工具链。
为了显示编译过程我们可以在命令后面加上一个选项V=s。即
```
$ make tools/install V=s
$ make toolchain/install V=s
```
注意V一定要大写。
不幸的是我发现Tools和Toolchain的编译十分漫长等待过程十分痛苦。这是因为需要从网上下载大量的文件而这些镜像源都不是特别好。为了减少等待的时间不妨给大家分享一个小技巧。通过研究编译的过程我发现所需的文件是下载并保存到openwrt目录的dl文件夹下的。通过实验我发现这个dl文件夹可以移植只要我们的OpenWrt SDK的版本是差不多的我们可以直接将已经弄好的dl文件夹放在openwrt目录中这样可以节省大量时间。编译所需的dl文件夹我均已打包上传请自行下载。
[------------百度网盘------------](https://pan.baidu.com/s/1acyd1aAr-QLtWQmy58eZ-g)
下载后提取压缩包到openwrt 目录,然后可以删掉该压缩包。
同样地不建议直接将形如http://downloads.openwrt.org/snapshots/trunk/ramips/OpenWrt-Toolchain-ramips-for-mipsel_24kec%2bdsp-gcc-4.8-linaro_uClibc-0.9.33.2.tar.bz2的这种文件解压后直接应用于我们的toolchain因为省略了编译安装过程后面可能会发生意想不到的错误。dl文件夹我已经提供给大家Toolchain的编译已经不需要太长时间。不要因小失大。
## Compile
```bash
$ make package/mentohust/compile V=s
```
如果顺利,编译完成之后就能在`openwrt/bin/packages/YourArchitecture/base`中找到你的ipk包了。还包含其依赖的libpcap.ipk。如果你的路由器默认没有安装libpcap包可以一并安装。
![compiled-ipk](https://wx1.sinaimg.cn/large/8832d37agy1fxksnqln5bj215p0q8n5j.jpg)
## Install
将上面拷贝出来的mentohust及libpcap的ipk用上面的方法利用WinSCP上传到路由器的tmp目录。这个操作很简单这里不再赘述。
使用快捷键`Ctrl+P`打开PuTTY输入密码(默认是admin)回车后,来到如下界面:
![pandorabox](https://ws3.sinaimg.cn/large/8832d37agy1fxkpeg7eg2j20ir0btjrj.jpg)
然后我们先`cd /tmp/`
然后用`opkg`命令安装我们所需的软件包:
```
opkg install libpcap_1.7.4-1_ramips_24kec.ipk
opkg install mentohust_0.3.1-1_ramips_24kec.ipk
```
这时有可能会出现这种情况:
![arch-mismatch](https://ws4.sinaimg.cn/large/8832d37agy1fxkpfctgj9j20ir0btmxg.jpg)
遇到这种错误,需要修改/etc/opkg.conf文件对于小米Mini需要在其尾部追加
```
arch all 1
arch ralink 200
arch ramips_24kec 100
```
这样就能正确地安装了:
![libpcap](https://wx3.sinaimg.cn/large/8832d37agy1fxkpfyu41kj20ua0jgdgv.jpg)
当然mentohust也可以了
![mentohust](https://ws4.sinaimg.cn/large/8832d37agy1fxkpg99g6zj20ir0btmxg.jpg)
在有些比较老的路由器固件中安装,会有类似这样的错误:
> //usr/lib/opkg/info/mentohust: line 4: default_postinst: not found
> Collected errors:
>
> pkg_run_script: package "mentohust" postinst script returned status 127.
> opkg_configure: dnsmasq-full.postinst returned 127.
上述错误原因如下:
因为evasi0n是基于 trunk 代码编译所以目前编译出的ipk 包默认带有
Package/postinst 脚本
```
#!/bin/sh
[ "${IPKG_NO_SCRIPT}" = "1" ] && exit 0
. ${IPKG_INSTROOT}/lib/functions.sh
default_postinst$0 $@
```
Package/prerm 脚本
```
#!/bin/sh
. ${IPKG_INSTROOT}/lib/functions.sh
default_prerm $0$@
```
而若不是最新编译的固件, /lib/functions.sh 中是没有 default_postinst default_prerm函数的所以会造成 127错误。
临时解决办法:
在PuTTY中键入如下命令并回车
`echo -e "\ndefault_postinst() {\n\treturn0\n}\ndefault_prerm() {\n\treturn 0\n}" >> /lib/functions.sh`
注意这是一条命令是用echo命令将这段空函数追加到functions.sh文件尾部。
上述错误解决之后终于可以愉快地安装mentohust了。
## Usage
安装好后可以立即使用,配置文件在`/etc/mentohust.conf`,可以自行编辑。
关于mentohust的用法想必不用我多说吧。我都已经帮忙帮到这一步了。这里提一下mentohust未能智能识别路由器WAN口对应的网卡请手动在mentohust.conf的末尾DHCP脚本中添加自己WAN口对应的网卡。最终脚本类似`udhcpc -i eth1`
最后可以将mentohust添加到开机启动怎么弄不用我多说了吧。
## 已知问题
- mentohust未能智能识别路由器WAN口对应的网卡请手动在mentohust.conf的末尾DHCP脚本中添加自己WAN口对应的网卡。最终脚本类似`udhcpc -i eth1`
- 暂未加入init.d目录的mentohust脚本可能下个版本加入。
- 后续可能加入只有一个Makefile通过自动从git下载源码进行编译的版本

View File

@ -0,0 +1,46 @@
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/package.mk
CC = mips-openwrt-linux-gcc
CFLAGS = -Wall -g -O2
INC_DIR= $(STAGING_DIR)/usr/include -I$(BUILD_DIR)/libpcap-*/ipkg-install/usr/include
LINK_DIR= $(STAGING_DIR)/usr/lib -L$(BUILD_DIR)/libpcap-*/ipkg-install/usr/lib
LIBS= $(BUILD_DIR)/libpcap-*/ipkg-install/usr/lib/libpcap.a
OBJ = mentohust.o dlfunc.o md5.o mycheck.o myconfig.o myfunc.o strnormalize.o myini.o mystate.o
.PHONY: all
all: mentohust
mentohust: $(OBJ)
$(CC) $(CFLAGS) -o $@ $(OBJ) $(LIBS) -I$(INC_DIR) -L$(LINK_DIR) $(LDFLAGS)
mentohust.o : mentohust.c
$(CC) $(CFLAGS) -c $< -I$(INC_DIR)
dlfunc.o : dlfunc.c
$(CC) $(CFLAGS) -c $< -I$(INC_DIR)
md5.o : md5.c md5.h
$(CC) $(CFLAGS) -c $< -I$(INC_DIR)
strnormalize.o: strnormalize.c strnormalize.h
$(CC) $(CFLAGS) -c $< -I$(INC_DIR)
mycheck.o : mycheck.c
$(CC) $(CFLAGS) -c $< -I$(INC_DIR)
myconfig.o : myconfig.c
$(CC) $(CFLAGS) -c $< -I$(INC_DIR)
myfunc.o : myfunc.c
$(CC) $(CFLAGS) -c $< -I$(INC_DIR)
myini.o : myini.c
$(CC) $(CFLAGS) -c $< -I$(INC_DIR)
mystate.o : mystate.c
$(CC) $(CFLAGS) -c $< -I$(INC_DIR)
clean :
rm -v $(OBJ) mentohust

View File

@ -0,0 +1,153 @@
/* -*- Mode: C; tab-width: 4; -*- */
/*
* Copyright (C) 2009, HustMoon Studio
*
* 文件名称dlfunc.c
* 摘 要:动态载入库函数
* 作 者HustMoon@BYHH
* 邮 箱www.ehust@gmail.com
* 日 期2009.11.11
*/
#include "dlfunc.h"
#ifndef NO_DYLOAD
#include <dlfcn.h>
int (*pcap_findalldevs)(pcap_if_t **, char *);
void (*pcap_freealldevs)(pcap_if_t *);
pcap_t *(*pcap_open_live)(const char *, int, int, int, char *);
int (*pcap_compile)(pcap_t *, struct bpf_program *, const char *, int, bpf_u_int32);
int (*pcap_setfilter)(pcap_t *, struct bpf_program *);
char *(*pcap_geterr)(pcap_t *);
void (*pcap_freecode)(struct bpf_program *);
int (*pcap_loop)(pcap_t *, int, pcap_handler, unsigned char *);
void (*pcap_close)(pcap_t *);
void (*pcap_breakloop)(pcap_t *);
int (*pcap_sendpacket)(pcap_t *, const unsigned char *, int);
static void *libpcap = NULL;
int load_libpcap(void) {
char *error;
#ifdef MAC_OS
char *file[] = {"libpcap.dylib", "libpcap.A.dylib"};
int i, count = 2;
#else
char *file[] = {"libpcap.so", "libpcap.so.1", "libpcap.so.1.0", "libpcap.so.0.9", "libpcap.so.0.8"};
int i, count = 5;
#endif
for (i=0; i<count && !libpcap; i++) {
libpcap = dlopen(file[i], RTLD_LAZY);
error = dlerror();
}
if (libpcap == NULL) {
printf("!! 打开libpcap失败请检查是否已安装该库文件。\n");
return -1;
}
if ((pcap_findalldevs = dlsym(libpcap, "pcap_findalldevs"), error = dlerror()) != NULL
|| (pcap_freealldevs = dlsym(libpcap, "pcap_freealldevs"), error = dlerror()) != NULL
|| (pcap_open_live = dlsym(libpcap, "pcap_open_live"), error = dlerror()) != NULL
|| (pcap_compile = dlsym(libpcap, "pcap_compile"), error = dlerror()) != NULL
|| (pcap_setfilter = dlsym(libpcap, "pcap_setfilter"), error = dlerror()) != NULL
|| (pcap_geterr = dlsym(libpcap, "pcap_geterr"), error = dlerror()) != NULL
|| (pcap_freecode = dlsym(libpcap, "pcap_freecode"), error = dlerror()) != NULL
|| (pcap_loop = dlsym(libpcap, "pcap_loop"), error = dlerror()) != NULL
|| (pcap_close = dlsym(libpcap, "pcap_close"), error = dlerror()) != NULL
|| (pcap_breakloop = dlsym(libpcap, "pcap_breakloop"), error = dlerror()) != NULL
|| (pcap_sendpacket = dlsym(libpcap, "pcap_sendpacket"), error = dlerror()) != NULL) {
printf("!! 从libpcap获取函数失败: %s\n", error);
free_libpcap();
return -1;
}
return 0;
}
void free_libpcap(void) {
if (libpcap) {
dlclose(libpcap);
dlerror();
libpcap = NULL;
}
}
#endif /* NO_DYLOAD */
#ifndef NO_NOTIFY
#include <dlfcn.h>
typedef void NotifyNotification, GtkWidget, GError;
typedef char gchar;
typedef int gint, gboolean;
static gboolean (*notify_notification_update)(NotifyNotification *, const gchar *,
const gchar *, const gchar *);
static void (*notify_notification_set_timeout)(NotifyNotification *, gint);
static gboolean (*notify_notification_show)(NotifyNotification *, GError **);
static void *libnotify = NULL;
static NotifyNotification *notify = NULL;
int load_libnotify(void) {
char *error;
gboolean (*notify_init)(const char *);
NotifyNotification *(*notify_notification_new)(const gchar *, const gchar *,
const gchar *, GtkWidget *);
#ifdef MAC_OS
char *file[] = {"libnotify.dylib", "libnotify.1.dylib"};
int i, count = 2;
#else
char *file[] = {"libnotify.so", "libnotify.so.1"};
int i, count = 2;
#endif
for (i=0; i<count && !libnotify; i++) {
libnotify = dlopen(file[i], RTLD_LAZY);
error = dlerror();
}
if (libnotify == NULL) {
printf("!! 打开libnotify失败请检查是否已安装该库文件。\n");
return -1;
}
if ((notify_init = dlsym(libnotify, "notify_init"), error = dlerror()) != NULL
|| (notify_notification_new = dlsym(libnotify, "notify_notification_new"), error = dlerror()) != NULL
|| (notify_notification_show = dlsym(libnotify, "notify_notification_show"), error = dlerror()) != NULL
|| (notify_notification_update = dlsym(libnotify, "notify_notification_update"), error = dlerror()) != NULL
|| (notify_notification_set_timeout = dlsym(libnotify, "notify_notification_set_timeout"), error = dlerror()) != NULL) {
printf("!! 从libnotify获取函数失败: %s\n", error);
free_libnotify();
return -1;
}
if (!notify_init("mentohust")) {
printf("!! 初始化libnotify失败。\n");
free_libnotify();
return -1;
}
notify = notify_notification_new("MentoHUST", NULL, NULL, NULL);
return 0;
}
void free_libnotify(void) {
void (*notify_uninit)(void);
if (notify) {
notify_uninit = dlsym(libnotify, "notify_uninit");
if (!dlerror())
notify_uninit();
notify = NULL;
}
if (libnotify) {
dlclose(libnotify);
dlerror();
libnotify = NULL;
}
}
void set_timeout(int timeout) {
notify_notification_set_timeout(notify, timeout);
}
void show_notify(const char *summary, char *body) {
notify_notification_update(notify, summary, body, NULL);
notify_notification_show(notify, NULL);
}
#endif /* NO_NOTIFY */

View File

@ -0,0 +1,77 @@
/* -*- Mode: C; tab-width: 4; -*- */
/*
* 文件名称dlfunc.h
* 摘 要:动态载入库函数
*/
#ifndef HUSTMOON_DLFUNC_H
#define HUSTMOON_DLFUNC_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <sys/time.h>
#define PCAP_ERRBUF_SIZE 256
#define PCAP_IF_LOOPBACK 0x00000001
typedef unsigned int bpf_u_int32;
typedef void pcap_t;
typedef struct pcap_if {
struct pcap_if *next;
char *name;
char *description;
void *addresses;
bpf_u_int32 flags;
}pcap_if_t;
struct bpf_program {
unsigned int bf_len;
void *bf_insns;
};
struct pcap_pkthdr {
struct timeval ts;
bpf_u_int32 caplen;
bpf_u_int32 len;
};
typedef void (*pcap_handler)(unsigned char *, const struct pcap_pkthdr *, const unsigned char *);
#ifdef NO_DYLOAD
int pcap_findalldevs(pcap_if_t **, char *);
void pcap_freealldevs(pcap_if_t *);
pcap_t *pcap_open_live(const char *, int, int, int, char *);
int pcap_compile(pcap_t *, struct bpf_program *, const char *, int, bpf_u_int32);
int pcap_setfilter(pcap_t *, struct bpf_program *);
char *pcap_geterr(pcap_t *);
void pcap_freecode(struct bpf_program *);
int pcap_loop(pcap_t *, int, pcap_handler, unsigned char *);
void pcap_close(pcap_t *);
void pcap_breakloop(pcap_t *);
int pcap_sendpacket(pcap_t *, const unsigned char *, int);
#else
extern int (*pcap_findalldevs)(pcap_if_t **, char *);
extern void (*pcap_freealldevs)(pcap_if_t *);
extern pcap_t *(*pcap_open_live)(const char *, int, int, int, char *);
extern int (*pcap_compile)(pcap_t *, struct bpf_program *, const char *, int, bpf_u_int32);
extern int (*pcap_setfilter)(pcap_t *, struct bpf_program *);
extern char *(*pcap_geterr)(pcap_t *);
extern void (*pcap_freecode)(struct bpf_program *);
extern int (*pcap_loop)(pcap_t *, int, pcap_handler, unsigned char *);
extern void (*pcap_close)(pcap_t *);
extern void (*pcap_breakloop)(pcap_t *);
extern int (*pcap_sendpacket)(pcap_t *, const unsigned char *, int);
int load_libpcap(void); /* 载入libpcap.so */
void free_libpcap(void); /* 释放libpcap.so */
#endif /* NO_DYLOAD */
#ifndef NO_NOTIFY
int load_libnotify(void); /* 载入libnotify.so */
void free_libnotify(void); /* 释放libnotify.so */
void set_timeout(int timeout); /* 设置超时间隔 */
void show_notify(const char *summary, char *body); /* 显示通知:概要、正文 */
#endif /* NO_NOTIFY */
#endif /* HUSTMOON_DLFUNC_H */

View File

@ -0,0 +1,297 @@
/* MD5.c - an implementation of md5 algorithm */
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#include "md5.h"
#include <string.h>
/* Constants for MD5Transform routine. */
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
static void MD5Transform(UINT4 [4], UCHAR [64]);
static void Encode(UCHAR *, UINT4 *, UINT4);
static void Decode(UINT4 *, UCHAR *, UINT4);
static UCHAR PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
void MD5Init (MD5_CTX * context)
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.
*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
void MD5Update (MD5_CTX *context, UCHAR *input, UINT4 inputLen)
{
UINT4 i, index, partLen;
/* Compute number of bytes mod 64 */
index = (UINT4)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.
*/
if (inputLen >= partLen) {
memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);
MD5Transform (context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
memcpy((POINTER)&context->buffer[index], (POINTER)&input[i],inputLen-i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
void MD5Final (UCHAR digest[16], MD5_CTX *context)
{
UCHAR bits[8];
UINT4 index, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64.
*/
index = (UINT4)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update (context, PADDING, padLen);
/* Append length (before padding) */
MD5Update (context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
/* Zeroize sensitive information.
*/
memset ((POINTER)context, 0, sizeof (*context));
}
/* MD5 basic transformation. Transforms state based on block.
*/
static void MD5Transform (UINT4 state[4],UCHAR block[64])
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information.
*/
memset ((POINTER)x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (UCHAR). Assumes len is
a multiple of 4.
*/
static void Encode (UCHAR *output, UINT4 *input, UINT4 len)
{
UINT4 i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (UCHAR)(input[i] & 0xff);
output[j+1] = (UCHAR)((input[i] >> 8) & 0xff);
output[j+2] = (UCHAR)((input[i] >> 16) & 0xff);
output[j+3] = (UCHAR)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (UCHAR) into output (UINT4). Assumes len is
a multiple of 4.
*/
static void Decode (UINT4 *output, UCHAR *input, UINT4 len)
{
UINT4 i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
/*Compute the md5sum (return static-local-variable),whose length is 16 bytes.*/
UCHAR* ComputeHash(UCHAR* src, UINT4 len)
{
MD5_CTX context;
static UCHAR digest[16];
MD5Init(&context);
MD5Update(&context, src, len);
MD5Final(digest, &context);
return digest;
}

View File

@ -0,0 +1,43 @@
/* MD5.H - header file for MD5.C */
/*
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.*/
#ifndef MD5_H
#define MD5_H
#include "types.h"
/* MD5 context. */
typedef struct
{
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
UCHAR buffer[64]; /* input buffer */
} MD5_CTX;
void MD5Init(MD5_CTX * context);
void MD5Update(MD5_CTX *context, UCHAR *input, UINT4 inputLen);
void MD5Final(UCHAR digest[16], MD5_CTX *context);
UCHAR* ComputeHash(UCHAR *src, UINT4 len);
#endif /* MD5_H */

View File

@ -0,0 +1,278 @@
/* -*- Mode: C; tab-width: 4; -*- */
/*
* Copyright (C) 2009, HustMoon Studio
*
* 文件名称mentohust.c
* 摘 要MentoHUST主函数
* 作 者HustMoon@BYHH
* 邮 箱www.ehust@gmail.com
*/
#include "strnormalize.h"
#include "myconfig.h"
#include "mystate.h"
#include "myfunc.h"
#include "dlfunc.h"
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <unistd.h>
extern pcap_t *hPcap;
extern volatile int state;
extern u_char *fillBuf;
extern const u_char *capBuf;
extern unsigned startMode, dhcpMode, maxFail;
extern u_char destMAC[];
extern int lockfd;
#ifndef NO_NOTIFY
extern int showNotify;
#endif
#ifndef NO_ARP
extern u_int32_t rip, gateway;
extern u_char gateMAC[];
#endif
static void exit_handle(void); /* 退出回调 */
static void sig_handle(int sig); /* 信号回调 */
static void pcap_handle(u_char *user, const struct pcap_pkthdr *h, const u_char *buf); /* pcap_loop回调 */
static void showRuijieMsg(const u_char *buf, unsigned bufLen); /* 显示锐捷服务器提示信息 */
static void showCernetMsg(const u_char *buf); /* 显示赛尔服务器提示信息 */
int main(int argc, char **argv)
{
atexit(exit_handle);
initConfig(argc, argv);
signal(SIGALRM, sig_handle); /* 定时器 */
signal(SIGHUP, sig_handle); /* 注销时 */
signal(SIGINT, sig_handle); /* Ctrl+C */
signal(SIGQUIT, sig_handle); /* Ctrl+\ */
signal(SIGTSTP, sig_handle); /* Ctrl+Z */
signal(SIGTERM, sig_handle); /* 被结束时 */
if (dhcpMode == 3) /* 认证前DHCP */
switchState(ID_DHCP);
else
switchState(ID_START); /* 开始认证 */
if (-1 == pcap_loop(hPcap, -1, pcap_handle, NULL)) { /* 开始捕获数据包 */
printf("!! 捕获数据包失败,请检查网络连接!\n");
#ifndef NO_NOTIFY
if (showNotify)
show_notify("MentoHUST - 错误提示", "捕获数据包失败,请检查网络连接!");
#endif
}
exit(EXIT_FAILURE);
}
static void exit_handle(void)
{
if (state != ID_DISCONNECT)
switchState(ID_DISCONNECT);
if (hPcap != NULL)
pcap_close(hPcap);
if (fillBuf != NULL)
free(fillBuf);
if (lockfd > -1)
close(lockfd);
#ifndef NO_NOTIFY
free_libnotify();
#endif
#ifndef NO_DYLOAD
free_libpcap();
#endif
printf(">> 认证已退出。\n");
}
static void sig_handle(int sig)
{
if (sig == SIGALRM) /* 定时器 */
{
if (-1 == switchState(state))
{
pcap_breakloop(hPcap);
printf("!! 发送数据包失败, 请检查网络连接!\n");
#ifndef NO_NOTIFY
if (showNotify)
show_notify("MentoHUST - 错误提示", "发送数据包失败, 请检查网络连接!");
#endif
exit(EXIT_FAILURE);
}
}
else /* 退出 */
{
pcap_breakloop(hPcap);
exit(EXIT_SUCCESS);
}
}
static void pcap_handle(u_char *user, const struct pcap_pkthdr *h, const u_char *buf)
{
static unsigned failCount = 0;
#ifndef NO_ARP
if (buf[0x0c]==0x88 && buf[0x0d]==0x8e) {
#endif
if (memcmp(destMAC, buf+6, 6)!=0 && startMode>2) /* 服务器MAC地址不符 */
return;
capBuf = buf;
if (buf[0x0F]==0x00 && buf[0x12]==0x01 && buf[0x16]==0x01) { /* 验证用户名 */
if (startMode < 3) {
memcpy(destMAC, buf+6, 6);
printf("** 认证MAC:\t%s\n", formatHex(destMAC, 6));
startMode += 3; /* 标记为已获取 */
}
if (startMode==3 && memcmp(buf+0x17, "User name", 9)==0) /* 塞尔 */
startMode = 5;
switchState(ID_IDENTITY);
}
else if (buf[0x0F]==0x00 && buf[0x12]==0x01 && buf[0x16]==0x04) /* 验证密码 */
switchState(ID_CHALLENGE);
else if (buf[0x0F]==0x00 && buf[0x12]==0x03) { /* 认证成功 */
printf(">> 认证成功!\n");
failCount = 0;
if (!(startMode%3 == 2)) {
getEchoKey(buf);
showRuijieMsg(buf, h->caplen);
}
if (dhcpMode==1 || dhcpMode==2) /* 二次认证第一次或者认证后 */
switchState(ID_DHCP);
else if (startMode%3 == 2)
switchState(ID_WAITECHO);
else
switchState(ID_ECHO);
}
else if (buf[0x0F]==0x00 && buf[0x12]==0x01 && buf[0x16]==0x02) /* 显示赛尔提示信息 */
showCernetMsg(buf);
else if (buf[0x0F] == 0x05) /* (赛尔)响应在线 */
switchState(ID_ECHO);
else if (buf[0x0F]==0x00 && buf[0x12]==0x04) { /* 认证失败或被踢下线 */
if (state==ID_WAITECHO || state==ID_ECHO) {
printf(">> 认证掉线,开始重连!\n");
switchState(ID_START);
}
else if (buf[0x1b]!=0 || startMode%3==2) {
printf(">> 认证失败!\n");
if (startMode%3 != 2)
showRuijieMsg(buf, h->caplen);
if (maxFail && ++failCount>=maxFail) {
printf(">> 连续认证失败%u次退出认证。\n", maxFail);
exit(EXIT_SUCCESS);
}
restart();
}
else
switchState(ID_START);
}
#ifndef NO_ARP
} else if (gateMAC[0]!=0xFE && buf[0x0c]==0x08 && buf[0x0d]==0x06) {
if (*(u_int32_t *)(buf+0x1c) == gateway) {
char str[50];
if (gateMAC[0] == 0xFF) {
memcpy(gateMAC, buf+0x16, 6);
printf("** 网关MAC:\t%s\n", formatHex(gateMAC, 6));
fflush(stdout);
sprintf(str, "arp -s %s %s", formatIP(gateway), formatHex(gateMAC, 6));
system(str);
} else if (buf[0x15]==0x02 && *(u_int32_t *)(buf+0x26)==rip
&& memcmp(gateMAC, buf+0x16, 6)!=0) {
printf("** ARP欺骗:\t%s\n", formatHex(buf+0x16, 6));
fflush(stdout);
#ifndef NO_NOTIFY
if (showNotify) {
sprintf(str, "欺骗源: %s", formatHex(buf+0x16, 6));
show_notify("MentoHUST - ARP提示", str);
}
#endif
}
}
}
#endif
}
#ifndef MAC_OS
static char *gbk2utf(char *gbksrc, size_t gbklen) /* GBK转UTF8 */
#else
static char *gbk2utf(const char *gbksrc, size_t gbklen) /* GBK转UTF8 */
#endif
{
/* GBK一汉字俩字节UTF-8一汉字3字节二者ASCII字符均一字节
所以这样申请是足够的了,要记得释放 */
str_normalize_init();
size_t utf8len = gbklen * 3 + 1;
char *utf8dst = (char *)malloc(utf8len);
memset(utf8dst,0,utf8len);
char *temp=(char *)malloc(gbklen+5);
memset(temp, 0, gbklen+5);
memcpy(temp,gbksrc,gbklen);
gbksrc = temp;
gbklen = strlen(gbksrc);
gbk_to_utf8(gbksrc, gbklen, &utf8dst, &utf8len);
free(temp);
return utf8dst;
}
static void showRuijieMsg(const u_char *buf, unsigned bufLen)
{
char *serverMsg;
int length = buf[0x1b];
if (length > 0)
{
for (serverMsg=(char *)(buf+0x1c); *serverMsg=='\r'||*serverMsg=='\n'; serverMsg++,length--); /* 跳过开头的换行符 */
if (strlen(serverMsg) < length)
length = strlen(serverMsg);
if (length>0 && (serverMsg=gbk2utf(serverMsg, length))!=NULL)
{
printf("$$ 系统提示:\t%s\n", serverMsg);
#ifndef NO_NOTIFY
if (showNotify)
show_notify("MentoHUST - 系统提示", serverMsg);
#endif
free(serverMsg);
}
}
if ((length=0x1c+buf[0x1b]+0x69+39) < bufLen)
{
serverMsg=(char *)(buf+length);
if (buf[length-1]-2 > bufLen-length)
length = bufLen - length;
else
length = buf[length-1]-2;
for (; *serverMsg=='\r'||*serverMsg=='\n'; serverMsg++,length--);
if (length>0 && (serverMsg=gbk2utf(serverMsg, length))!=NULL)
{
printf("$$ 计费提示:\t%s\n", serverMsg);
#ifndef NO_NOTIFY
if (showNotify)
show_notify("MentoHUST - 计费提示", serverMsg);
#endif
free(serverMsg);
}
}
fflush(stdout);
}
static void showCernetMsg(const u_char *buf)
{
char *serverMsg = (char *)(buf+0x17);
int length = ntohs(*(u_int16_t *)(buf+0x14)) - 5;
if (strlen(serverMsg) < length)
length = strlen(serverMsg);
if (length>0 && (serverMsg=gbk2utf(serverMsg, length))!=NULL)
{
printf("$$ 系统提示:\t%s\n", serverMsg);
#ifndef NO_NOTIFY
if (showNotify)
show_notify("MentoHUST - 系统提示", serverMsg);
#endif
free(serverMsg);
}
fflush(stdout);
}

View File

@ -0,0 +1,46 @@
# MentoHUST for Linux By HustMoon Studio
#
# 配置文件名称必须是小写/etc/mentohust.conf编码格式建议是UTF-8
# 配置文件中一行开头的空格和Tab会被忽略其他的会视为参数一部分
# 配置文件中Section与Key不区分大小写以#或;开头的行视为注释
# 同一个参数若在命令行参数和配置文件中均有设置,使用命令行参数
# 命令行中使用参数-h或-?可查看详细参数信息,建议通过命令行设置参数
# 命令行中使用参数-w可将配置更新到/etc/mentohust.conf
[MentoHUST]
;用户名长度不超过64
Username=
;密码(简单加密)
EncodePass=
;网卡
Nic=
;静态IP用户可以使用非本机IP
IP=
;掩码,无关紧要
Mask=
;网关如果指定了就会监视网关ARP信息
Gateway=
;DNS服务器无关紧要
DNS=
;Ping主机用于掉线检测0.0.0.0表示关闭该功能
PingHost=
;每次发包超时时间(秒)
Timeout=
;发送Echo包的间隔
EchoInterval=
;失败等待认证失败后等待RestartWait秒或者服务器请求后重启认证
RestartWait=
;寻找服务器时的组播地址类型 0标准 1锐捷 2将MentoHUST用于赛尔认证
StartMode=
;DHCP方式 0(不使用) 1(二次认证) 2(认证后) 3(认证前)
DhcpMode=
;是否后台运行: 0(否) 1(是,关闭输出) 2(是,保留输出) 3(是,输出到文件/tmp/mentohust.log)
DaemonMode=
;是否显示通知: 0(否) 1~20(是)
ShowNotify=
;客户端版本号如果未开启客户端校验但对版本号有要求可以在此指定形如3.30
Version=
;认证数据文件,如果需要校验客户端,就需要正确设置
DataFile=
;进行DHCP的脚本
DhcpScript=

View File

@ -0,0 +1,189 @@
/* -*- Mode: C; tab-width: 4; -*- */
/*
* Copyright (C) 2009, HustMoon Studio
*
* 文件名称mycheck.c
* 摘 要:客户端校验算法
* 作 者kkHAIKE & HustMoon
*/
#include "mycheck.h"
#include "md5.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static BYTE *bin_8021x = NULL;
static DWORD size_8021x;
static BYTE hex[][17]={"0123456789ABCDEF", "0123456789abcdef"};
#ifdef WORDS_BIGENDIAN
WORD ltobs(WORD x) {
return ((x & 0xff) << 8) | ((x & 0xff00) >> 8);
}
DWORD ltobl(DWORD x) {
return ((x & 0xff) << 24) |\
((x & 0xff00) << 8) |\
((x & 0xff0000) >> 8) |\
((x & 0xff000000) >> 24);
}
#endif
void hex_to_str(const BYTE *a, char *b, int hexsize, int upper) {
BYTE *q = (BYTE *)b;
int i;
for (i=0; i<hexsize; i++) {
*q = hex[upper][a[i]>>4]; q++;
*q = hex[upper][a[i]&0xf]; q++;
}
*q = 0;
}
BYTE *ReadCode(const char *file, DWORD *size) {
BYTE *data = NULL;
int i;
FILE *fp;
PPE_HEADER_MAP hpe;
if ((fp=fopen(file, "rb")) == NULL)
goto fileError;
data = (BYTE *)malloc(0x1000);
if (fread(data, 0x1000, 1, fp) < 1)
goto fileError;
hpe = (PPE_HEADER_MAP)(data + LTOBL(((PIMAGE_DOS_HEADER)data)->e_lfanew));
for (i=0; i<LTOBS(hpe->_head.NumberOfSections); i++) {
if (LTOBL(hpe->section_header[i].Characteristics) & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE)) {
fseek(fp, LTOBL(hpe->section_header[i].PointerToRawData), SEEK_SET);
*size = LTOBL(hpe->section_header[i].SizeOfRawData);
free(data);
data = (BYTE *)malloc(*size);
if (fread(data, *size, 1, fp) < 1)
goto fileError;
fclose(fp);
return data;
}
}
fileError:
if (fp != NULL)
fclose(fp);
if (data != NULL)
free(data);
return NULL;
}
BYTE *ReadCode2(const char *dataFile, DWORD *size) {
BYTE Buf[16], *buf=Buf;
FILE *fp = NULL;
if ((fp=fopen(dataFile, "rb")) == NULL
|| fread(buf, 16, 1, fp ) < 1)
goto fileError;
*size = LTOBL(*(UINT4 *)buf ^ *(UINT4 *)(buf + 4));
if ((int)*size <= 0)
goto fileError;
buf = (BYTE *)malloc(*size+0x100);
if (fread(buf, *size, 1, fp) < 1) {
free(buf);
goto fileError;
}
fclose(fp);
return buf;
fileError:
if (fp != NULL)
fclose(fp);
return NULL;
}
void check_free() {
if (bin_8021x) {
free(bin_8021x);
bin_8021x = NULL;
}
}
int check_init(const char *dataFile) {
char name[0x100];
char *p;
check_free();
strcpy(name, dataFile);
if ((p=strrchr(name, '/')+1) == (void *)1)
p = name;
strcpy(p, "8021x.exe");
if ((bin_8021x=ReadCode(name, &size_8021x)) == NULL
&& (bin_8021x=ReadCode2(dataFile, &size_8021x)) == NULL)
return -1;
return 0;
}
void V2_check(const BYTE *seed, char *final_str) {
int i, size = size_8021x / 8;
BYTE table[144], *md5Dig, *b8021x = (BYTE *)malloc(size+16);
memcpy(b8021x, seed, 16);
for (i=0; i<8; i++) {
memcpy(b8021x+16, bin_8021x+size*i, size);
md5Dig = ComputeHash(b8021x, size+16);
table[18*i] = seed[2*i];
memcpy(table+18*i+1, md5Dig, 16);
table[18*i+17] = seed[2*i+1];
}
free(b8021x);
md5Dig = ComputeHash(table, 144);
hex_to_str(md5Dig, final_str, 16, 1);
}
DWORD getVer(const char *file) {
FILE *fp;
BYTE *data = NULL;
int i, j;
DWORD size, VirtualAddress;
PPE_HEADER_MAP hpe;
PIMAGE_RESOURCE_DIRECTORY prd;
PIMAGE_RESOURCE_DATA_ENTRY prde;
PVS_VERSIONINFO pvs;
if ((fp=fopen(file, "rb")) == NULL)
goto fileError;
data = (BYTE *)malloc(0x1000);
if (fread(data, 0x1000, 1, fp) < 1)
goto fileError;
hpe = (PPE_HEADER_MAP)(data + LTOBL(((PIMAGE_DOS_HEADER)data)->e_lfanew));
for (i=LTOBS(hpe->_head.NumberOfSections)-1; i>=0; i--) {
if (strcmp(hpe->section_header[i].Name, ".rsrc") == 0) {
fseek(fp, LTOBL(hpe->section_header[i].PointerToRawData), SEEK_SET);
size = LTOBL(hpe->section_header[i].SizeOfRawData);
VirtualAddress = LTOBL(hpe->section_header[i].VirtualAddress);
free(data);
data = (BYTE *)malloc(size);
if (fread(data, size, 1, fp) < 1)
goto fileError;
prd = (PIMAGE_RESOURCE_DIRECTORY)data;
for (j=0; j<LTOBS(prd->NumberOfIdEntries); j++) {
prd->DirectoryEntries[j].Name = LTOBL(prd->DirectoryEntries[j].Name);
if (prd->DirectoryEntries[j].Id==16 && prd->DirectoryEntries[j].NameIsString==0) {
prd->DirectoryEntries[j].OffsetToData = LTOBL(prd->DirectoryEntries[j].OffsetToData);
prd = (PIMAGE_RESOURCE_DIRECTORY)(data+prd->DirectoryEntries[j].OffsetToDirectory);
prd->DirectoryEntries[0].OffsetToData = LTOBL(prd->DirectoryEntries[0].OffsetToData);
prd = (PIMAGE_RESOURCE_DIRECTORY)(data+prd->DirectoryEntries[0].OffsetToDirectory);
prde = (PIMAGE_RESOURCE_DATA_ENTRY)(data+LTOBL(prd->DirectoryEntries[0].OffsetToData));
pvs = (PVS_VERSIONINFO)(data+LTOBL(prde->OffsetToData)-VirtualAddress);
size = pvs->Value.dwFileVersionMS;
fclose(fp);
free(data);
return size;
}
}
goto fileError;
}
}
fileError:
if (fp != NULL)
fclose(fp);
if (data != NULL)
free(data);
return -1;
}

View File

@ -0,0 +1,219 @@
/* -*- Mode: C; tab-width: 4; -*- */
/*
* Copyright (C) 2009, HustMoon Studio
*
* 文件名称mycheck.h
* 摘 要:客户端校验算法
* 作 者kkHAIKE
*/
#ifndef MYCHECK_H
#define MYCHECK_H
#include "types.h"
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields.
//
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
//
// NT additional fields.
//
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
#define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct _IMAGE_SECTION_HEADER {
char Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
typedef struct _PE_HEADER_MAP
{
DWORD signature;
IMAGE_FILE_HEADER _head;
IMAGE_OPTIONAL_HEADER opt_head;
IMAGE_SECTION_HEADER section_header[8];
}PE_HEADER_MAP,*PPE_HEADER_MAP;
typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
#ifdef WORDS_BIGENDIAN
union {
struct {
DWORD NameIsString:1;
DWORD NameOffset:31;
};
DWORD Name;
struct {
WORD Id_unuse;
WORD Id;
};
};
union {
DWORD OffsetToData;
struct {
DWORD DataIsDirectory:1;
DWORD OffsetToDirectory:31;
};
};
#else
union {
struct {
DWORD NameOffset:31;
DWORD NameIsString:1;
};
DWORD Name;
WORD Id;
};
union {
DWORD OffsetToData;
struct {
DWORD OffsetToDirectory:31;
DWORD DataIsDirectory:1;
};
};
#endif
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
typedef struct _IMAGE_RESOURCE_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
WORD NumberOfNamedEntries;
WORD NumberOfIdEntries;
IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;
typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
DWORD OffsetToData;
DWORD Size;
DWORD CodePage;
DWORD Reserved;
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;
typedef struct tagVS_FIXEDFILEINFO {
DWORD dwSignature; /* e.g. 0xfeef04bd */
DWORD dwStrucVersion; /* e.g. 0x00000042 = "0.42" */
DWORD dwFileVersionMS; /* e.g. 0x00030075 = "3.75" */
DWORD dwFileVersionLS; /* e.g. 0x00000031 = "0.31" */
DWORD dwProductVersionMS; /* e.g. 0x00030010 = "3.10" */
DWORD dwProductVersionLS; /* e.g. 0x00000031 = "0.31" */
DWORD dwFileFlagsMask; /* = 0x3F for version "0.42" */
DWORD dwFileFlags; /* e.g. VFF_DEBUG | VFF_PRERELEASE */
DWORD dwFileOS; /* e.g. VOS_DOS_WINDOWS16 */
DWORD dwFileType; /* e.g. VFT_DRIVER */
DWORD dwFileSubtype; /* e.g. VFT2_DRV_KEYBOARD */
DWORD dwFileDateMS; /* e.g. 0 */
DWORD dwFileDateLS; /* e.g. 0 */
} VS_FIXEDFILEINFO;
typedef struct _VS_VERSIONINFO {
WORD wLength;
WORD wValueLength;
WORD wType;
WORD szKey[16];
WORD Padding1[1];
VS_FIXEDFILEINFO Value;
} VS_VERSIONINFO, *PVS_VERSIONINFO;
#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code
#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable
#ifdef WORDS_BIGENDIAN
#define LTOBS(x) ltobs(x)
#define LTOBL(x) ltobl(x)
WORD ltobs(WORD x);
DWORD ltobl(DWORD x);
#else
#define LTOBS(x) (x)
#define LTOBL(x) (x)
#endif
int check_init(const char *dataFile);
void V2_check(const BYTE *seed, char *final_str);
void check_free();
DWORD getVer(const char *file);
#endif

View File

@ -0,0 +1,592 @@
/* -*- Mode: C; tab-width: 4; -*- */
/*
* Copyright (C) 2009, HustMoon Studio
*
* 文件名称myconfig.c
* 摘 要:初始化认证参数
* 作 者HustMoon@BYHH
* 邮 箱www.ehust@gmail.com
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#else
static const char *VERSION = "0.3.1";
static const char *PACKAGE_BUGREPORT = "http://code.google.com/p/mentohust/issues/list";
#endif
#include "myconfig.h"
#include "myini.h"
#include "myfunc.h"
#include "dlfunc.h"
#include <string.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <sys/stat.h>
#define ACCOUNT_SIZE 65 /* 用户名密码长度*/
#define NIC_SIZE 16 /* 网卡名最大长度 */
#define MAX_PATH 255 /* FILENAME_MAX */
#define D_TIMEOUT 8 /* 默认超时间隔 */
#define D_ECHOINTERVAL 30 /* 默认心跳间隔 */
#define D_RESTARTWAIT 15 /* 默认重连间隔 */
#define D_STARTMODE 0 /* 默认组播模式 */
#define D_DHCPMODE 0 /* 默认DHCP模式 */
#define D_DAEMONMODE 0 /* 默认daemon模式 */
#define D_MAXFAIL 0 /* 默认允许失败次数 */
static const char *D_DHCPSCRIPT = "dhclient"; /* 默认DHCP脚本 */
static const char *CFG_FILE = "/etc/mentohust.conf"; /* 配置文件 */
static const char *LOG_FILE = "/tmp/mentohust.log"; /* 日志文件 */
static const char *LOCK_FILE = "/tmp/mentohust.pid"; /* 锁文件 */
#define LOCKMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) /* 创建掩码 */
#ifndef NO_NOTIFY
#define D_SHOWNOTIFY 5 /* 默认Show Notify模式 */
int showNotify = D_SHOWNOTIFY; /* 显示通知 */
#endif
extern int bufType; /*0内置xrgsu 1内置Win 2仅文件 3文件+校验*/
extern u_char version[]; /* 版本 */
char userName[ACCOUNT_SIZE] = ""; /* 用户名 */
char password[ACCOUNT_SIZE] = ""; /* 密码 */
char nic[NIC_SIZE] = ""; /* 网卡名 */
char dataFile[MAX_PATH] = ""; /* 数据文件 */
char dhcpScript[MAX_PATH] = ""; /* DHCP脚本 */
u_int32_t ip = 0; /* 本机IP */
u_int32_t mask = 0; /* 子网掩码 */
u_int32_t gateway = 0; /* 网关 */
u_int32_t dns = 0; /* DNS */
u_int32_t pingHost = 0; /* ping */
u_char localMAC[6]; /* 本机MAC */
u_char destMAC[6]; /* 服务器MAC */
unsigned timeout = D_TIMEOUT; /* 超时间隔 */
unsigned echoInterval = D_ECHOINTERVAL; /* 心跳间隔 */
unsigned restartWait = D_RESTARTWAIT; /* 失败等待 */
unsigned startMode = D_STARTMODE; /* 组播模式 */
unsigned dhcpMode = D_DHCPMODE; /* DHCP模式 */
unsigned maxFail = D_MAXFAIL; /* 允许失败次数 */
pcap_t *hPcap = NULL; /* Pcap句柄 */
int lockfd = -1; /* 锁文件描述符 */
static int readFile(int *daemonMode); /* 读取配置文件来初始化 */
static void readArg(char argc, char **argv, int *saveFlag, int *exitFlag, int *daemonMode); /* 读取命令行参数来初始化 */
static void showHelp(const char *fileName); /* 显示帮助信息 */
static int getAdapter(); /* 查找网卡名 */
static void printConfig(); /* 显示初始化后的认证参数 */
static int openPcap(); /* 初始化pcap、设置过滤器 */
static void saveConfig(int daemonMode); /* 保存参数 */
static void checkRunning(int exitFlag, int daemonMode); /* 检测是否已运行 */
#ifndef NO_ENCODE_PASS
static const unsigned char base64Tab[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};
static const char xorRuijie[] = {"~!:?$*<(qw2e5o7i8x12c6m67s98w43d2l45we82q3iuu1z4xle23rt4oxclle34e54u6r8m"};
static int encodePass(char *dst, const char *osrc) {
unsigned char in[3], buf[70];
unsigned char *src = buf;
int sz = strlen(osrc);
int i, len;
if (sizeof(xorRuijie) < sz)
return -1;
for(i=0; i<sz; i++)
src[i] = osrc[i] ^ xorRuijie[i];
while (sz > 0) {
for (len=0, i=0; i<3; i++, sz--) {
if (sz > 0) {
len++;
in[i] = src[i];
} else in[i] = 0;
}
src += 3;
if (len) {
dst[0] = base64Tab[ in[0] >> 2 ];
dst[1] = base64Tab[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
dst[2] = len > 1 ? base64Tab[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=';
dst[3] = len > 2 ? base64Tab[ in[2] & 0x3f ] : '=';
dst += 4;
}
}
*dst = '\0';
return 0;
}
static int decodePass(char *dst, const char *src) {
unsigned esi = 0, idx = 0;
int i=0, j=0, equal=0;
for(; src[i]!='\0'; i++) {
if (src[i] == '=') {
if (++equal > 2)
return -1;
} else {
for(idx=0; base64Tab[idx]!='\0'; idx++) {
if(base64Tab[idx] == src[i])
break;
}
if (idx == 64)
return -1;
esi += idx;
}
if(i%4 == 3) {
dst[j++] = (char)(esi>>16);
if(equal < 2)
dst[j++] = (char)(esi>>8);
if(equal < 1)
dst[j++] = (char)esi;
esi = 0;
equal = 0;
}
esi <<= 6;
}
if (i%4!=0 || sizeof(xorRuijie)<j)
return -1;
for(i=0; i<j; i++)
dst[i] ^= xorRuijie[i];
dst[j] = '\0';
return 0;
}
#endif
void initConfig(int argc, char **argv)
{
int saveFlag = 0; /* 是否需要保存参数 */
int exitFlag = 0; /* 0Nothing 1退出 2重启 */
int daemonMode = D_DAEMONMODE; /* 是否后台运行 */
printf("\n欢迎使用MentoHUST\t版本: %s\n"
"Copyright (C) 2009-2010 HustMoon Studio\n"
"人到华中大,有甜亦有辣。明德厚学地,求是创新家。\n"
"Bug report to %s\n\n", VERSION, PACKAGE_BUGREPORT);
saveFlag = (readFile(&daemonMode)==0 ? 0 : 1);
readArg(argc, argv, &saveFlag, &exitFlag, &daemonMode);
#ifndef NO_NOTIFY
if (showNotify) {
seteuid(getuid());
if (load_libnotify() == -1)
showNotify = 0;
else
set_timeout(1000 * showNotify);
seteuid(0);
}
#endif
#ifndef NO_DYLOAD
if (load_libpcap() == -1) {
#ifndef NO_NOTIFY
if (showNotify)
show_notify("MentoHUST - 错误提示", "载入libpcap失败, 请检查该库文件!");
#endif
exit(EXIT_FAILURE);
}
#endif
if (nic[0] == '\0')
{
saveFlag = 1;
if (getAdapter() == -1) { /* 找不到(第一块)网卡? */
#ifndef NO_NOTIFY
if (showNotify)
show_notify("MentoHUST - 错误提示", "找不到网卡!");
#endif
exit(EXIT_FAILURE);
}
}
if (userName[0]=='\0' || password[0]=='\0') /* 未写用户名密码? */
{
saveFlag = 1;
printf("?? 请输入用户名: ");
scanf("%s", userName);
printf("?? 请输入密码: ");
scanf("%s", password);
printf("?? 请选择组播地址(0标准 1锐捷私有 2赛尔): ");
scanf("%u", &startMode);
startMode %= 3;
printf("?? 请选择DHCP方式(0不使用 1二次认证 2认证后 3认证前): ");
scanf("%u", &dhcpMode);
dhcpMode %= 4;
}
checkRunning(exitFlag, daemonMode);
if (startMode%3==2 && gateway==0) /* 赛尔且未填写网关地址 */
{
gateway = ip; /* 据说赛尔的网关是ip前三字节后一字节是2 */
((u_char *)&gateway)[3] = 0x02;
}
if (dhcpScript[0] == '\0') /* 未填写DHCP脚本 */
strcpy(dhcpScript, D_DHCPSCRIPT);
newBuffer();
printConfig();
if (fillHeader()==-1 || openPcap()==-1) { /* 获取IP、MAC打开网卡 */
#ifndef NO_NOTIFY
if (showNotify)
show_notify("MentoHUST - 错误提示", "获取MAC地址或打开网卡失败");
#endif
exit(EXIT_FAILURE);
}
if (saveFlag)
saveConfig(daemonMode);
}
static int readFile(int *daemonMode)
{
char tmp[16];
char *buf = loadFile(CFG_FILE);
if (buf == NULL)
return -1;
getString(buf, "MentoHUST", "Username", "", userName, sizeof(userName));
getString(buf, "MentoHUST", "Password", "", password, sizeof(password));
#ifndef NO_ENCODE_PASS
char pass[ACCOUNT_SIZE*4/3];
if (password[0] == '\0') {
getString(buf, "MentoHUST", "EncodePass", "", pass, sizeof(pass));
decodePass(password, pass);
} else {
encodePass(pass, password);
setString(&buf, "MentoHUST", "Password", NULL);
setString(&buf, "MentoHUST", "EncodePass", pass);
saveFile(buf, CFG_FILE);
}
#endif
getString(buf, "MentoHUST", "Nic", "", nic, sizeof(nic));
getString(buf, "MentoHUST", "Datafile", "", dataFile, sizeof(dataFile));
getString(buf, "MentoHUST", "DhcpScript", "", dhcpScript, sizeof(dhcpScript));
getString(buf, "MentoHUST", "Version", "", tmp, sizeof(tmp));
if (strlen(tmp) >= 3) {
unsigned ver[2];
if (sscanf(tmp, "%u.%u", ver, ver+1)!=EOF && ver[0]!=0) {
version[0] = ver[0];
version[1] = ver[1];
bufType = 1;
}
}
getString(buf, "MentoHUST", "IP", "255.255.255.255", tmp, sizeof(tmp));
ip = inet_addr(tmp);
getString(buf, "MentoHUST", "Mask", "255.255.255.255", tmp, sizeof(tmp));
mask = inet_addr(tmp);
getString(buf, "MentoHUST", "Gateway", "0.0.0.0", tmp, sizeof(tmp));
gateway = inet_addr(tmp);
getString(buf, "MentoHUST", "DNS", "0.0.0.0", tmp, sizeof(tmp));
dns = inet_addr(tmp);
getString(buf, "MentoHUST", "PingHost", "0.0.0.0", tmp, sizeof(tmp));
pingHost = inet_addr(tmp);
timeout = getInt(buf, "MentoHUST", "Timeout", D_TIMEOUT) % 100;
echoInterval = getInt(buf, "MentoHUST", "EchoInterval", D_ECHOINTERVAL) % 1000;
restartWait = getInt(buf, "MentoHUST", "RestartWait", D_RESTARTWAIT) % 100;
startMode = getInt(buf, "MentoHUST", "StartMode", D_STARTMODE) % 3;
dhcpMode = getInt(buf, "MentoHUST", "DhcpMode", D_DHCPMODE) % 4;
#ifndef NO_NOTIFY
showNotify = getInt(buf, "MentoHUST", "ShowNotify", D_SHOWNOTIFY) % 21;
#endif
*daemonMode = getInt(buf, "MentoHUST", "DaemonMode", D_DAEMONMODE) % 4;
maxFail = getInt(buf, "MentoHUST", "MaxFail", D_MAXFAIL);
free(buf);
return 0;
}
static void readArg(char argc, char **argv, int *saveFlag, int *exitFlag, int *daemonMode)
{
char *str, c;
int i;
for (i=1; i<argc; i++)
{
str = argv[i];
if (str[0]!='-' && str[0]!='/')
continue;
c = str[1];
if (c=='h' || c=='?' || strcmp(str, "--help")==0)
showHelp(argv[0]);
else if (c == 'w')
*saveFlag = 1;
else if (c == 'k') {
if (strlen(str) > 2)
*exitFlag = 2;
else {
*exitFlag = 1;
return;
}
} else if (strlen(str) > 2) {
if (c == 'u')
strncpy(userName, str+2, sizeof(userName)-1);
else if (c == 'p')
strncpy(password, str+2, sizeof(password)-1);
else if (c == 'n')
strncpy(nic, str+2, sizeof(nic)-1);
else if (c == 'f')
strncpy(dataFile, str+2, sizeof(dataFile)-1);
else if (c == 'c')
strncpy(dhcpScript, str+2, sizeof(dhcpScript)-1);
else if (c=='v' && strlen(str+2)>=3) {
unsigned ver[2];
if (sscanf(str+2, "%u.%u", ver, ver+1) != EOF) {
if (ver[0] == 0)
bufType = 0;
else {
version[0] = ver[0];
version[1] = ver[1];
bufType = 1;
}
}
}
else if (c == 'i')
ip = inet_addr(str+2);
else if (c == 'm')
mask = inet_addr(str+2);
else if (c == 'g')
gateway = inet_addr(str+2);
else if (c == 's')
dns = inet_addr(str+2);
else if (c == 'o')
pingHost = inet_addr(str+2);
else if (c == 't')
timeout = atoi(str+2) % 100;
else if (c == 'e')
echoInterval = atoi(str+2) % 1000;
else if (c == 'r')
restartWait = atoi(str+2) % 100;
else if (c == 'a')
startMode = atoi(str+2) % 3;
else if (c == 'd')
dhcpMode = atoi(str+2) % 4;
#ifndef NO_NOTIFY
else if (c == 'y')
showNotify = atoi(str+2) % 21;
#endif
else if (c == 'b')
*daemonMode = atoi(str+2) % 4;
else if (c == 'l')
maxFail = atoi(str+2);
}
}
}
static void showHelp(const char *fileName)
{
char *helpString =
"用法:\t%s [-选项][参数]\n"
"选项:\t-h 显示本帮助信息\n"
"\t-k -k(退出程序) 其他(重启程序)\n"
"\t-w 保存参数到配置文件\n"
"\t-u 用户名\n"
"\t-p 密码\n"
"\t-n 网卡名\n"
"\t-i IP[默认本机IP]\n"
"\t-m 子网掩码[默认本机掩码]\n"
"\t-g 网关[默认0.0.0.0]\n"
"\t-s DNS[默认0.0.0.0]\n"
"\t-o Ping主机[默认0.0.0.0,表示关闭该功能]\n"
"\t-t 认证超时(秒)[默认8]\n"
"\t-e 响应间隔(秒)[默认30]\n"
"\t-r 失败等待(秒)[默认15]\n"
"\t-l 允许失败次数[默认0表示无限制]\n"
"\t-a 组播地址: 0(标准) 1(锐捷) 2(赛尔) [默认0]\n"
"\t-d DHCP方式: 0(不使用) 1(二次认证) 2(认证后) 3(认证前) [默认0]\n"
"\t-b 是否后台运行: 0(否) 1(是,关闭输出) 2(是,保留输出) 3(是,输出到文件) [默认0]\n"
#ifndef NO_NOTIFY
"\t-y 是否显示通知: 0(否) 1~20(是) [默认5]\n"
#endif
"\t-v 客户端版本号[默认0.00表示兼容xrgsu]\n"
"\t-f 自定义数据文件[默认不使用]\n"
"\t-c DHCP脚本[默认dhclient]\n"
"例如:\t%s -uusername -ppassword -neth0 -i192.168.0.1 -m255.255.255.0 -g0.0.0.0 -s0.0.0.0 -o0.0.0.0 -t8 -e30 -r15 -a0 -d1 -b0 -v4.10 -fdefault.mpf -cdhclient\n"
"注意使用时请确保是以root权限运行\n\n";
printf(helpString, fileName, fileName);
exit(EXIT_SUCCESS);
}
static int getAdapter()
{
pcap_if_t *alldevs, *d;
int num = 0, avail = 0, i;
char errbuf[PCAP_ERRBUF_SIZE];
if (pcap_findalldevs(&alldevs, errbuf)==-1 || alldevs==NULL)
{
printf("!! 查找网卡失败: %s\n", errbuf);
return -1;
}
for (d=alldevs; d!=NULL; d=d->next)
{
num++;
if (!(d->flags & PCAP_IF_LOOPBACK) && strcmp(d->name, "any")!=0)
{
printf("** 网卡[%d]:\t%s\n", num, d->name);
avail++;
i = num;
}
}
if (avail == 0)
{
pcap_freealldevs(alldevs);
printf("!! 找不到网卡!\n");
return -1;
}
if (avail > 1)
{
printf("?? 请选择网卡[1-%d]: ", num);
scanf("%d", &i);
if (i < 1)
i = 1;
else if (i > num)
i = num;
}
printf("** 您选择了第[%d]块网卡。\n", i);
for (d=alldevs; i>1; d=d->next, i--);
strncpy(nic, d->name, sizeof(nic)-1);
pcap_freealldevs(alldevs);
return 0;
}
static void printConfig()
{
char *addr[] = {"标准", "锐捷", "赛尔"};
char *dhcp[] = {"不使用", "二次认证", "认证后", "认证前"};
printf("** 用户名:\t%s\n", userName);
/* printf("** 密码:\t%s\n", password); */
printf("** 网卡: \t%s\n", nic);
if (gateway)
printf("** 网关地址:\t%s\n", formatIP(gateway));
if (dns)
printf("** DNS地址:\t%s\n", formatIP(dns));
if (pingHost)
printf("** 智能重连:\t%s\n", formatIP(pingHost));
printf("** 认证超时:\t%u秒\n", timeout);
printf("** 响应间隔:\t%u秒\n", echoInterval);
printf("** 失败等待:\t%u秒\n", restartWait);
printf("** 允许失败:\t%u次\n", maxFail);
printf("** 组播地址:\t%s\n", addr[startMode]);
printf("** DHCP方式:\t%s\n", dhcp[dhcpMode]);
#ifndef NO_NOTIFY
if (showNotify)
printf("** 通知超时:\t%d秒\n", showNotify);
#endif
if (bufType >= 2)
printf("** 数据文件:\t%s\n", dataFile);
if (dhcpMode != 0)
printf("** DHCP脚本:\t%s\n", dhcpScript);
}
static int openPcap()
{
char buf[PCAP_ERRBUF_SIZE], *fmt;
struct bpf_program fcode;
if ((hPcap = pcap_open_live(nic, 2048, 1, 1000, buf)) == NULL)
{
printf("!! 打开网卡%s失败: %s\n", nic, buf);
return -1;
}
fmt = formatHex(localMAC, 6);
#ifndef NO_ARP
sprintf(buf, "((ether proto 0x888e and (ether dst %s or ether dst 01:80:c2:00:00:03)) "
"or ether proto 0x0806) and not ether src %s", fmt, fmt);
#else
sprintf(buf, "ether proto 0x888e and (ether dst %s or ether dst 01:80:c2:00:00:03) "
"and not ether src %s", fmt, fmt);
#endif
if (pcap_compile(hPcap, &fcode, buf, 0, 0xffffffff) == -1
|| pcap_setfilter(hPcap, &fcode) == -1)
{
printf("!! 设置pcap过滤器失败: %s\n", pcap_geterr(hPcap));
return -1;
}
pcap_freecode(&fcode);
return 0;
}
static void saveConfig(int daemonMode)
{
char *buf = loadFile(CFG_FILE);
if (buf == NULL) {
buf = (char *)malloc(1);
buf[0] = '\0';
}
setString(&buf, "MentoHUST", "DhcpScript", dhcpScript);
setString(&buf, "MentoHUST", "DataFile", dataFile);
if (bufType != 0) {
char ver[10];
sprintf(ver, "%u.%u", version[0], version[1]);
setString(&buf, "MentoHUST", "Version", ver);
} else
setString(&buf, "MentoHUST", "Version", "0.00");
#ifndef NO_NOTIFY
setInt(&buf, "MentoHUST", "ShowNotify", showNotify);
#endif
setInt(&buf, "MentoHUST", "DaemonMode", daemonMode);
setInt(&buf, "MentoHUST", "DhcpMode", dhcpMode);
setInt(&buf, "MentoHUST", "StartMode", startMode);
setInt(&buf, "MentoHUST", "MaxFail", maxFail);
setInt(&buf, "MentoHUST", "RestartWait", restartWait);
setInt(&buf, "MentoHUST", "EchoInterval", echoInterval);
setInt(&buf, "MentoHUST", "Timeout", timeout);
setString(&buf, "MentoHUST", "PingHost", formatIP(pingHost));
setString(&buf, "MentoHUST", "DNS", formatIP(dns));
setString(&buf, "MentoHUST", "Gateway", formatIP(gateway));
setString(&buf, "MentoHUST", "Mask", formatIP(mask));
setString(&buf, "MentoHUST", "IP", formatIP(ip));
setString(&buf, "MentoHUST", "Nic", nic);
#ifdef NO_ENCODE_PASS
setString(&buf, "MentoHUST", "Password", password);
#else
char pass[ACCOUNT_SIZE*4/3];
encodePass(pass, password);
setString(&buf, "MentoHUST", "EncodePass", pass);
#endif
setString(&buf, "MentoHUST", "Username", userName);
if (saveFile(buf, CFG_FILE) != 0)
printf("!! 保存认证参数到%s失败\n", CFG_FILE);
else
printf("** 认证参数已成功保存到%s.\n", CFG_FILE);
free(buf);
}
static void checkRunning(int exitFlag, int daemonMode)
{
struct flock fl;
lockfd = open (LOCK_FILE, O_RDWR|O_CREAT, LOCKMODE);
if (lockfd < 0) {
perror("!! 打开锁文件失败"); /* perror真的很好啊以前没用它真是太亏了 */
goto error_exit;
}
fl.l_start = 0;
fl.l_whence = SEEK_SET;
fl.l_len = 0;
fl.l_type = F_WRLCK;
if (fcntl(lockfd, F_GETLK, &fl) < 0) {
perror("!! 获取文件锁失败");
goto error_exit;
}
if (exitFlag) {
if (fl.l_type != F_UNLCK) {
printf(">> 已发送退出信号给MentoHUST进程(PID=%d).\n", fl.l_pid);
if (kill(fl.l_pid, SIGINT) == -1)
perror("!! 结束进程失败");
}
else
printf("!! 没有MentoHUST正在运行\n");
if (exitFlag == 1)
exit(EXIT_SUCCESS);
}
else if (fl.l_type != F_UNLCK) {
printf("!! MentoHUST已经运行(PID=%d)!\n", fl.l_pid);
exit(EXIT_FAILURE);
}
if (daemonMode) { /* 貌似我过早进入后台模式了,就给个选项保留输出或者输出到文件吧 */
printf(">> 进入后台运行模式,使用参数-k可退出认证。\n");
if (daemon(0, (daemonMode+1)%2))
perror("!! 后台运行失败");
else if (daemonMode == 3) {
freopen(LOG_FILE, "w", stdout);
freopen(LOG_FILE, "a", stderr);
}
}
fl.l_type = F_WRLCK;
fl.l_pid = getpid();
if (fcntl(lockfd, F_SETLKW, &fl) < 0) {
perror("!! 加锁失败");
goto error_exit;
}
return;
error_exit:
#ifndef NO_NOTIFY
if (showNotify)
show_notify("MentoHUST - 错误提示", "操作锁文件失败请检查是否为root权限");
#endif
exit(EXIT_FAILURE);
}

View File

@ -0,0 +1,13 @@
/*
* Copyright (C) 2009, HustMoon Studio
*
* 文件名称myconfig.h
* 摘 要:初始化认证参数
* 作 者HustMoon@BYHH
*/
#ifndef HUSTMOON_MYCONFIG_H
#define HUSTMOON_MYCONFIG_H
void initConfig(int argc, char **argv); /* 初始化配置 */
#endif

View File

@ -0,0 +1,522 @@
/* -*- Mode: C; tab-width: 4; -*- */
/*
* Copyright (C) 2009, HustMoon Studio
*
* 文件名称myfunc.c
* 摘 要:认证相关算法及方法
* 作 者HustMoon@BYHH
*/
#include "myfunc.h"
#include "md5.h"
#include "mycheck.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <arpa/inet.h>
#ifndef SIOCGIFHWADDR /* BSD、MacOS */
#include <net/if_dl.h>
#include <ifaddrs.h>
#endif
#include <sys/poll.h>
const u_char STANDARD_ADDR[] = {0x01,0x80,0xC2,0x00,0x00,0x03};
const u_char RUIJIE_ADDR[] = {0x01,0xD0,0xF8,0x00,0x00,0x03};
static const char *DATAFILE = "/etc/mentohust/"; /* 默认数据文件(目录) */
static int dataOffset; /* 抓包偏移 */
static u_int32_t echoKey = 0, echoNo = 0; /* Echo阶段所需 */
u_char *fillBuf = NULL; /* 填充包地址 */
int fillSize = 0; /* 填充包大小 */
int bufType = 0; /*0内置xrgsu 1内置Win 2仅文件 3文件+校验*/
u_char version[2]; /* 版本 */
#ifndef NO_ARP
u_int32_t rip = 0; /* 实际IP */
u_char gateMAC[6]; /* 网关MAC */
#endif
extern char password[];
extern char nic[];
extern char dataFile[];
extern u_int32_t ip, mask, gateway, dns, pingHost;
extern u_char localMAC[], destMAC[];
extern unsigned startMode, dhcpMode;
static int checkFile(); /* 检查数据文件 */
static int getVersion(); /* 获取8021x.exe版本号 */
static int getAddress(); /* 获取网络地址 */
static u_char encode(u_char base); /* 锐捷算法颠倒一个字节的8位 */
static void checkSum(u_char *buf); /* 锐捷算法,计算两个字节的检验值 */
static int setProperty(u_char type, const u_char *value, int length); /* 设置指定属性 */
static int readPacket(int type); /* 读取数据 */
static int Check(const u_char *md5Seed); /* 校验算法 */
char *formatIP(u_int32_t ip)
{
static char tmp[16];
u_char *p = (u_char *)(&ip);
sprintf(tmp, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
return tmp;
}
char *formatHex(const void *buf, int length)
{
static char hex[385];
u_char *p = (u_char *)buf;
int i;
if (length > 128)
length = 128;
for (i=0; i<length; i++)
sprintf(hex+3*i,"%02x:", p[i]);
hex[3*length-1] = '\0';
return hex;
}
static int checkFile() {
u_char Buf[16], *buf=Buf;
FILE *fp = NULL;
if ((fp=fopen(dataFile, "rb")) == NULL)
goto fileError;
if (fread(buf, 16, 1, fp)<1 || memcmp(buf, "HUST", 4)!=0) {
fclose(fp);
goto fileError;
}
dataOffset = (int)LTOBL(*(u_int32_t *)buf ^ *(u_int32_t *)(buf + 8)) + 16;
fseek(fp, 0, SEEK_END);
fillSize = ftell(fp);
fclose(fp);
if (dataOffset < 16)
goto fileError;
fillSize = (fillSize - dataOffset) / 2 + 0x17;
if (fillSize<0x80 || fillSize>0x397)
goto fileError;
return 0;
fileError:
if (dataFile[strlen(dataFile)-1] != '/')
printf("!! 所选文件%s无效改用内置数据认证。\n", dataFile);
return -1;
}
static int getVersion() {
char file[0x100], *p;
DWORD ver;
strcpy(file, dataFile);
if ((p=strrchr(file, '/')+1) == (void *)1)
p = file;
strcpy(p, "8021x.exe");
if ((ver=getVer(file)) == (DWORD)-1)
return -1;
p = (char *)&ver;
version[0] = p[2];
version[1] = p[0];
bufType = 1;
return 0;
}
void newBuffer()
{
if (dataFile[0] == '\0')
strcpy(dataFile, DATAFILE);
getVersion();
if (checkFile() == 0)
bufType += 2;
else fillSize = (bufType==0 ? 0x80 : 0x1d7);
fillBuf = (u_char *)malloc(fillSize);
}
static int getAddress()
{
struct ifreq ifr;
#ifndef SIOCGIFHWADDR /* BSD、MacOS */
struct ifaddrs *ifap, *p = NULL;
struct sockaddr_dl *sdl;
#endif
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
{
printf("!! 创建套接字失败!\n");
return -1;
}
strcpy(ifr.ifr_name, nic);
#ifdef SIOCGIFHWADDR
if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
goto getMACError;
memcpy(localMAC, ifr.ifr_hwaddr.sa_data, 6);
#else
if (getifaddrs(&ifap) == 0)
{
for (p=ifap; p; p=p->ifa_next)
{
if (p->ifa_name && strcmp(p->ifa_name, nic)==0)
{
sdl = (struct sockaddr_dl *)p->ifa_addr;
memcpy(localMAC, sdl->sdl_data + sdl->sdl_nlen, 6);
break;
}
}
freeifaddrs(ifap);
}
if (p == NULL)
goto getMACError;
#endif
if (startMode == 0)
memcpy(destMAC, STANDARD_ADDR, 6);
else if (startMode == 1)
memcpy(destMAC, RUIJIE_ADDR, 6);
#ifndef NO_ARP
gateMAC[0] = 0xFE;
if (ioctl(sock, SIOCGIFADDR, &ifr) < 0)
printf("!! 在网卡%s上获取IP失败!\n", nic);
else {
rip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
if (gateway!=0 && (startMode%3!=2 || ((u_char *)&gateway)[3]!=0x02))
gateMAC[0] = 0xFF;
}
if (dhcpMode!=0 || ip==-1)
ip = rip;
#else
if (dhcpMode!=0 || ip==-1) {
if (ioctl(sock, SIOCGIFADDR, &ifr) < 0)
printf("!! 在网卡%s上获取IP失败!\n", nic);
else
ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
}
#endif
if (dhcpMode!=0 || mask==-1) {
if (ioctl(sock, SIOCGIFNETMASK, &ifr) < 0)
printf("!! 在网卡%s上获取子网掩码失败!\n", nic);
else
mask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
}
close(sock);
printf("** 本机MAC:\t%s\n", formatHex(localMAC, 6));
printf("** 使用IP:\t%s\n", formatIP(ip));
printf("** 子网掩码:\t%s\n", formatIP(mask));
return 0;
getMACError:
close(sock);
printf("!! 在网卡%s上获取MAC失败!\n", nic);
return -1;
}
static u_char encode(u_char base) /* 算法将一个字节的8位颠倒并取反 */
{
u_char result = 0;
int i;
for (i=0; i<8; i++)
{
result <<= 1;
result |= base&0x01;
base >>= 1;
}
return ~result;
}
static void checkSum(u_char *buf) /* 算法计算两个字节的checksum */
{
u_char table[] =
{
0x00,0x00,0x21,0x10,0x42,0x20,0x63,0x30,0x84,0x40,0xA5,0x50,0xC6,0x60,0xE7,0x70,
0x08,0x81,0x29,0x91,0x4A,0xA1,0x6B,0xB1,0x8C,0xC1,0xAD,0xD1,0xCE,0xE1,0xEF,0xF1,
0x31,0x12,0x10,0x02,0x73,0x32,0x52,0x22,0xB5,0x52,0x94,0x42,0xF7,0x72,0xD6,0x62,
0x39,0x93,0x18,0x83,0x7B,0xB3,0x5A,0xA3,0xBD,0xD3,0x9C,0xC3,0xFF,0xF3,0xDE,0xE3,
0x62,0x24,0x43,0x34,0x20,0x04,0x01,0x14,0xE6,0x64,0xC7,0x74,0xA4,0x44,0x85,0x54,
0x6A,0xA5,0x4B,0xB5,0x28,0x85,0x09,0x95,0xEE,0xE5,0xCF,0xF5,0xAC,0xC5,0x8D,0xD5,
0x53,0x36,0x72,0x26,0x11,0x16,0x30,0x06,0xD7,0x76,0xF6,0x66,0x95,0x56,0xB4,0x46,
0x5B,0xB7,0x7A,0xA7,0x19,0x97,0x38,0x87,0xDF,0xF7,0xFE,0xE7,0x9D,0xD7,0xBC,0xC7,
0xC4,0x48,0xE5,0x58,0x86,0x68,0xA7,0x78,0x40,0x08,0x61,0x18,0x02,0x28,0x23,0x38,
0xCC,0xC9,0xED,0xD9,0x8E,0xE9,0xAF,0xF9,0x48,0x89,0x69,0x99,0x0A,0xA9,0x2B,0xB9,
0xF5,0x5A,0xD4,0x4A,0xB7,0x7A,0x96,0x6A,0x71,0x1A,0x50,0x0A,0x33,0x3A,0x12,0x2A,
0xFD,0xDB,0xDC,0xCB,0xBF,0xFB,0x9E,0xEB,0x79,0x9B,0x58,0x8B,0x3B,0xBB,0x1A,0xAB,
0xA6,0x6C,0x87,0x7C,0xE4,0x4C,0xC5,0x5C,0x22,0x2C,0x03,0x3C,0x60,0x0C,0x41,0x1C,
0xAE,0xED,0x8F,0xFD,0xEC,0xCD,0xCD,0xDD,0x2A,0xAD,0x0B,0xBD,0x68,0x8D,0x49,0x9D,
0x97,0x7E,0xB6,0x6E,0xD5,0x5E,0xF4,0x4E,0x13,0x3E,0x32,0x2E,0x51,0x1E,0x70,0x0E,
0x9F,0xFF,0xBE,0xEF,0xDD,0xDF,0xFC,0xCF,0x1B,0xBF,0x3A,0xAF,0x59,0x9F,0x78,0x8F,
0x88,0x91,0xA9,0x81,0xCA,0xB1,0xEB,0xA1,0x0C,0xD1,0x2D,0xC1,0x4E,0xF1,0x6F,0xE1,
0x80,0x10,0xA1,0x00,0xC2,0x30,0xE3,0x20,0x04,0x50,0x25,0x40,0x46,0x70,0x67,0x60,
0xB9,0x83,0x98,0x93,0xFB,0xA3,0xDA,0xB3,0x3D,0xC3,0x1C,0xD3,0x7F,0xE3,0x5E,0xF3,
0xB1,0x02,0x90,0x12,0xF3,0x22,0xD2,0x32,0x35,0x42,0x14,0x52,0x77,0x62,0x56,0x72,
0xEA,0xB5,0xCB,0xA5,0xA8,0x95,0x89,0x85,0x6E,0xF5,0x4F,0xE5,0x2C,0xD5,0x0D,0xC5,
0xE2,0x34,0xC3,0x24,0xA0,0x14,0x81,0x04,0x66,0x74,0x47,0x64,0x24,0x54,0x05,0x44,
0xDB,0xA7,0xFA,0xB7,0x99,0x87,0xB8,0x97,0x5F,0xE7,0x7E,0xF7,0x1D,0xC7,0x3C,0xD7,
0xD3,0x26,0xF2,0x36,0x91,0x06,0xB0,0x16,0x57,0x66,0x76,0x76,0x15,0x46,0x34,0x56,
0x4C,0xD9,0x6D,0xC9,0x0E,0xF9,0x2F,0xE9,0xC8,0x99,0xE9,0x89,0x8A,0xB9,0xAB,0xA9,
0x44,0x58,0x65,0x48,0x06,0x78,0x27,0x68,0xC0,0x18,0xE1,0x08,0x82,0x38,0xA3,0x28,
0x7D,0xCB,0x5C,0xDB,0x3F,0xEB,0x1E,0xFB,0xF9,0x8B,0xD8,0x9B,0xBB,0xAB,0x9A,0xBB,
0x75,0x4A,0x54,0x5A,0x37,0x6A,0x16,0x7A,0xF1,0x0A,0xD0,0x1A,0xB3,0x2A,0x92,0x3A,
0x2E,0xFD,0x0F,0xED,0x6C,0xDD,0x4D,0xCD,0xAA,0xBD,0x8B,0xAD,0xE8,0x9D,0xC9,0x8D,
0x26,0x7C,0x07,0x6C,0x64,0x5C,0x45,0x4C,0xA2,0x3C,0x83,0x2C,0xE0,0x1C,0xC1,0x0C,
0x1F,0xEF,0x3E,0xFF,0x5D,0xCF,0x7C,0xDF,0x9B,0xAF,0xBA,0xBF,0xD9,0x8F,0xF8,0x9F,
0x17,0x6E,0x36,0x7E,0x55,0x4E,0x74,0x5E,0x93,0x2E,0xB2,0x3E,0xD1,0x0E,0xF0,0x1E
};
u_char *checkSum = buf + 0x15;
int i, index;
for (i=0; i<0x15; i++)
{
index = checkSum[0] ^ buf[i];
checkSum[0] = checkSum[1] ^ table[index*2+1];
checkSum[1] = table[index*2];
}
for (i=0; i<0x17; i++)
buf[i] = encode(buf[i]);
}
int fillHeader()
{
if (getAddress() == -1)
return -1;
memset(fillBuf, 0, fillSize);
fillBuf[0x02] = 0x13;
fillBuf[0x03] = 0x11;
if (dhcpMode != 0)
fillBuf[0x04] = 0x01; /* DHCP位使用1、不使用0 */
memcpy(fillBuf+0x05, &ip, 4);
memcpy(fillBuf+0x09, &mask, 4);
memcpy(fillBuf+0x0D, &gateway, 4);
memcpy(fillBuf+0x11, &dns, 4);
checkSum(fillBuf);
return 0;
}
static int setProperty(u_char type, const u_char *value, int length)
{
u_char *p = fillBuf+0x46, *end = fillBuf+fillSize-length-8; /* 形如1a 28 00 00 13 11 17 22至少8个字节 */
while (p < end)
{
if (*p == 0x1a) /* 有些老版本没有前两个字节包括xrgsu */
p += 2;
if (p[4] == type)
{
memcpy(p+4+p[5]-length, value, length);
return 0;
}
p += p[5] + 4;
}
return -1;
}
static int readPacket(int type)
{
u_char dhcp[] = {0x00};
FILE *fp = fopen(dataFile, "rb");
if (fp == NULL)
goto fileError;
type %= 2; /* 偶数读Start包奇数读Md5包 */
fseek(fp, dataOffset+(fillSize-0x17)*type, SEEK_SET);
if (fread(fillBuf+0x17, fillSize-0x17, 1, fp) < 1) /* 前0x17字节是地址及校验值 */
{
fclose(fp);
goto fileError;
}
fclose(fp);
if (dhcpMode == 1) /* 二次认证第一次 */
dhcp[0] = 0x01;
setProperty(0x18, dhcp, 1);
setProperty(0x2D, localMAC, 6);
if (bufType == 3)
memcpy(fillBuf+0x3b, version, 2);
return 0;
fileError:
printf("!! 所选文件%s无效改用内置数据认证。\n", dataFile);
bufType -= 2;
if (bufType==1 && fillSize<0x1d7) {
free(fillBuf);
fillSize = 0x1d7;
fillBuf = (u_char *)malloc(fillSize);
}
return -1;
}
void fillStartPacket()
{
if (bufType <= 1) { /* 使用xrgsu */
const u_char packet0[] = {
0x00,0x00,0x13,0x11,0x38,0x30,0x32,0x31,0x78,0x2e,0x65,0x78,0x65,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x13,0x11,0x00,0x28,0x1a,
0x28,0x00,0x00,0x13,0x11,0x17,0x22,0x91,0x66,0x64,0x93,0x67,0x60,0x65,0x62,0x62,
0x94,0x61,0x69,0x67,0x63,0x91,0x93,0x92,0x68,0x66,0x93,0x91,0x66,0x95,0x65,0xaa,
0xdc,0x64,0x98,0x96,0x6a,0x9d,0x66,0x00,0x00,0x13,0x11,0x18,0x06,0x02,0x00,0x00
};
const u_char packet1[] = {
0x00,0x00,0x13,0x11,0x38,0x30,0x32,0x31,0x78,0x2e,0x65,0x78,0x65,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x04,0x0a,0x00,0x02,0x00,0x00,0x00,0x13,0x11,0x01,0x8c,0x1a,
0x28,0x00,0x00,0x13,0x11,0x17,0x22,0x36,0x38,0x44,0x43,0x31,0x32,0x33,0x42,0x37,
0x45,0x42,0x32,0x33,0x39,0x46,0x32,0x33,0x41,0x38,0x43,0x30,0x30,0x30,0x33,0x38,
0x38,0x34,0x39,0x38,0x36,0x33,0x39,0x1a,0x0c,0x00,0x00,0x13,0x11,0x18,0x06,0x00,
0x00,0x00,0x00,0x1a,0x0e,0x00,0x00,0x13,0x11,0x2d,0x08,0x00,0x00,0x00,0x00,0x00,
0x00,0x1a,0x08,0x00,0x00,0x13,0x11,0x2f,0x02,0x1a,0x09,0x00,0x00,0x13,0x11,0x35,
0x03,0x01,0x1a,0x18,0x00,0x00,0x13,0x11,0x36,0x12,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0x18,0x00,0x00,0x13,0x11,
0x38,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x86,
0x13,0x4c,0x1a,0x88,0x00,0x00,0x13,0x11,0x4d,0x82,0x36,0x38,0x64,0x63,0x31,0x32,
0x33,0x62,0x30,0x37,0x65,0x62,0x32,0x33,0x39,0x66,0x32,0x33,0x61,0x38,0x30,0x64,
0x63,0x66,0x32,0x35,0x38,0x37,0x35,0x64,0x30,0x35,0x37,0x37,0x30,0x63,0x37,0x32,
0x31,0x65,0x34,0x35,0x36,0x34,0x35,0x65,0x35,0x33,0x37,0x61,0x62,0x33,0x35,0x31,
0x62,0x62,0x36,0x33,0x31,0x35,0x35,0x61,0x65,0x31,0x36,0x32,0x36,0x31,0x36,0x37,
0x65,0x62,0x30,0x39,0x32,0x32,0x33,0x65,0x32,0x61,0x30,0x61,0x37,0x38,0x30,0x33,
0x31,0x31,0x36,0x31,0x61,0x63,0x30,0x39,0x64,0x61,0x32,0x64,0x63,0x30,0x37,0x33,
0x36,0x39,0x33,0x61,0x34,0x66,0x35,0x61,0x32,0x39,0x32,0x38,0x36,0x37,0x35,0x31,
0x66,0x39,0x37,0x66,0x34,0x64,0x30,0x34,0x36,0x38,0x1a,0x28,0x00,0x00,0x13,0x11,
0x39,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x1a,0x48,0x00,0x00,0x13,0x11,0x54,0x42,0x48,0x55,0x53,0x54,0x4d,0x4f,
0x4f,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0x08,0x00,0x00,0x13,0x11,
0x55,0x02,0x1a,0x09,0x00,0x00,0x13,0x11,0x62,0x03,0x00,0x00,0x00,0x00,0x00,0x00
};
u_char dhcp[] = {0x00};
if (dhcpMode == 1) /* 二次认证第一次 */
dhcp[0] = 0x01;
if (bufType == 1) {
memcpy(fillBuf+0x17, packet1, sizeof(packet1));
memcpy(fillBuf+0x3b, version, 2);
} else
memcpy(fillBuf+0x17, packet0, sizeof(packet0));
setProperty(0x18, dhcp, 1);
setProperty(0x2D, localMAC, 6);
}
else if (readPacket(0) == -1) /* 读取数据失败就用默认的填充 */
fillStartPacket();
}
void fillMd5Packet(const u_char *md5Seed)
{
if (bufType <= 1) { /* 不使用数据包? */
/* xrgsu的Md5包与Start包只有一个字节的差异若以其他版本为基础可进一步区别对待 */
fillStartPacket();
if (bufType == 1)
Check(md5Seed);
} else {
if (readPacket(1) == -1)
fillMd5Packet(md5Seed);
else
Check(md5Seed);
}
echoNo = 0x0000102B; /* 初始化echoNo */
}
static int Check(const u_char *md5Seed) /* 客户端校验 */
{
char final_str[129];
int value;
printf("** 客户端版本:\t%d.%d\n", fillBuf[0x3B], fillBuf[0x3C]);
printf("** MD5种子:\t%s\n", formatHex(md5Seed, 16));
value = check_init(dataFile);
if (value == -1) {
printf("!! 缺少8021x.exe信息客户端校验无法继续\n");
return 1;
}
V2_check(md5Seed, final_str);
printf("** V2校验值:\t%s\n", final_str);
setProperty(0x17, (u_char *)final_str, 32);
check_free();
return 0;
}
void fillEchoPacket(u_char *echoBuf)
{
int i;
u_int32_t dd1=htonl(echoKey + echoNo), dd2=htonl(echoNo);
u_char *bt1=(u_char *)&dd1, *bt2=(u_char *)&dd2;
echoNo++;
for (i=0; i<4; i++)
{
echoBuf[0x18+i] = encode(bt1[i]);
echoBuf[0x22+i] = encode(bt2[i]);
}
}
void getEchoKey(const u_char *capBuf)
{
int i, offset = 0x1c+capBuf[0x1b]+0x69+24; /* 通过比较了大量抓包,通用的提取点就是这样的 */
u_char *base;
echoKey = ntohl(*(u_int32_t *)(capBuf+offset));
base = (u_char *)(&echoKey);
for (i=0; i<4; i++)
base[i] = encode(base[i]);
}
u_char *checkPass(u_char id, const u_char *md5Seed, int seedLen)
{
u_char md5Src[80];
int md5Len = strlen(password);
md5Src[0] = id;
memcpy(md5Src+1, password, md5Len);
md5Len++;
if (startMode % 3 == 2) /* 赛尔? */
{
memcpy(md5Src+md5Len, "xxghlmxhzb", 10);
md5Len += 10;
}
memcpy(md5Src+md5Len, md5Seed, seedLen);
md5Len += seedLen;
return ComputeHash(md5Src, md5Len);
}
void fillCernetAddr(u_char *buf)
{
memcpy(buf+0x18, &ip, 4);
memcpy(buf+0x1C, &mask, 4);
memcpy(buf+0x20, &gateway, 4);
memset(buf+0x24, 0, 4); /* memcpy(buf+0x24, &dns, 4); */
}
int isOnline()
{
u_char echoPacket[] =
{
0x08,0x00,0x61,0xb2,0x02,0x00,0x01,0x00,0x57,0x65,0x6C,0x63,0x6F,0x6D,0x65,0x20,
0x74,0x6F,0x20,0x4D,0x65,0x6E,0x74,0x6F,0x48,0x55,0x53,0x54,0x21,0x0A,0x43,0x6F,
0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x63,0x29,0x20,0x32,0x30,0x30,0x39,
0x20,0x48,0x75,0x73,0x74,0x4D,0x6F,0x6F,0x6E,0x20,0x53,0x74,0x75,0x64,0x69,0x6F
};
int sock=-1, rtVal, t;
struct pollfd pfd;
struct sockaddr_in dest;
if (pingHost == 0)
return 0;
memset(&dest, 0, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = pingHost;
if ((sock=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
goto pingError;
pfd.fd = sock;
pfd.events = POLLIN;
for (t=1; t<=3; t++) {
if (sendto(sock, echoPacket, sizeof(echoPacket), 0,
(struct sockaddr *)&dest, sizeof(dest)) < 0)
goto pingError;
rtVal = poll(&pfd, 1, t*1000);
if (rtVal == -1)
goto pingError;
if (rtVal > 0) {
close(sock);
return 0;
}
}
close(sock);
return -1;
pingError:
perror("!! Ping主机出错关闭该功能");
if (sock != -1)
close(sock);
pingHost = 0;
return 0;
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (C) 2009, HustMoon Studio
*
* 文件名称myfunc.h
* 摘 要:认证相关算法及方法
* 作 者HustMoon@BYHH
*/
#ifndef HUSTMOON_MYFUNC_H
#define HUSTMOON_MYFUNC_H
#include <sys/types.h>
char *formatIP(u_int32_t ip); /* 格式化IP */
char *formatHex(const void *buf, int length); /* 格式化成十六进制形式 */
void newBuffer(); /* 检测数据文件有效性并分配内存 */
int fillHeader(); /* 填充网络地址及校验值部分 */
void fillStartPacket(); /* 填充Start包 */
void fillMd5Packet(const u_char *md5Seed); /* 填充Md5包 */
void fillEchoPacket(u_char *buf); /* 填充Echo包 */
void getEchoKey(const u_char *capBuf); /* 获取EchoKey */
u_char *checkPass(u_char id, const u_char *md5Seed, int seedLen); /* 计算密码的md5 */
void fillCernetAddr(u_char *buf); /* 填充赛尔网络地址 */
int isOnline(); /* ping主机判断是否掉线 */
#endif

View File

@ -0,0 +1,203 @@
/* -*- Mode: C; tab-width: 4; -*- */
/*
* Copyright (C) 2009, HustMoon Studio
*
* 文件名称myini.c
* 摘 要读取ini文件+写入ini文件
* 作 者HustMoon@BYHH
* 修 改2009.10.8
*/
#include "myini.h"
#include <stdio.h>
#include <string.h>
#define NOT_COMMENT(c) (c!=';' && c!='#') /* 不是注释行 */
#ifndef strnicmp
#define strnicmp strncasecmp
#endif
static void getLine(const char *buf, int inStart, int *lineStart, int *lineEnd);
static int findKey(const char *buf, const char *section, const char *key,
int *sectionStart, int *valueStart, unsigned long *valueSize);
static int getSection(const char *buf, int inStart);
char *loadFile(const char *fileName)
{
FILE *fp = NULL;
long size = 0;
char *buf = NULL;
if ((fp=fopen(fileName, "rb")) == NULL)
return NULL;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
rewind(fp);
buf = (char *)malloc(size+1);
buf[size] = '\0';
if (fread(buf, size, 1, fp) < 1)
{
free(buf);
buf = NULL;
}
fclose(fp);
return buf;
}
static void getLine(const char *buf, int inStart, int *lineStart, int *lineEnd)
{
int start, end;
for (start=inStart; buf[start]==' ' || buf[start]=='\t' || buf[start]=='\r' || buf[start]=='\n'; start++);
for (end=start; buf[end]!='\r' && buf[end]!='\n' && buf[end]!='\0'; end++);
*lineStart = start;
*lineEnd = end;
}
static int findKey(const char *buf, const char *section, const char *key,
int *sectionStart, int *valueStart, unsigned long *valueSize)
{
int lineStart, lineEnd, i;
for (*sectionStart=-1, lineEnd=0; buf[lineEnd]!='\0'; )
{
getLine(buf, lineEnd, &lineStart, &lineEnd);
if (buf[lineStart] == '[')
{
for (i=++lineStart; i<lineEnd && buf[i]!=']'; i++);
if (i<lineEnd && strnicmp(buf+lineStart, section, i-lineStart)==0) /* 找到Section */
{
*sectionStart = lineStart-1;
if (key == NULL)
return -1;
}
else if (*sectionStart != -1) /* 找到Section但未找到Key */
return -1;
}
else if (*sectionStart!=-1 && NOT_COMMENT(buf[lineStart])) /* 找到Section且该行不是注释 */
{
for (i=lineStart+1; i<lineEnd && buf[i]!='='; i++);
if (i<lineEnd && strnicmp(buf+lineStart, key, i-lineStart)==0) /* 找到Key */
{
*valueStart = i + 1;
*valueSize = lineEnd - *valueStart;
return 0;
}
}
}
return -1;
}
int getString(const char *buf, const char *section, const char *key,
const char *defaultValue, char *value, unsigned long size)
{
int sectionStart, valueStart;
unsigned long valueSize;
if (findKey(buf, section, key, &sectionStart, &valueStart, &valueSize)!=0 || valueSize==0) /* 未找到? */
{
strncpy(value, defaultValue, size);
return -1;
}
if (size-1 < valueSize) /* 找到但太长? */
valueSize = size - 1;
memset(value, 0, size);
strncpy(value, buf+valueStart, valueSize);
return 0;
}
int getInt(const char *buf, const char *section, const char *key, int defaultValue)
{
char value[21] = {0};
getString(buf, section, key, "", value, sizeof(value));
if (value[0] == '\0') /* 找不到或找到但为空? */
return defaultValue;
return atoi(value);
}
void setString(char **buf, const char *section, const char *key, const char *value)
{
int sectionStart, valueStart;
unsigned long valueSize;
char *newBuf = NULL;
if (findKey(*buf, section, key, &sectionStart, &valueStart, &valueSize) == 0) /* 找到key */
{
if (value == NULL) /* 删除key? */
memmove(*buf+valueStart-strlen(key)-1, *buf+valueStart+valueSize,
strlen(*buf)+1-valueStart-valueSize);
else /* 修改key */
{
newBuf = (char *)malloc(strlen(*buf)-valueSize+strlen(value)+1);
memcpy(newBuf, *buf, valueStart);
strcpy(newBuf+valueStart, value);
strcpy(newBuf+valueStart+strlen(value), *buf+valueStart+valueSize);
free(*buf);
*buf = newBuf;
}
}
else if (sectionStart != -1) /* 找到section找不到key */
{
if (key == NULL) /* 删除section? */
{
valueStart = getSection(*buf, sectionStart+3);
if (valueStart <= sectionStart) /* 后面没有section */
(*buf)[sectionStart] = '\0';
else
memmove(*buf+sectionStart, *buf+valueStart, strlen(*buf)+1-valueStart);
}
else if (value != NULL) /* 不是要删除key */
{
newBuf = (char *)malloc(strlen(*buf)+strlen(key)+strlen(value)+4);
valueSize = sectionStart+strlen(section)+2;
memcpy(newBuf, *buf, valueSize);
sprintf(newBuf+valueSize, "\n%s=%s", key, value);
strcpy(newBuf+strlen(newBuf), *buf+valueSize);
free(*buf);
*buf = newBuf;
}
}
else /* 找不到section? */
{
if (key!=NULL && value!=NULL)
{
newBuf = (char *)malloc(strlen(*buf)+strlen(section)+strlen(key)+strlen(value)+8);
strcpy(newBuf, *buf);
sprintf(newBuf+strlen(newBuf), "\n[%s]\n%s=%s", section, key, value);
free(*buf);
*buf = newBuf;
}
}
}
static int getSection(const char *buf, int inStart)
{
int lineStart, lineEnd, i;
for (lineEnd=inStart; buf[lineEnd]!='\0'; )
{
getLine(buf, lineEnd, &lineStart, &lineEnd);
if (buf[lineStart] == '[')
{
for (i=lineStart+1; i<lineEnd && buf[i]!=']'; i++);
if (i < lineEnd)
return lineStart;
}
}
return -1;
}
void setInt(char **buf, const char *section, const char *key, int value)
{
char svalue[21];
sprintf(svalue, "%d", value);
setString(buf, section, key, svalue);
}
int saveFile(const char *buf, const char *fileName)
{
FILE *fp;
int result;
if ((fp=fopen(fileName, "wb")) == NULL)
return -1;
result = fwrite(buf, strlen(buf), 1, fp)<1 ? -1 : 0;
fclose(fp);
return result;
}

View File

@ -0,0 +1,32 @@
/* -*- Mode: C; tab-width: 4; -*- */
/*
* Copyright (C) 2009, HustMoon Studio
*
* 文件名称myini.h
* 摘 要读取ini文件+写入ini文件
* 作 者HustMoon@BYHH
* 修 改2009.10.8
*/
#ifndef HUSTMOON_MYINI_H
#define HUSTMOON_MYINI_H
#include <stdlib.h> /* for free() */
#ifdef __cplusplus
extern "C"
{
#endif
char *loadFile(const char *fileName); /* 读取文件 */
int getString(const char *buf, const char *section, const char *key,
const char *defaultValue, char *value, unsigned long size); /* 读取字符串 */
int getInt(const char *buf, const char *section, const char *key, int defaultValue); /* 读取整数 */
void setString(char **buf, const char *section, const char *key, const char *value); /* 设置字符串value=NULL则删除keykey=NULL则删除section */
void setInt(char **buf, const char *section, const char *key, int value); /* 设置整数 */
int saveFile(const char *buf, const char *fileName); /* 写入文件 */
#ifdef __cplusplus
};
#endif
#endif

View File

@ -0,0 +1,331 @@
/* -*- Mode: C; tab-width: 4; -*- */
/*
* Copyright (C) 2009, HustMoon Studio
*
* 文件名称mystate.c
* 摘 要:改变认证状态
* 作 者HustMoon@BYHH
* 邮 箱www.ehust@gmail.com
*/
#include "mystate.h"
#include "myfunc.h"
#include "dlfunc.h"
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#define MAX_SEND_COUNT 3 /* 最大超时次数 */
volatile int state = ID_DISCONNECT; /* 认证状态 */
const u_char *capBuf = NULL; /* 抓到的包 */
static u_char sendPacket[0x3E8]; /* 用来发送的包 */
static int sendCount = 0; /* 同一阶段发包计数 */
extern const u_char STANDARD_ADDR[];
extern char userName[];
extern unsigned startMode;
extern unsigned dhcpMode;
extern u_char localMAC[], destMAC[];
extern unsigned timeout;
extern unsigned echoInterval;
extern unsigned restartWait;
extern char dhcpScript[];
extern pcap_t *hPcap;
extern u_char *fillBuf;
extern unsigned fillSize;
extern u_int32_t pingHost;
#ifndef NO_ARP
extern u_int32_t rip, gateway;
extern u_char gateMAC[];
static void sendArpPacket(); /* ARP监视 */
#endif
static void setTimer(unsigned interval); /* 设置定时器 */
static int renewIP(); /* 更新IP */
static void fillEtherAddr(u_int32_t protocol); /* 填充MAC地址和协议 */
static int sendStartPacket(); /* 发送Start包 */
static int sendIdentityPacket(); /* 发送Identity包 */
static int sendChallengePacket(); /* 发送Md5 Challenge包 */
static int sendEchoPacket(); /* 发送心跳包 */
static int sendLogoffPacket(); /* 发送退出包 */
static int waitEchoPacket(); /* 等候响应包 */
static void setTimer(unsigned interval) /* 设置定时器 */
{
struct itimerval timer;
timer.it_value.tv_sec = interval;
timer.it_value.tv_usec = 0;
timer.it_interval.tv_sec = interval;
timer.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &timer, NULL);
}
int switchState(int type)
{
if (state == type) /* 跟上次是同一状态? */
sendCount++;
else
{
state = type;
sendCount = 0;
}
if (sendCount>=MAX_SEND_COUNT && type!=ID_ECHO) /* 超时太多次? */
{
switch (type)
{
case ID_START:
printf(">> 找不到服务器,重启认证!\n");
break;
case ID_IDENTITY:
printf(">> 发送用户名超时,重启认证!\n");
break;
case ID_CHALLENGE:
printf(">> 发送密码超时,重启认证!\n");
break;
case ID_WAITECHO:
printf(">> 等候响应包超时,自行响应!\n");
return switchState(ID_ECHO);
}
return restart();
}
switch (type)
{
case ID_DHCP:
return renewIP();
case ID_START:
return sendStartPacket();
case ID_IDENTITY:
return sendIdentityPacket();
case ID_CHALLENGE:
return sendChallengePacket();
case ID_WAITECHO: /* 塞尔的就不ping了不好计时 */
return waitEchoPacket();
case ID_ECHO:
if (pingHost && sendCount*echoInterval > 60) { /* 1分钟左右 */
if (isOnline() == -1) {
printf(">> 认证掉线,开始重连!\n");
return switchState(ID_START);
}
sendCount = 1;
}
#ifndef NO_ARP
if (gateMAC[0] != 0xFE)
sendArpPacket();
#endif
return sendEchoPacket();
case ID_DISCONNECT:
return sendLogoffPacket();
}
return 0;
}
int restart()
{
if (startMode >= 3) /* 标记服务器地址为未获取 */
startMode -= 3;
state = ID_START;
sendCount = -1;
setTimer(restartWait); /* restartWait秒后或者服务器请求后重启认证 */
return 0;
}
static int renewIP()
{
setTimer(0); /* 取消定时器 */
printf(">> 正在获取IP...\n");
system(dhcpScript);
printf(">> 操作结束。\n");
dhcpMode += 3; /* 标记为已获取123变为4565不需再认证*/
if (fillHeader() == -1)
exit(EXIT_FAILURE);
if (dhcpMode == 5)
return switchState(ID_ECHO);
return switchState(ID_START);
}
static void fillEtherAddr(u_int32_t protocol)
{
memset(sendPacket, 0, 0x3E8);
memcpy(sendPacket, destMAC, 6);
memcpy(sendPacket+0x06, localMAC, 6);
*(u_int32_t *)(sendPacket+0x0C) = htonl(protocol);
}
static int sendStartPacket()
{
if (startMode%3 == 2) /* 赛尔 */
{
if (sendCount == 0)
{
printf(">> 寻找服务器...\n");
memcpy(sendPacket, STANDARD_ADDR, 6);
memcpy(sendPacket+0x06, localMAC, 6);
*(u_int32_t *)(sendPacket+0x0C) = htonl(0x888E0101);
*(u_int16_t *)(sendPacket+0x10) = 0;
memset(sendPacket+0x12, 0xa5, 42);
setTimer(timeout);
}
return pcap_sendpacket(hPcap, sendPacket, 60);
}
if (sendCount == 0)
{
printf(">> 寻找服务器...\n");
fillStartPacket();
fillEtherAddr(0x888E0101);
memcpy(sendPacket+0x12, fillBuf, fillSize);
setTimer(timeout);
}
return pcap_sendpacket(hPcap, sendPacket, 0x3E8);
}
static int sendIdentityPacket()
{
int nameLen = strlen(userName);
if (startMode%3 == 2) /* 赛尔 */
{
if (sendCount == 0)
{
printf(">> 发送用户名...\n");
*(u_int16_t *)(sendPacket+0x0E) = htons(0x0100);
*(u_int16_t *)(sendPacket+0x10) = *(u_int16_t *)(sendPacket+0x14) = htons(nameLen+30);
sendPacket[0x12] = 0x02;
sendPacket[0x16] = 0x01;
sendPacket[0x17] = 0x01;
fillCernetAddr(sendPacket);
memcpy(sendPacket+0x28, "03.02.05", 8);
memcpy(sendPacket+0x30, userName, nameLen);
setTimer(timeout);
}
sendPacket[0x13] = capBuf[0x13];
return pcap_sendpacket(hPcap, sendPacket, nameLen+48);
}
if (sendCount == 0)
{
printf(">> 发送用户名...\n");
fillEtherAddr(0x888E0100);
nameLen = strlen(userName);
*(u_int16_t *)(sendPacket+0x14) = *(u_int16_t *)(sendPacket+0x10) = htons(nameLen+5);
sendPacket[0x12] = 0x02;
sendPacket[0x13] = capBuf[0x13];
sendPacket[0x16] = 0x01;
memcpy(sendPacket+0x17, userName, nameLen);
memcpy(sendPacket+0x17+nameLen, fillBuf, fillSize);
setTimer(timeout);
}
return pcap_sendpacket(hPcap, sendPacket, 0x3E8);
}
static int sendChallengePacket()
{
int nameLen = strlen(userName);
if (startMode%3 == 2) /* 赛尔 */
{
if (sendCount == 0)
{
printf(">> 发送密码...\n");
*(u_int16_t *)(sendPacket+0x0E) = htons(0x0100);
*(u_int16_t *)(sendPacket+0x10) = *(u_int16_t *)(sendPacket+0x14) = htons(nameLen+22);
sendPacket[0x12] = 0x02;
sendPacket[0x13] = capBuf[0x13];
sendPacket[0x16] = 0x04;
sendPacket[0x17] = 16;
memcpy(sendPacket+0x18, checkPass(capBuf[0x13], capBuf+0x18, capBuf[0x17]), 16);
memcpy(sendPacket+0x28, userName, nameLen);
setTimer(timeout);
}
return pcap_sendpacket(hPcap, sendPacket, nameLen+40);
}
if (sendCount == 0)
{
printf(">> 发送密码...\n");
fillMd5Packet(capBuf+0x18);
fillEtherAddr(0x888E0100);
*(u_int16_t *)(sendPacket+0x14) = *(u_int16_t *)(sendPacket+0x10) = htons(nameLen+22);
sendPacket[0x12] = 0x02;
sendPacket[0x13] = capBuf[0x13];
sendPacket[0x16] = 0x04;
sendPacket[0x17] = 16;
memcpy(sendPacket+0x18, checkPass(capBuf[0x13], capBuf+0x18, capBuf[0x17]), 16);
memcpy(sendPacket+0x28, userName, nameLen);
memcpy(sendPacket+0x28+nameLen, fillBuf, fillSize);
setTimer(timeout);
}
return pcap_sendpacket(hPcap, sendPacket, 0x3E8);
}
static int sendEchoPacket()
{
if (startMode%3 == 2) /* 赛尔 */
{
*(u_int16_t *)(sendPacket+0x0E) = htons(0x0106);
*(u_int16_t *)(sendPacket+0x10) = 0;
memset(sendPacket+0x12, 0xa5, 42);
switchState(ID_WAITECHO); /* 继续等待 */
return pcap_sendpacket(hPcap, sendPacket, 60);
}
if (sendCount == 0)
{
u_char echo[] =
{
0x00,0x1E,0xFF,0xFF,0x37,0x77,0x7F,0x9F,0xFF,0xFF,0xD9,0x13,0xFF,0xFF,0x37,0x77,
0x7F,0x9F,0xFF,0xFF,0xF7,0x2B,0xFF,0xFF,0x37,0x77,0x7F,0x3F,0xFF
};
printf(">> 发送心跳包以保持在线...\n");
fillEtherAddr(0x888E01BF);
memcpy(sendPacket+0x10, echo, sizeof(echo));
setTimer(echoInterval);
}
fillEchoPacket(sendPacket);
return pcap_sendpacket(hPcap, sendPacket, 0x2D);
}
static int sendLogoffPacket()
{
setTimer(0); /* 取消定时器 */
if (startMode%3 == 2) /* 赛尔 */
{
*(u_int16_t *)(sendPacket+0x0E) = htons(0x0102);
*(u_int16_t *)(sendPacket+0x10) = 0;
memset(sendPacket+0x12, 0xa5, 42);
return pcap_sendpacket(hPcap, sendPacket, 60);
}
fillStartPacket(); /* 锐捷的退出包与Start包类似不过其实不这样也是没问题的 */
fillEtherAddr(0x888E0102);
memcpy(sendPacket+0x12, fillBuf, fillSize);
return pcap_sendpacket(hPcap, sendPacket, 0x3E8);
}
static int waitEchoPacket()
{
if (sendCount == 0)
setTimer(echoInterval);
return 0;
}
#ifndef NO_ARP
static void sendArpPacket()
{
u_char arpPacket[0x3C] = {
0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x06,0x00,0x01,
0x08,0x00,0x06,0x04,0x00};
if (gateMAC[0] != 0xFF) {
memcpy(arpPacket, gateMAC, 6);
memcpy(arpPacket+0x06, localMAC, 6);
arpPacket[0x15]=0x02;
memcpy(arpPacket+0x16, localMAC, 6);
memcpy(arpPacket+0x1c, &rip, 4);
memcpy(arpPacket+0x20, gateMAC, 6);
memcpy(arpPacket+0x26, &gateway, 4);
pcap_sendpacket(hPcap, arpPacket, 0x3C);
}
memset(arpPacket, 0xFF, 6);
memcpy(arpPacket+0x06, localMAC, 6);
arpPacket[0x15]=0x01;
memcpy(arpPacket+0x16, localMAC, 6);
memcpy(arpPacket+0x1c, &rip, 4);
memset(arpPacket+0x20, 0, 6);
memcpy(arpPacket+0x26, &gateway, 4);
pcap_sendpacket(hPcap, arpPacket, 0x2A);
}
#endif

View File

@ -0,0 +1,22 @@
/*
* Copyright (C) 2009, HustMoon Studio
*
* 文件名称mystate.h
* 摘 要:改变认证状态
* 作 者HustMoon@BYHH
*/
#ifndef HUSTMOON_MYSTATE_H
#define HUSTMOON_MYSTATE_H
#define ID_DISCONNECT 0 /* 断开状态 */
#define ID_START 1 /* 寻找服务器 */
#define ID_IDENTITY 2 /* 发送用户名 */
#define ID_CHALLENGE 3 /* 发送密码 */
#define ID_ECHO 4 /* 发送心跳包 */
#define ID_DHCP 5 /* 更新IP */
#define ID_WAITECHO 6 /* 等待心跳包 */
int switchState(int type); /* 改变状态 */
int restart(); /* 重启认证 */
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
/**
* Copyright(c) 2012-2013, All Rights Reserved.
*
* @file strnormalize.h
* @details Check GBK character you could do
* code >= 0x8000 && _pGbk2Utf16[code - 0x8000] != 0
* @author cnangel
* @version 1.0.0
* @date 2012/10/09 11:44:58
*/
#ifndef __STRNORMALIZE_H__
#define __STRNORMALIZE_H__
#ifdef __cplusplus
extern "C" {
#endif
#define SNO_TO_LOWER 1
#define SNO_TO_UPPER 2
#define SNO_TO_HALF 4
#define SNO_TO_SIMPLIFIED 8
void str_normalize_init();
void str_normalize_gbk(char *text, unsigned options);
void str_normalize_utf8(char *text, unsigned options);
int gbk_to_utf8(const char *from, unsigned int from_len, char **to, unsigned int *to_len);
int utf8_to_gbk(const char *from, unsigned int from_len, char **to, unsigned int *to_len);
#ifdef __cplusplus
}
#endif
#endif /* __STRNORMALIZE_H__ */

View File

@ -0,0 +1,10 @@
#ifndef TYPES_H
#define TYPES_H
typedef unsigned char *POINTER;
typedef unsigned char BYTE;
typedef unsigned char UCHAR;
typedef unsigned short int WORD;
typedef int LONG;
typedef unsigned int DWORD;
typedef unsigned int UINT4;
#endif

View File

@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=adguardhome
PKG_VERSION:=0.107.0-b.11
PKG_RELEASE:=10
PKG_RELEASE:=
PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=48b0cefb29b67cee2171a9eacda9f06f8380b02b

100
amule/Makefile Normal file
View File

@ -0,0 +1,100 @@
# Copyright (C) 2021 ImmortalWrt
# <https://immortalwrt.org>
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=amule
PKG_VERSION:=2.3.3
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/amule-project/amule/tar.gz/$(PKG_VERSION)?
PKG_HASH:=skip
PKG_CONFIG_DEPEDS:= CONFIG_AMULE_CRYPTOPP_STATIC_LINKING
PKG_FIXUP:=autoreconf
PKG_BUILD_DEPENDS:=libcryptopp libgd
PKG_BUILD_PARALLEL:=1
PKG_INSTALL:=1
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/nls.mk
define Package/amule
SUBMENU:=P2P
SECTION:=net
CATEGORY:=Network
TITLE:=A multi-platform eMule-like ed2k client
URL:=http://www.amule.org/
DEPENDS:=+libpng +libpthread +libncurses +libreadline +libwxbase +libupnp +libbfd \
$(ICONV_DEPENDS) $(INTL_DEPENDS) +!AMULE_CRYPTOPP_STATIC_LINKING:libcryptopp
endef
define Package/amule/config
config AMULE_CRYPTOPP_STATIC_LINKING
bool "Link libcryptopp statically"
default n
endef
TARGET_LDFLAGS+= -liconv
CONFIGURE_ARGS+= \
--disable-static \
--disable-rpath \
--disable-ccache \
--disable-optimize \
--disable-profile \
--disable-monolithic \
--enable-amule-daemon \
--enable-amulecmd \
--enable-webserver \
--disable-amule-gui \
--disable-cas \
--disable-wxcas \
--disable-ed2k \
--disable-alc \
--disable-alcc \
--disable-debug \
--disable-fileview \
--disable-plasmamule \
--without-wxdebug \
--enable-dlp \
--enable-upnp \
--with-gnu-ld \
--with-zlib="$(STAGING_DIR)/usr" \
--with-gdlib-prefix="$(STAGING_DIR)/usr" \
--with-libpng-prefix="$(STAGING_DIR)/usr" \
--with-wx-prefix="$(STAGING_DIR)/usr" \
--with-crypto-prefix="$(STAGING_DIR)/usr" \
--with-libiconv-prefix="$(ICONV_PREFIX)" \
--with-libintl-prefix="$(INTL_PREFIX)" \
--with-libupnp-prefix="$(STAGING_DIR)/usr" \
--without-x
MAKE_FLAGS += HOSTCC="$(HOSTCC)"
define Build/Configure
cd $(PKG_BUILD_DIR); $(SHELL) autogen.sh
$(call Build/Configure/Default)
ifeq ($(CONFIG_AMULE_CRYPTOPP_STATIC_LINKING),y)
$(SED) 's;^CRYPTOPP_LIBS.*;CRYPTOPP_LIBS \= "$(STAGING_DIR)/usr/lib/libcryptopp.a";g' \
$(PKG_BUILD_DIR)/src/Makefile
endif
endef
define Package/amule/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/amulecmd $(1)/usr/bin/amulecmd
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/amuled $(1)/usr/bin/amuled
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/amuleweb $(1)/usr/bin/amuleweb
$(INSTALL_DIR) $(1)/usr/share
$(CP) $(PKG_INSTALL_DIR)/usr/share/amule $(1)/usr/share/
endef
$(eval $(call BuildPackage,amule))

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
--- a/m4/libupnp.m4
+++ b/m4/libupnp.m4
@@ -57,7 +57,6 @@ dnl Test for --with-libupnp-prefix
])
dnl Check for libupnp >= MIN_LIBUPNP_VERSION
- AS_IF([test $cross_compiling = no], [
AC_MSG_CHECKING([for libupnp version >= MIN_LIBUPNP_VERSION])
AS_IF([test -n "$PKG_CONFIG"], [
AS_IF([$PKG_CONFIG libupnp --exists], [
@@ -84,11 +83,6 @@ dnl Check for libupnp >= MIN_LIBUPNP_VER
])
AC_MSG_RESULT([$result$resultstr])
libupnp_error="libupnp >= MIN_LIBUPNP_VERSION not found$resultstr"
- ], [
-dnl Currently cross-compilation with libupnp is not supported.
- result=no
- libupnp_error="cross compiling"
- ])
dnl Execute the right action.
AS_IF([test ${result:-no} = yes], [$2], [$3])

83
aria2/Config.in Normal file
View File

@ -0,0 +1,83 @@
menu "Aria2 Configuration"
depends on PACKAGE_aria2
choice
prompt "SSL Library"
default ARIA2_OPENSSL
config ARIA2_OPENSSL
bool "OpenSSL"
config ARIA2_GNUTLS
bool "GnuTLS"
config ARIA2_NOSSL
bool "No SSL Support"
endchoice
choice
prompt "Crypto Library"
depends on !ARIA2_OPENSSL
default ARIA2_NOCRYPTO
config ARIA2_NETTLE
bool "Nettle"
config ARIA2_LIBGCRYPT
bool "Libgcrypt"
config ARIA2_NOCRYPTO
bool "No Crypto Library"
endchoice
choice
prompt "XML Library"
default ARIA2_NOXML
config ARIA2_LIBXML2
bool "Libxml2"
config ARIA2_EXPAT
bool "Expat"
config ARIA2_NOXML
bool "No XML Library"
endchoice
config ARIA2_GMP
bool "GNU Multiple Precision Arithmetic Library"
depends on ARIA2_NETTLE
default n
config ARIA2_BITTORRENT
bool "Enable Bittorrent Support"
depends on ARIA2_OPENSSL || ARIA2_LIBGCRYPT || \
(ARIA2_NETTLE && ARIA2_GMP)
default y
config ARIA2_METALINK
bool "Enable Metalink Support"
depends on !ARIA2_NOXML
default n
config ARIA2_SFTP
bool "Enable SFTP Support"
default n
config ARIA2_ASYNC_DNS
bool "Enable Async DNS Support"
default n
config ARIA2_COOKIE
bool "Enable Firefox3/Chromium Cookie Support"
default n
config ARIA2_WEBSOCKET
bool "Enable JSON-RPC over WebSocket Support"
depends on ARIA2_OPENSSL || ARIA2_LIBGCRYPT || ARIA2_NETTLE
default y
endmenu

121
aria2/Makefile Normal file
View File

@ -0,0 +1,121 @@
#
# Copyright (C) 2012-2018 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=aria2
PKG_VERSION:=1.36.0
PKG_RELEASE:=9
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://github.com/aria2/aria2/releases/download/release-$(PKG_VERSION)/
PKG_HASH:=skip
PKG_INSTALL:=1
PKG_BUILD_PARALLEL:=1
PKG_MAINTAINER:=Imre Kaloz <kaloz@openwrt.org>, \
Hsing-Wang Liao <kuoruan@gmail.com>
PKG_LICENSE:=GPLv2
PKG_LICENSE_FILES:=COPYING
PKG_CPE_ID:=cpe:/a:tatsuhiro_tsujikawa:aria2
PKG_CONFIG_DEPENDS := \
CONFIG_ARIA2_NOSSL \
CONFIG_ARIA2_OPENSSL \
CONFIG_ARIA2_GNUTLS \
CONFIG_ARIA2_NOCRYPTO \
CONFIG_ARIA2_NETTLE \
CONFIG_ARIA2_LIBGCRYPT \
CONFIG_ARIA2_LIBXML2 \
CONFIG_ARIA2_EXPAT \
CONFIG_ARIA2_GMP \
CONFIG_ARIA2_BITTORRENT \
CONFIG_ARIA2_METALINK \
CONFIG_ARIA2_SFTP \
CONFIG_ARIA2_ASYNC_DNS \
CONFIG_ARIA2_COOKIE \
CONFIG_ARIA2_WEBSOCKET
include $(INCLUDE_DIR)/package.mk
define Package/aria2/config
source "$(SOURCE)/Config.in"
endef
define Package/aria2
SECTION:=net
CATEGORY:=Network
SUBMENU:=File Transfer
TITLE:=lightweight download utility
URL:=https://aria2.github.io/
DEPENDS:=+zlib +libstdcpp +ARIA2_OPENSSL:libopenssl +ARIA2_GNUTLS:libgnutls \
+ARIA2_NETTLE:libnettle +ARIA2_LIBGCRYPT:libgcrypt +ARIA2_GMP:libgmp \
+ARIA2_LIBXML2:libxml2 +ARIA2_EXPAT:libexpat +ARIA2_SFTP:libssh2 \
+ARIA2_ASYNC_DNS:libcares +ARIA2_COOKIE:libsqlite3
USERID:=aria2=6800:aria2=6800
endef
define Package/aria2/description
aria2 is a lightweight multi-protocol & multi-source command-line download
utility
endef
CONFIGURE_ARGS += \
--disable-nls \
$(if $(CONFIG_ARIA2_NOSSL),--disable,--enable)-ssl \
$(if $(CONFIG_ARIA2_BITTORRENT),--enable,--disable)-bittorrent \
$(if $(CONFIG_ARIA2_METALINK),--enable,--disable)-metalink \
$(if $(CONFIG_ARIA2_WEBSOCKET),--enable,--disable)-websocket \
$(if $(CONFIG_ARIA2_OPENSSL),--with,--without)-openssl \
$(if $(CONFIG_ARIA2_GNUTLS),--with,--without)-gnutls \
$(if $(CONFIG_ARIA2_NETTLE),--with,--without)-libnettle \
$(if $(CONFIG_ARIA2_LIBGCRYPT),--with,--without)-libgcrypt \
$(if $(CONFIG_ARIA2_GMP),--with,--without)-libgmp \
$(if $(CONFIG_ARIA2_LIBXML2),--with,--without)-libxml2 \
$(if $(CONFIG_ARIA2_EXPAT),--with,--without)-libexpat \
$(if $(CONFIG_ARIA2_SFTP),--with,--without)-libssh2 \
$(if $(CONFIG_ARIA2_ASYNC_DNS),--with,--without)-libcares \
$(if $(CONFIG_ARIA2_COOKIE),--with,--without)-sqlite3 \
--without-libuv \
--with-libz
TARGET_CXXFLAGS += -ffunction-sections -fdata-sections -flto
TARGET_LDFLAGS += -Wl,--gc-sections -flto
define Package/aria2/conffiles
/etc/config/aria2
endef
define Download/aria2.conf
URL:=https://github.com/P3TERX/aria2.conf/archive
URL_FILE:=master.zip
FILE:=aria2.conf
HASH:=skip
endef
define Build/Prepare
$(call Build/Prepare/Default)
unzip $(DL_DIR)/aria2.conf -d $(PKG_BUILD_DIR)/
sed -i '/rpc-secret/d' $(PKG_BUILD_DIR)/aria2.conf-master/*
endef
define Package/aria2/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/aria2c $(1)/usr/bin
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/aria2.init $(1)/etc/init.d/aria2
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/aria2.conf $(1)/etc/config/aria2
$(INSTALL_DIR) $(1)/usr/share/aria2
$(INSTALL_BIN) $(PKG_BUILD_DIR)/aria2.conf-master/* $(1)/usr/share/aria2/
endef
$(eval $(call Download,aria2.conf))
$(eval $(call BuildPackage,aria2))

23
aria2/files/aria2.conf Normal file
View File

@ -0,0 +1,23 @@
# You can use most aria2 command-line options, replace '-' with '_'.
# eg. 'rpc-secret' ==> 'rpc_secret'
#
# We do not support all options at this time. But you can add any option
# with 'list extra_settings'.
#
# You can also add new config sections to define multi instance.
#
config aria2 'main'
option enabled '0'
option user 'aria2'
option dir '/mnt/sda1/aria2'
option config_dir '/var/etc/aria2'
option bt_enable_lpd 'true'
option enable_dht 'true'
option follow_torrent 'true'
option file_allocation 'none'
option save_session_interval '30'
option split '128'
option min_split_size '100K'
option max_connection_per_server '128'
list extra_settings 'dht-file-path=/usr/share/aria2/dht.dat'

360
aria2/files/aria2.init Normal file
View File

@ -0,0 +1,360 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2016-2017 Hsing-wang Liao <kuoruan@gmail.com>
# Licensed to the public under the Apache License 2.0.
START=99
USE_PROCD=1
NAME=aria2
PROG=/usr/bin/aria2c
_info() {
logger -p daemon.info -t "$NAME" "$*"
}
_err() {
logger -p daemon.err -t "$NAME" "$*"
}
_make_dir() {
local d
for d in "$@"; do
if [ ! -d "$d" ]; then
mkdir -p "$d" 2>/dev/null || return 1
fi
done
return 0
}
_create_file() {
touch "$@" 2>/dev/null
}
_change_owner() {
local u="$1"; shift
local d
for d in "$@"; do
if [ -f "$d" ]; then
chown "$u" "$d" 2>/dev/null || return 1
elif [ -d "$d" ]; then
chown -R "$u" "$d" 2>/dev/null || return 1
fi
done
return 0
}
_change_file_mode() {
local mod="$1"; shift
chmod "$mod" "$@" 2>/dev/null
}
_reset_dir_mode() {
local d
for d in "$@"; do
if [ -d "$d" ]; then
find "$d" -type d -exec chmod 755 {} \; 2>/dev/null
find "$d" -type f -exec chmod 644 {} \; 2>/dev/null
fi
done
}
append_options() {
local o; local v
for o in "$@"; do
v="$(eval echo "\$$o")"
[ -n "$v" ] && \
echo "${o//_/-}=$v" >>"$config_file_tmp"
done
}
append_setting() {
local s="$1"
[ -n "$s" ] && \
echo "$s" >>"$config_file_tmp"
}
append_header() {
local h="$1"
[ -n "$h" ] && \
echo "header=\"$h\"" >>"$config_file_tmp"
}
aria2_validate() {
uci_load_validate "$NAME" aria2 "$1" "$2" \
'enabled:bool:0' \
'enable_logging:bool' \
'enable_proxy:bool' \
'config_dir:string:/var/etc/aria2' \
'user:string' \
'all_proxy:string' \
'all_proxy_passwd:string' \
'all_proxy_user:string' \
'auto_save_interval:range(0,600)' \
'bt_enable_lpd:or("true","false")' \
'bt_detach_seed_only:or("true","false")' \
'bt_load_saved_metadata:or("true","false")' \
'bt_prioritize_piece:string' \
'bt_max_open_files:uinteger' \
'bt_max_peers:uinteger' \
'bt_remove_unselected_file:or("true","false")' \
'bt_request_peer_speed_limit:string' \
'bt_save_metadata:or("true","false")' \
'bt_seed_unverified:or("true","false")' \
'bt_stop_timeout:uinteger' \
'bt_tracker:list(string)' \
'ca_certificate:file' \
'certificate:file' \
'check_certificate:or("true","false"):true' \
'check_integrity:or("true","false")' \
'connect_timeout:uinteger' \
'dht_listen_port:string' \
'dir:string' \
'disable_ipv6:or("true","false")' \
'disk_cache:string' \
'enable_dht:or("true","false"):true' \
'enable_dht6:or("true","false")' \
'enable_peer_exchange:or("true","false")' \
'event_poll:or("epoll","kqueue","port","poll","select")' \
'file_allocation:or("none","prealloc","trunc","falloc")' \
'follow_torrent:or("true","false","mem")' \
'force_save:or("true","false")' \
'http_accept_gzip:or("true","false")' \
'http_no_cache:or("true","false")' \
'listen_port:string' \
'log:string' \
'log_level:or("debug","info","notice","warn","error")' \
'lowest_speed_limit:string' \
'max_concurrent_downloads:uinteger' \
'max_connection_per_server:uinteger' \
'max_download_limit:string' \
'max_overall_download_limit:string' \
'max_overall_upload_limit:string' \
'max_tries:uinteger' \
'max_upload_limit:string' \
'min_split_size:string' \
'pause:or("true","false")' \
'pause_metadata:or("true","false")' \
'peer_id_prefix:string' \
'private_key:file' \
'retry_wait:uinteger' \
'rpc_auth_method:or("none","user_pass","token")' \
'rpc_certificate:file' \
'rpc_listen_port:range(1024,65535)' \
'rpc_passwd:string' \
'rpc_private_key:file' \
'rpc_secret:string' \
'rpc_secure:or("true","false")' \
'rpc_user:string' \
'save_session_interval:uinteger' \
'seed_ratio:ufloat' \
'seed_time:ufloat' \
'split:uinteger' \
'timeout:uinteger' \
'user_agent:string'
}
aria2_start() {
local section="$1"
[ "$2" = "0" ] || { _err "Validation failed."; return 1; }
[ "$enabled" = "1" ] || { _info "Instance \"$section\" disabled."; return 1; }
[ -n "$dir" ] || { _err "Please set download dir."; return 1; }
[ -d "$dir" ] || { _err "Please create download dir first."; return 1; }
config_file="$config_dir/$NAME.conf.$section"
config_file_tmp="$config_dir/$NAME.conf.tmp"
session_file="$config_dir/$NAME.session.$section"
_make_dir "$config_dir" || {
_err "Can't create config dir: $config_dir"
return 1
}
_create_file "$session_file" "$config_file" "$config_file_tmp" || {
_err "Can't create files: $session_file, $config_file, $config_file_tmp"
return 1
}
# create tmp file
cat >"$config_file_tmp" <<-EOF
# Auto generated file, changes to this file will be lost.
EOF
append_setting "dir=$dir"
append_setting "enable-rpc=true"
append_setting "rpc-allow-origin-all=true"
append_setting "rpc-listen-all=true"
append_setting "quiet=true"
append_setting "continue=true"
append_setting "input-file=$session_file"
append_setting "save-session=$session_file"
if [ -z "$enable_logging" ]; then
append_options "log" "log_level"
elif [ "$enable_logging" = "1" ]; then
log=${log:-"/var/log/aria2.log"}
local log_dir
log_dir="$(dirname "$log")"
_make_dir "$log_dir" || {
_err "Can't create log dir: $log_dir"
return 1
}
# create or clear log file
echo >"$log"
append_setting "log=$log"
append_options "log_level"
fi
if [ -z "$enable_proxy" ] || [ "$enable_proxy" = "1" ]; then
append_options "all_proxy" "all_proxy_user" "all_proxy_passwd"
fi
unset_auth_method() {
uci -q batch <<-EOF
set $NAME.$section.rpc_auth_method=""
commit $NAME
EOF
}
if [ -z "$rpc_auth_method" ]; then
if [ -n "$rpc_secret" ]; then
append_setting "rpc-secret=$rpc_secret"
elif [ -n "$rpc_user" ]; then
append_setting "rpc-user=$rpc_user"
append_setting "rpc-passwd=$rpc_passwd"
else
_info "It is recommended to set RPC secret."
fi
elif [ "$rpc_auth_method" = "token" ]; then
if [ -n "$rpc_secret" ]; then
append_setting "rpc-secret=$rpc_secret"
else
unset_auth_method
fi
elif [ "$rpc_auth_method" = "user_pass" ]; then
if [ -n "$rpc_user" ]; then
append_setting "rpc-user=$rpc_user"
append_setting "rpc-passwd=$rpc_passwd"
else
_info "Please set RPC user."
unset_auth_method
fi
fi
if [ ."$rpc_secure" = ."true" ] && [ -n "$rpc_certificate" ]; then
append_setting "rpc-secure=true"
append_options "rpc_certificate" "rpc_private_key"
fi
if [ ."$check_certificate" = ."true" ]; then
append_setting "check-certificate=true"
append_options "ca_certificate"
elif [ ."$check_certificate" = ."false" ]; then
append_setting "check-certificate=false"
fi
if [ ."$enable_dht" = ."true" ]; then
dht_file="$config_dir/dht.dat.$section"
_create_file "$dht_file" || {
_err "Can't create DHT file: $dht_file"
return 1
}
append_setting "enable-dht=true"
append_setting "dht-file-path=$dht_file"
fi
if [ ."$enable_dht6" = ."true" ] && [ ."$disable_ipv6" != ."true" ]; then
dht6_file="$config_dir/dht6.dat.$section"
_create_file "$dht6_file" || {
_err "Can't create DHT6 file: $dht6_file"
return 1
}
append_setting "enable-dht6=true"
append_setting "dht-file-path6=$dht6_file"
fi
if [ -n "$bt_tracker" ]; then
local bt_tracker_list; local t
for t in $bt_tracker; do
if [ -z "$bt_tracker_list" ]; then
bt_tracker_list="$t"
else
bt_tracker_list="$bt_tracker_list,$t"
fi
done
append_setting "bt-tracker=$bt_tracker_list"
fi
append_options "auto_save_interval" "bt_enable_lpd" "bt_max_open_files" "bt_max_peers" \
"bt_remove_unselected_file" "bt_request_peer_speed_limit" "bt_prioritize_piece" \
"bt_stop_timeout" "bt_detach_seed_only" "bt_save_metadata" "bt_load_saved_metadata" \
"bt_seed_unverified" "certificate" "check_integrity" "connect_timeout" "dht_listen_port" \
"disable_ipv6" "disk_cache" "enable_peer_exchange" "event_poll" "file_allocation" \
"follow_torrent" "force_save" "http_accept_gzip" "http_no_cache" "listen_port" \
"lowest_speed_limit" "max_concurrent_downloads" "max_connection_per_server" \
"max_download_limit" "max_overall_download_limit" "max_overall_upload_limit" "max_tries" \
"max_upload_limit" "min_split_size" "pause" "pause_metadata" "peer_id_prefix" "private_key" \
"retry_wait" "rpc_listen_port" "save_session_interval" "seed_ratio" "seed_time" "split" "timeout" \
"user_agent"
config_list_foreach "$section" "header" append_header
config_list_foreach "$section" "extra_settings" append_setting
cd /usr/share/aria2 && sh ./tracker.sh
cat /usr/share/aria2/aria2.conf > "$config_file"
echo '' >> "$config_file"
sed '/^$/d' "$config_file_tmp" >> "$config_file"
rm -f "$config_file_tmp"
_reset_dir_mode "$config_dir"
_change_file_mode 600 "$config_file"
if [ -n "$user" ]; then
if ( user_exists "$user" && _change_owner "$user" "$config_dir" "$log" ); then
_info "Aria2 will run with user '$user'."
if [ "$user" != "root" ]; then
_info "Please make sure user '$user' has write access to download dir: $dir"
fi
else
_info "Setting run user to '$user' failed, default user will be used."
user=
fi
fi
procd_open_instance "$NAME.$section"
procd_set_param command "$PROG"
procd_append_param command --conf-path="$config_file"
procd_set_param respawn
procd_set_param stdout 1
procd_set_param stderr 1
procd_set_param file "$config_file"
[ -n "$user" ] && \
procd_set_param user "$user"
procd_add_jail "$NAME.$section" log
procd_add_jail_mount "$config_file"
procd_add_jail_mount_rw "$dir" "$config_dir" "$log"
procd_close_instance
}
service_triggers() {
procd_add_reload_trigger "$NAME"
procd_add_validation aria2_validate
}
start_service() {
config_load "$NAME"
config_foreach aria2_validate "aria2" aria2_start
}

View File

@ -0,0 +1,29 @@
--- /src/OptionHandlerFactory.cc 2018-05-15 20:33:25.000000000 +0800
+++ /src/OptionHandlerFactory.cc 2018-07-05 10:40:25.000000000 +0800
@@ -440,7 +440,7 @@
{
OptionHandler* op(new NumberOptionHandler(PREF_MAX_CONNECTION_PER_SERVER,
TEXT_MAX_CONNECTION_PER_SERVER,
- "1", 1, 16, 'x'));
+ "64", 1, -1, 'x'));
op->addTag(TAG_BASIC);
op->addTag(TAG_FTP);
op->addTag(TAG_HTTP);
@@ -501,7 +501,7 @@
}
{
OptionHandler* op(new UnitNumberOptionHandler(
- PREF_MIN_SPLIT_SIZE, TEXT_MIN_SPLIT_SIZE, "20M", 1_m, 1_g, 'k'));
+ PREF_MIN_SPLIT_SIZE, TEXT_MIN_SPLIT_SIZE, "1M", 1_k, 1_g, 'k'));
op->addTag(TAG_BASIC);
op->addTag(TAG_FTP);
op->addTag(TAG_HTTP);
@@ -905,7 +905,7 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
}
{
OptionHandler* op(new UnitNumberOptionHandler(
- PREF_PIECE_LENGTH, TEXT_PIECE_LENGTH, "1M", 1_m, 1_g));
+ PREF_PIECE_LENGTH, TEXT_PIECE_LENGTH, "1M", 1_k, 1_g));
op->addTag(TAG_ADVANCED);
op->addTag(TAG_FTP);
op->addTag(TAG_HTTP);

View File

@ -0,0 +1,61 @@
From 66524bee738e98742c908d93c993d0a78a2d9891 Mon Sep 17 00:00:00 2001
From: myfreeer <myfreeer@users.noreply.github.com>
Date: Sat, 18 Nov 2017 11:55:04 +0800
Subject: [PATCH 3/4] download: retry on slow speed and conection close
This would provide better speed on bad network conditions
---
src/DownloadCommand.cc | 2 +-
src/SocketBuffer.cc | 3 ++-
src/SocketCore.cc | 2 +-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/DownloadCommand.cc b/src/DownloadCommand.cc
index 2db41e4..f49eb80 100644
--- a/src/DownloadCommand.cc
+++ b/src/DownloadCommand.cc
@@ -306,7 +306,7 @@ void DownloadCommand::checkLowestDownloadSpeed() const
startupIdleTime_) {
int nowSpeed = peerStat_->calculateDownloadSpeed();
if (nowSpeed <= lowestDownloadSpeedLimit_) {
- throw DL_ABORT_EX2(fmt(EX_TOO_SLOW_DOWNLOAD_SPEED, nowSpeed,
+ throw DL_RETRY_EX2(fmt(EX_TOO_SLOW_DOWNLOAD_SPEED, nowSpeed,
lowestDownloadSpeedLimit_,
getRequest()->getHost().c_str()),
error_code::TOO_SLOW_DOWNLOAD_SPEED);
diff --git a/src/SocketBuffer.cc b/src/SocketBuffer.cc
index 62862ff..1906173 100644
--- a/src/SocketBuffer.cc
+++ b/src/SocketBuffer.cc
@@ -39,6 +39,7 @@
#include "SocketCore.h"
#include "DlAbortEx.h"
+#include "DlRetryEx.h"
#include "message.h"
#include "fmt.h"
#include "LogFactory.h"
@@ -158,7 +159,7 @@ ssize_t SocketBuffer::send()
}
ssize_t slen = socket_->writeVector(iov, num);
if (slen == 0 && !socket_->wantRead() && !socket_->wantWrite()) {
- throw DL_ABORT_EX(fmt(EX_SOCKET_SEND, "Connection closed."));
+ throw DL_RETRY_EX(fmt(EX_SOCKET_SEND, "Connection closed."));
}
// A2_LOG_NOTICE(fmt("num=%zu, amount=%d, bufq.size()=%zu, SEND=%d",
// num, amount, bufq_.size(), slen));
diff --git a/src/SocketCore.cc b/src/SocketCore.cc
index 77dc30c..537375a 100644
--- a/src/SocketCore.cc
+++ b/src/SocketCore.cc
@@ -1009,7 +1009,7 @@ bool SocketCore::tlsHandshake(TLSContext* tlsctx, const std::string& hostname)
if (rv == TLS_ERR_ERROR) {
// Damn those error.
- throw DL_ABORT_EX(fmt("SSL/TLS handshake failure: %s",
+ throw DL_RETRY_EX(fmt("SSL/TLS handshake failure: %s",
handshakeError.empty()
? tlsSession_->getLastErrorString().c_str()
: handshakeError.c_str()));
--
2.17.1

View File

@ -0,0 +1,239 @@
From 8adbc01dc5975a64c55fe594d8c758c71e8183b3 Mon Sep 17 00:00:00 2001
From: myfreeer <myfreeer@users.noreply.github.com>
Date: Sun, 22 Jul 2018 19:59:02 +0800
Subject: [PATCH] option: add option to retry on http 400, 403, 406, or unknown
--retry-on-400[=true|false] Configure whether retry or not when
HTTP server returns 400 Bad Request.
Only effective if retry-wait > 0.
Possible Values: true, false
Default: false
Tags: #advanced, #http
--retry-on-403[=true|false] Configure whether retry or not when
HTTP server returns 403 Forbidden.
Only effective if retry-wait > 0.
Possible Values: true, false
Default: false
Tags: #advanced, #http
--retry-on-406[=true|false] Configure whether retry or not when
HTTP server returns 406 Not Acceptable.
Only effective if retry-wait > 0.
Possible Values: true, false
Default: false
Tags: #advanced, #http
--retry-on-unknown[=true|false] Configure whether retry or not when
HTTP server returns unknown status code.
Only effective if retry-wait > 0.
Possible Values: true, false
Default: false
Tags: #advanced, #http
---
src/HttpSkipResponseCommand.cc | 42 +++++++++++++++++++++++++++++-----
src/OptionHandlerFactory.cc | 40 ++++++++++++++++++++++++++++++++
src/prefs.cc | 8 +++++++
src/prefs.h | 8 +++++++
src/usage_text.h | 16 +++++++++++++
5 files changed, 108 insertions(+), 6 deletions(-)
diff --git a/src/HttpSkipResponseCommand.cc b/src/HttpSkipResponseCommand.cc
index a722d77..de4ad6c 100644
--- a/src/HttpSkipResponseCommand.cc
+++ b/src/HttpSkipResponseCommand.cc
@@ -204,7 +204,7 @@ bool HttpSkipResponseCommand::processResponse()
auto statusCode = httpResponse_->getStatusCode();
if (statusCode >= 400) {
switch (statusCode) {
- case 401:
+ case 401: // Unauthorized
if (getOption()->getAsBool(PREF_HTTP_AUTH_CHALLENGE) &&
!httpResponse_->getHttpRequest()->authenticationUsed() &&
getDownloadEngine()->getAuthConfigFactory()->activateBasicCred(
@@ -213,15 +213,41 @@ bool HttpSkipResponseCommand::processResponse()
return prepareForRetry(0);
}
throw DL_ABORT_EX2(EX_AUTH_FAILED, error_code::HTTP_AUTH_FAILED);
- case 404:
+ case 404: // Not Found
if (getOption()->getAsInt(PREF_MAX_FILE_NOT_FOUND) == 0) {
throw DL_ABORT_EX2(MSG_RESOURCE_NOT_FOUND,
error_code::RESOURCE_NOT_FOUND);
}
throw DL_RETRY_EX2(MSG_RESOURCE_NOT_FOUND,
error_code::RESOURCE_NOT_FOUND);
- case 502:
- case 503:
+ case 400: // Bad Request
+ if (getOption()->getAsBool(PREF_RETRY_ON_400)
+ && getOption()->getAsInt(PREF_RETRY_WAIT) > 0) {
+ throw DL_RETRY_EX2(fmt(EX_BAD_STATUS, statusCode),
+ error_code::HTTP_PROTOCOL_ERROR);
+ }
+ break;
+ case 403: // Forbidden
+ if (getOption()->getAsBool(PREF_RETRY_ON_403)
+ && getOption()->getAsInt(PREF_RETRY_WAIT) > 0) {
+ throw DL_RETRY_EX2(fmt(EX_BAD_STATUS, statusCode),
+ error_code::HTTP_PROTOCOL_ERROR);
+ }
+ break;
+ case 406: // Not Acceptable
+ if (getOption()->getAsBool(PREF_RETRY_ON_406)
+ && getOption()->getAsInt(PREF_RETRY_WAIT) > 0) {
+ throw DL_RETRY_EX2(fmt(EX_BAD_STATUS, statusCode),
+ error_code::HTTP_PROTOCOL_ERROR);
+ }
+ break;
+ case 408: // Request Timeout
+ case 429: // Too Many Requests
+ case 502: // Bad Gateway
+ case 503: // Service Unavailable
+ case 507: // Insufficient Storage
+ case 520: // https://github.com/aria2/aria2/issues/1229
+ case 521: // https://github.com/aria2/aria2/issues/1229
// Only retry if pretry-wait > 0. Hammering 'busy' server is not
// a good idea.
if (getOption()->getAsInt(PREF_RETRY_WAIT) > 0) {
@@ -230,12 +256,16 @@ bool HttpSkipResponseCommand::processResponse()
}
throw DL_ABORT_EX2(fmt(EX_BAD_STATUS, statusCode),
error_code::HTTP_SERVICE_UNAVAILABLE);
- case 504:
+ case 504: // Gateway Timeout
// This is Gateway Timeout, so try again
throw DL_RETRY_EX2(fmt(EX_BAD_STATUS, statusCode),
error_code::HTTP_SERVICE_UNAVAILABLE);
};
-
+ if (getOption()->getAsBool(PREF_RETRY_ON_UNKNOWN)
+ && getOption()->getAsInt(PREF_RETRY_WAIT) > 0) {
+ throw DL_RETRY_EX2(fmt(EX_BAD_STATUS, statusCode),
+ error_code::HTTP_PROTOCOL_ERROR);
+ }
throw DL_ABORT_EX2(fmt(EX_BAD_STATUS, statusCode),
error_code::HTTP_PROTOCOL_ERROR);
}
diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc
index 5768f7b..decb03e 100644
--- a/src/OptionHandlerFactory.cc
+++ b/src/OptionHandlerFactory.cc
@@ -934,6 +934,46 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
op->setChangeOptionForReserved(true);
handlers.push_back(op);
}
+ {
+ OptionHandler* op(new BooleanOptionHandler(
+ PREF_RETRY_ON_400, TEXT_RETRY_ON_400, A2_V_FALSE, OptionHandler::OPT_ARG));
+ op->addTag(TAG_ADVANCED);
+ op->addTag(TAG_HTTP);
+ op->setInitialOption(true);
+ op->setChangeGlobalOption(true);
+ op->setChangeOptionForReserved(true);
+ handlers.push_back(op);
+ }
+ {
+ OptionHandler* op(new BooleanOptionHandler(
+ PREF_RETRY_ON_403, TEXT_RETRY_ON_403, A2_V_FALSE, OptionHandler::OPT_ARG));
+ op->addTag(TAG_ADVANCED);
+ op->addTag(TAG_HTTP);
+ op->setInitialOption(true);
+ op->setChangeGlobalOption(true);
+ op->setChangeOptionForReserved(true);
+ handlers.push_back(op);
+ }
+ {
+ OptionHandler* op(new BooleanOptionHandler(
+ PREF_RETRY_ON_406, TEXT_RETRY_ON_406, A2_V_FALSE, OptionHandler::OPT_ARG));
+ op->addTag(TAG_ADVANCED);
+ op->addTag(TAG_HTTP);
+ op->setInitialOption(true);
+ op->setChangeGlobalOption(true);
+ op->setChangeOptionForReserved(true);
+ handlers.push_back(op);
+ }
+ {
+ OptionHandler* op(new BooleanOptionHandler(
+ PREF_RETRY_ON_UNKNOWN, TEXT_RETRY_ON_UNKNOWN, A2_V_FALSE, OptionHandler::OPT_ARG));
+ op->addTag(TAG_ADVANCED);
+ op->addTag(TAG_HTTP);
+ op->setInitialOption(true);
+ op->setChangeGlobalOption(true);
+ op->setChangeOptionForReserved(true);
+ handlers.push_back(op);
+ }
{
OptionHandler* op(new BooleanOptionHandler(
PREF_REUSE_URI, TEXT_REUSE_URI, A2_V_TRUE, OptionHandler::OPT_ARG));
diff --git a/src/prefs.cc b/src/prefs.cc
index 937e927..33eff91 100644
--- a/src/prefs.cc
+++ b/src/prefs.cc
@@ -327,6 +327,14 @@ PrefPtr PREF_ENABLE_ASYNC_DNS6 = makePref("enable-async-dns6");
PrefPtr PREF_MAX_DOWNLOAD_RESULT = makePref("max-download-result");
// value: 1*digit
PrefPtr PREF_RETRY_WAIT = makePref("retry-wait");
+// value: true | false
+PrefPtr PREF_RETRY_ON_400 = makePref("retry-on-400");
+// value: true | false
+PrefPtr PREF_RETRY_ON_403 = makePref("retry-on-403");
+// value: true | false
+PrefPtr PREF_RETRY_ON_406 = makePref("retry-on-406");
+// value: true | false
+PrefPtr PREF_RETRY_ON_UNKNOWN = makePref("retry-on-unknown");
// value: string
PrefPtr PREF_ASYNC_DNS_SERVER = makePref("async-dns-server");
// value: true | false
diff --git a/src/prefs.h b/src/prefs.h
index e1f8397..019e774 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -280,6 +280,14 @@ extern PrefPtr PREF_ENABLE_ASYNC_DNS6;
extern PrefPtr PREF_MAX_DOWNLOAD_RESULT;
// value: 1*digit
extern PrefPtr PREF_RETRY_WAIT;
+// value: true | false
+extern PrefPtr PREF_RETRY_ON_400;
+// value: true | false
+extern PrefPtr PREF_RETRY_ON_403;
+// value: true | false
+extern PrefPtr PREF_RETRY_ON_406;
+// value: true | false
+extern PrefPtr PREF_RETRY_ON_UNKNOWN;
// value: string
extern PrefPtr PREF_ASYNC_DNS_SERVER;
// value: true | false
diff --git a/src/usage_text.h b/src/usage_text.h
index d73b50d..75d34a0 100644
--- a/src/usage_text.h
+++ b/src/usage_text.h
@@ -64,6 +64,22 @@
_(" --retry-wait=SEC Set the seconds to wait between retries. \n" \
" With SEC > 0, aria2 will retry download when the\n" \
" HTTP server returns 503 response.")
+#define TEXT_RETRY_ON_400 \
+ _(" --retry-on-400[=true|false] Configure whether retry or not when\n" \
+ " HTTP server returns 400 Bad Request.\n" \
+ " Only effective if retry-wait > 0.")
+#define TEXT_RETRY_ON_403 \
+ _(" --retry-on-403[=true|false] Configure whether retry or not when\n" \
+ " HTTP server returns 403 Forbidden.\n" \
+ " Only effective if retry-wait > 0.")
+#define TEXT_RETRY_ON_406 \
+ _(" --retry-on-406[=true|false] Configure whether retry or not when\n" \
+ " HTTP server returns 406 Not Acceptable.\n" \
+ " Only effective if retry-wait > 0.")
+#define TEXT_RETRY_ON_UNKNOWN \
+ _(" --retry-on-unknown[=true|false] Configure whether retry or not when\n" \
+ " HTTP server returns unknown status code.\n" \
+ " Only effective if retry-wait > 0.")
#define TEXT_TIMEOUT \
_(" -t, --timeout=SEC Set timeout in seconds.")
#define TEXT_MAX_TRIES \
--
2.18.0

View File

@ -0,0 +1,123 @@
From b938aa51e50852d1b185db3188357073ad374416 Mon Sep 17 00:00:00 2001
From: myfreeer <myfreeer@users.noreply.github.com>
Date: Sun, 13 Dec 2020 15:40:56 +0800
Subject: [PATCH] option: add option to disable Want-Digest header
Sending this HTTP header should be optional.
Should close https://github.com/myfreeer/aria2-build-msys2/issues/10
--http-want-digest[=true|false] Send Want-Digest HTTP requser header
with only limited hash algorithms:
SHA-512, SHA-256, and SHA-1.
The Want-Digest HTTP header is primarily used
in a HTTP request, to ask the responder to
provide a digest of the requested resource
using the Digest response header
Possible Values: true, false
Default: false
Tags: #advanced, #http
---
src/AbstractProxyRequestCommand.cc | 1 +
src/HttpRequestCommand.cc | 1 +
src/OptionHandlerFactory.cc | 12 ++++++++++++
src/prefs.cc | 2 ++
src/prefs.h | 2 ++
src/usage_text.h | 8 ++++++++
6 files changed, 26 insertions(+)
diff --git a/src/AbstractProxyRequestCommand.cc b/src/AbstractProxyRequestCommand.cc
index bd2bcb3..1feed07 100644
--- a/src/AbstractProxyRequestCommand.cc
+++ b/src/AbstractProxyRequestCommand.cc
@@ -72,6 +72,7 @@ bool AbstractProxyRequestCommand::executeInternal()
if (httpConnection_->sendBufferIsEmpty()) {
auto httpRequest = make_unique<HttpRequest>();
httpRequest->setUserAgent(getOption()->get(PREF_USER_AGENT));
+ httpRequest->setNoWantDigest(!getOption()->getAsBool(PREF_HTTP_WANT_DIGEST));
httpRequest->setRequest(getRequest());
httpRequest->setProxyRequest(proxyRequest_);
diff --git a/src/HttpRequestCommand.cc b/src/HttpRequestCommand.cc
index a2b8e7e..8c50153 100644
--- a/src/HttpRequestCommand.cc
+++ b/src/HttpRequestCommand.cc
@@ -90,6 +90,7 @@ createHttpRequest(const std::shared_ptr<Request>& req,
{
auto httpRequest = make_unique<HttpRequest>();
httpRequest->setUserAgent(option->get(PREF_USER_AGENT));
+ httpRequest->setNoWantDigest(!option->getAsBool(PREF_HTTP_WANT_DIGEST));
httpRequest->setRequest(req);
httpRequest->setFileEntry(fileEntry);
httpRequest->setSegment(segment);
diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc
index a058eb9..9ff615a 100644
--- a/src/OptionHandlerFactory.cc
+++ b/src/OptionHandlerFactory.cc
@@ -1106,6 +1106,18 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
op->setChangeOptionForReserved(true);
handlers.push_back(op);
}
+ {
+ OptionHandler* op(
+ new BooleanOptionHandler(PREF_HTTP_WANT_DIGEST,
+ TEXT_HTTP_WANT_DIGEST,
+ A2_V_FALSE, OptionHandler::OPT_ARG));
+ op->addTag(TAG_ADVANCED);
+ op->addTag(TAG_HTTP);
+ op->setInitialOption(true);
+ op->setChangeGlobalOption(true);
+ op->setChangeOptionForReserved(true);
+ handlers.push_back(op);
+ }
{
OptionHandler* op(new BooleanOptionHandler(
PREF_ENABLE_HTTP_KEEP_ALIVE, TEXT_ENABLE_HTTP_KEEP_ALIVE, A2_V_TRUE,
diff --git a/src/prefs.cc b/src/prefs.cc
index 9793706..bdb33e2 100644
--- a/src/prefs.cc
+++ b/src/prefs.cc
@@ -437,6 +437,8 @@ PrefPtr PREF_HTTP_ACCEPT_GZIP = makePref("http-accept-gzip");
// value: true | false
PrefPtr PREF_CONTENT_DISPOSITION_DEFAULT_UTF8 =
makePref("content-disposition-default-utf8");
+// values: true | false
+PrefPtr PREF_HTTP_WANT_DIGEST = makePref("http-want-digest");
/**
* Proxy related preferences
diff --git a/src/prefs.h b/src/prefs.h
index f014d9c..c88f2d0 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -389,6 +389,8 @@ extern PrefPtr PREF_HTTP_NO_CACHE;
extern PrefPtr PREF_HTTP_ACCEPT_GZIP;
// value: true | false
extern PrefPtr PREF_CONTENT_DISPOSITION_DEFAULT_UTF8;
+// value: true | false
+extern PrefPtr PREF_HTTP_WANT_DIGEST;
/**;
* Proxy related preferences
diff --git a/src/usage_text.h b/src/usage_text.h
index 7a0a981..aee3ac0 100644
--- a/src/usage_text.h
+++ b/src/usage_text.h
@@ -560,6 +560,14 @@
" Content-Disposition header as UTF-8 instead of\n" \
" ISO-8859-1, for example, the filename parameter,\n" \
" but not the extended version filename*.")
+#define TEXT_HTTP_WANT_DIGEST \
+ _(" --http-want-digest[=true|false] Send Want-Digest HTTP requser header\n" \
+ " with only limited hash algorithms:\n" \
+ " SHA-512, SHA-256, and SHA-1.\n" \
+ " The Want-Digest HTTP header is primarily used\n" \
+ " in a HTTP request, to ask the responder to\n" \
+ " provide a digest of the requested resource\n" \
+ " using the Digest response header")
#define TEXT_EVENT_POLL \
_(" --event-poll=POLL Specify the method for polling events.")
#define TEXT_BT_EXTERNAL_IP \
--
2.29.2

71
autocore/Makefile Normal file
View File

@ -0,0 +1,71 @@
#
# Copyright (C) 2010-2011 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=autocore
PKG_VERSION:=1
PKG_RELEASE:=29
include $(INCLUDE_DIR)/package.mk
define Package/autocore-arm
TITLE:=ARM auto core script.
MAINTAINER:=CN_SZTL
DEPENDS:=@(arm||aarch64) \
+TARGET_bcm27xx:bcm27xx-userland \
+TARGET_bcm53xx:nvram \
+ethtool
VARIANT:=arm
endef
define Package/autocore-x86
TITLE:=x86/x64 auto core loadbalance script.
MAINTAINER:=Lean / CN_SZTL
DEPENDS:=@TARGET_x86 +bc +lm-sensors +ethtool
VARIANT:=x86
endef
define Package/autocore-arm/description
Display more details info about the devices in LuCI.
endef
define Download/armcpuinfo
URL:=https://raw.githubusercontent.com/immortalwrt/immortalwrt/master/package/emortal/autocore/files/arm
URL_FILE:=cpuinfo
FILE:=cpuinfo
HASH:=skip
endef
define Build/Prepare
sed -i 's/cpu_arch="?"/cpu_arch="ARMv8 Processor"/' $(DL_DIR)/cpuinfo
endef
define Build/Compile
endef
define Package/autocore-arm/install
$(INSTALL_DIR) $(1)/sbin
$(INSTALL_BIN) $(DL_DIR)/cpuinfo $(1)/sbin/cpuinfo
$(INSTALL_BIN) ./files/common/ethinfo $(1)/sbin/ethinfo
$(INSTALL_DIR) $(1)/www/luci-static/resources/view/status/include
$(INSTALL_DATA) ./files/common/29_eth.js $(1)/www/luci-static/resources/view/status/include/
endef
define Package/autocore-x86/install
$(INSTALL_DIR) $(1)/sbin
$(INSTALL_BIN) ./files/x86/cpuinfo $(1)/sbin/cpuinfo
$(INSTALL_BIN) ./files/common/ethinfo $(1)/sbin/ethinfo
$(INSTALL_DIR) $(1)/www/luci-static/resources/view/status/include
$(INSTALL_DATA) ./files/common/29_eth.js $(1)/www/luci-static/resources/view/status/include/
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/view/admin_status/index/
$(INSTALL_DATA) ./files/x86/nvme_status.htm $(1)/usr/lib/lua/luci/view/admin_status/index/
endef
$(eval $(call Download,armcpuinfo))
$(eval $(call BuildPackage,autocore-arm))
$(eval $(call BuildPackage,autocore-x86))

View File

@ -0,0 +1,34 @@
'use strict';
'require rpc';
var callEthInfo = rpc.declare({
object: 'luci',
method: 'getEthInfo'
});
return L.Class.extend({
title: _('Interfaces'),
load: function() {
return L.resolveDefault(callEthInfo(), {});
},
render: function(info) {
if (info && info.result) {
var result = "";
var ports = eval('(' + info.result + ')');
var tmp = "<div class='table' width='100%' cellspacing='10' style='text-align: center' id='ethinfo'><ul style='list-style: none; margin:0 auto; display: inline-block;'>";
for (var i in ports) {
tmp = tmp + String.format(
'<li style="float: left; margin: 0px 1em;"><span style="line-height:25px">%s</span><br /><small><img draggable="false" src="/luci-static/resources/icons/%s" /><br />%s<br />%s</small></li>',
ports[i].name,
ports[i].status ? 'port_up.png' : 'port_down.png',
ports[i].speed,
ports[i].duplex ? _('full-duplex') : _('half-duplex'));
}
tmp + "</ul></div>";
result = tmp;
return result;
}
}
});

View File

@ -0,0 +1,39 @@
#!/bin/sh
a=$(ip address | grep ^[0-9] | awk -F: '{print $2}' | sed "s/ //g" | grep '^[e]' | grep -v "@" | grep -v "\.")
b=$(echo "$a" | wc -l)
rm -f /tmp/state/ethinfo
echo -n "[" > /tmp/state/ethinfo
for i in $(seq 1 $b)
do
h=$(echo '{"name":' )
c=$(echo "$a" | sed -n ${i}p)
d=$(ethtool $c)
e=$(echo "$d" | grep "Link detected" | awk -F: '{printf $2}' | sed 's/^[ \t]*//g')
if [ $e = yes ]; then
l=1
else
l=0
fi
f=$(echo "$d" | grep "Speed" | awk -F: '{printf $2}' | sed 's/^[ \t]*//g' | tr -d "Unknown!")
[ -z "$f" ] && f=" - "
g=$(echo "$d" | grep "Duplex" | awk -F: '{printf $2}' | sed 's/^[ \t]*//g')
if [ "$g" == "Full" ]; then
x=1
else
x=0
fi
echo -n "$h \"$c\", \"status\": $l, \"speed\": \"$f\", \"duplex\": $x}," >> /tmp/state/ethinfo
done
sed -i 's/.$//' /tmp/state/ethinfo
echo -n "]" >> /tmp/state/ethinfo
cat /tmp/state/ethinfo

View File

@ -0,0 +1,5 @@
#!/bin/sh
MHz=`grep 'MHz' /proc/cpuinfo | cut -c11- |sed -n '1p'`
TEMP=`sensors 2>/dev/null | grep 'Core 0' | cut -c12-`
echo "$MHz MHz $TEMP "

View File

@ -0,0 +1,228 @@
<% local raid = {}
local devs = {}
local devinfo = {}
local colors = { "c0c0ff", "fbbd00", "e97c30", "a0e0a0", "b2c005", "e0c0ff" }
local mounts = nixio.fs.readfile("/proc/mounts")
local show_raid = 1
local show_disc = 1
if self then
if self.hide_raid then
show_raid = 0
end
if self.hide_disc then
show_disc = 0
end
end
function disp_size(s)
local units = { "kB", "MB", "GB", "TB" }
local i, unit
s = s / 2
for i, unit in ipairs(units) do
if (i == #units) or (s < 1024) then
return math.floor(s * 100) / 100 .. unit
end
s = s / 1024
end
end
function first_line(s)
local n = s:find("\n")
if n then
return s:sub(1, n-1)
end
return s
end
function get_fs(pname, status)
for r,raid in ipairs(raid) do
for m,member in ipairs(raid.members) do
if member.name == pname then
return "(raid member)"
end
end
end
local mounted_fs = mounts:match("\n[a-z/]*" .. pname .. " [^ ]* ([^ ]*)")
if mounted_fs then
if status == "standby" then
return "(" .. mounted_fs .. ")"
end
local df = luci.sys.exec("df /dev/" .. pname):match(" ([0-9]+)%% ")
return "(" .. mounted_fs .. " " .. df .. "%)"
end
if status == "standby" then
return
end
local blkid = luci.sys.exec(" blkid -s TYPE /dev/" .. pname):match("TYPE=\"(.*)\"")
if blkid then
return "(" .. blkid .. ")"
end
end
function get_status(raid)
for m,member in ipairs(raid.members) do
for d,dev in ipairs(devinfo) do
if member.name == dev.name then
return dev.status
end
for p,part in ipairs(dev.parts) do
if member.name == part.name then
return dev.status
end
end
end
end
end
function get_parts(dev,status,size)
local c = 1
local unused = size
local parts = {}
for part in nixio.fs.glob("/sys/block/" .. dev .."/" .. dev .. "*") do
local pname = nixio.fs.basename(part)
local psize = nixio.fs.readfile(part .. "/size")
table.insert(parts, {name=pname, size=psize, perc=math.floor(psize*100/size), fs=get_fs(pname,status), color=colors[c]})
c = c + 1
unused = unused - psize
end
if unused > 2048 then
table.insert(parts, { name="", fs=get_fs(dev,status), size=unused, color=colors[c] })
end
return parts
end
for dev in nixio.fs.glob("/sys/block/*") do
if nixio.fs.access(dev .. "/md") then
local name = nixio.fs.basename(dev)
local rlevel = first_line(nixio.fs.readfile(dev .. "/md/level"))
local ndisks = tonumber(nixio.fs.readfile(dev .. "/md/raid_disks"))
local size = tonumber(nixio.fs.readfile(dev .. "/size"))
local metav = nixio.fs.readfile(dev .. "/md/metadata_version")
local degr = tonumber(nixio.fs.readfile(dev .. "/md/degraded"))
local sync = first_line(nixio.fs.readfile(dev .. "/md/sync_action"))
local sync_speed = tonumber(nixio.fs.readfile(dev .. "/md/sync_speed"))
local sync_compl = nixio.fs.readfile(dev .. "/md/sync_completed")
local status = "active"
if sync ~= "idle" then
local progress, total = nixio.fs.readfile(dev .. "/md/sync_completed"):match("^([0-9]*)[^0-9]*([0-9]*)")
local rem = (total - progress) / sync_speed / 2
local rems = math.floor(rem % 60)
if rems < 10 then rems = "0" .. rems end
rem = math.floor(rem / 60)
local remm = math.floor(rem % 60)
if remm < 10 then remm = "0" .. remm end
local remh = math.floor(rem / 60)
local remstr = remh .. ":" .. remm .. ":" .. rems
status = sync .. " (" .. math.floor(sync_speed/1024) .. "MB/s, " .. math.floor(progress * 1000 / total) /10 .. "%, rem. " .. remstr .. ")"
elseif degr == 1 then
status = "degraded"
end
local members = {}
local c = 1
for member in nixio.fs.glob("/sys/block/" .. name .. "/md/dev-*") do
local dname = nixio.fs.basename(nixio.fs.readlink(member .. "/block"))
local dsize = disp_size(tonumber(nixio.fs.readfile(member .. "/block/size")))
local dstate = nixio.fs.readfile(member .. "/state"):gsub("_", " "):match "^%s*(.-)%s*$"
table.insert(members, { name = dname, size = dsize, state = dstate, color = colors[c] })
c = c + 1
end
table.insert(raid, {name=name, rlevel=rlevel, ndisks=ndisks, size=size, metav=metav, status=status, members=members })
end
end
if show_disc == 1 then
for dev in nixio.fs.glob("/sys/class/nvme/*/device/nvme/*") do
local section
local model = nixio.fs.readfile(dev .. "/model")
local fw = nixio.fs.readfile(dev .. "/firmware_rev")
for bdev in nixio.fs.glob(dev .. "/nvme*") do
local section
local name = nixio.fs.basename(bdev)
local size = tonumber(nixio.fs.readfile(bdev .. "/size"))
local unused = size
local status = "-"
local temp = "-"
local serial = "-"
local secsize = "-"
for _,line in ipairs(luci.util.execl("smartctl -A -i -d nvme -n standby -f brief /dev/" .. name)) do
local attrib, val
if section == 1 then
attrib, val = line:match "^(.*):%s*(.*)"
elseif section == 2 then
attrib, val = line:match("^([0-9 ]*) [^ ]* * [POSRCK-]* *[0-9-]* *[0-9-]* *[0-9-]* *[0-9-]* *([0-9-]*)")
else
attrib = line:match "^=== START OF (.*) SECTION ==="
if attrib == "INFORMATION" then
section = 1
elseif attrib == "READ SMART DATA" then
section = 2
elseif status == "-" then
val = line:match "^Device is in (.*) mode"
if val then
status = val:lower()
end
end
end
if not attrib then
if section ~= 2 then section = 0 end
elseif (attrib == "Power mode is") or (attrib == "Power mode was") then
status = val:lower():match "(%S*)"
elseif attrib == "Serial Number" then
serial = val
elseif attrib == "194" then
temp = val .. "&deg;C"
end
end
table.insert(devinfo, {name=name, model=model, fw=fw, size=size, serial=serial, parts=get_parts(name,status,size) })
end
end
end
if show_raid == 1 and #devinfo > 0 then %>
<div class="cbi-section">
<h3><%:NVMe SSD%></h3>
<table class="cbi-section-table" style="white-space: nowrap">
<tr>
<th width="5%">&nbsp;</th>
<th width="30%"><%:Model%></th>
<th width="25%"><%:Serial number%></th>
<th width="20%"><%:Firmware%></th>
<th width="20%"><%:Capacity%></th>
<!-- <th width="10%"><%:Temperature%></th>-->
</tr>
<% local style=true
for d,dev in ipairs(devinfo) do %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
<td class="cbi-vluae-field" style="padding-bottom:0px; border-bottom-width:0px; vertical-align:middle" rowspan="4"><%=dev.name%></td>
<td class="cbi-value-field" style="padding-bottom:0px; border-bottom-width:0px" rowspan="2"><%=dev.model%></td>
<td class="cbi-value-field" style="padding-bottom:0px; border-bottom-width:0px" rowspan="2"><%=dev.serial%></td>
<td class="cbi-value-field" style="padding-bottom:0px; border-bottom-width:0px" rowspan="2"><%=dev.fw%></td>
<td class="cbi-value-field" style="padding-bottom:0px; border-bottom-width:0px" rowspan="2"><%=disp_size(dev.size)%></td>
<!-- <td class="cbi-value-field" style="padding-bottom:0px; border-bottom-width:0px" rowspan="2"><%=dev.temp%></td>-->
</tr>
<tr style="height:0px" />
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
<td style="padding:0px; border-top-width:0px" colspan="7" rowspan="2">
<table style="border: 0pt; border-collapse:collapse; width:100%; padding:0px; margin:0px"><tr>
<% for _,part in pairs(dev.parts) do %>
<td style="text-align:center; padding: 0px 4px; border-radius: 3px; background-color:#<%=part.color%>" width="<%=part.perc%>%"><%=part.name%> <%=disp_size(part.size)%> <%=part.fs%></td>
<% end %>
</tr></table>
</td>
</tr>
<tr style="height:0px" />
<% style = not style
end %>
</table>
</div>
<% end %>

35
autoshare-ksmbd/Makefile Normal file
View File

@ -0,0 +1,35 @@
#
# Copyright (C) 2010-2011 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=autoshare-ksmbd
PKG_VERSION:=1
PKG_RELEASE:=11
PKG_ARCH:=all
include $(INCLUDE_DIR)/package.mk
define Package/autoshare-ksmbd
TITLE:=Samba autoconfig hotplug script.
MAINTAINER:=Lean
DEPENDS:=+wsdd2
endef
define Package/autoshare-ksmbd/description
A hotplug script to config Samba share automatically.
endef
define Build/Compile
endef
define Package/autoshare-ksmbd/install
$(INSTALL_DIR) $(1)/etc/hotplug.d/block
$(INSTALL_BIN) ./files/20-smb-ksmbd $(1)/etc/hotplug.d/block/20-smb-ksmbd
endef
$(eval $(call BuildPackage,autoshare-ksmbd))

View File

@ -0,0 +1,113 @@
#!/bin/sh
#
# D-Team Technology Co.,Ltd. ShenZhen
# 作者:Vic
#
# 警告:对着屏幕的哥们,我们允许你使用此脚本,但不允许你抹去作者的信息,请保留这段话。
#
. /lib/functions.sh
. /lib/functions/service.sh
global=0
config_file="/etc/config/ksmbd"
[ ! -f /etc/config/ksmbd ] && {
echo "
config globals
option 'workgroup' 'WORKGROUP'
option 'description' 'Ksmbd on OpenWrt'
" > $config_file
}
wait_for_init() {
for i in `seq 30`
do
[ -e /tmp/procd.done ] || {
sleep 1; continue;
}
return
done
}
smb_handle() {
config_get path $1 path
if [ "$path" = "$2" ] ;then
global=1
fi
}
chk_en() {
config_get_bool autoshare $1 autoshare 1
[ $autoshare -eq 0 ] && exit
}
config_load ksmbd
config_foreach chk_en ksmbd
device=`basename $DEVPATH`
case "$ACTION" in
add)
case "$device" in
sd*);;
md*);;
hd*);;
*) return;;
esac
path="/dev/$device"
wait_for_init
cat /proc/mounts | while read j
do
str=${j%% *}
if [ "$str" == $path ];then
strr=${j#* }
target=${strr%% *}
global=0
config_foreach smb_handle share $target
name=${target#*/mnt/}
name=$(echo $name | sed -e "s/^\///")
if [ $global -eq 0 ] ;then
echo -e "\n\nconfig share" >> $config_file
echo -e "\toption auto '1'" >> $config_file
echo -e "\toption name '$name'" >> $config_file
echo -e "\toption path '$target'" >> $config_file
echo -e "\toption read_only 'no'" >> $config_file
echo -e "\toption guest_ok 'yes'" >> $config_file
echo -e "\toption create_mask '0666'" >> $config_file
echo -e "\toption dir_mask '0777'" >> $config_file
echo -e "\toption device '$device'" >> $config_file
echo -e "\toption force_root '1'" >> $config_file
/etc/init.d/ksmbd reload
return
fi
fi
done
;;
remove)
i=0
while true
do
dev=`uci get ksmbd.@share[$i].device`
[ $? -ne 0 ] && break
[ "$dev" = "$device" ] && {
auto=`uci get ksmbd.@share[$i].auto`
[ $auto = "1" ] && {
mount_dir=`uci get ksmbd.@share[$i].name`
uci delete ksmbd.@share[$i]
uci commit
/etc/init.d/ksmbd reload
return
}
}
let i+=1
done
;;
esac

35
autoshare-samba/Makefile Normal file
View File

@ -0,0 +1,35 @@
#
# Copyright (C) 2010-2011 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=autoshare-samba
PKG_VERSION:=1
PKG_RELEASE:=11
PKG_ARCH:=all
include $(INCLUDE_DIR)/package.mk
define Package/autoshare-samba
TITLE:=Samba autoconfig hotplug script.
MAINTAINER:=Lean
DEPENDS:=+wsdd2
endef
define Package/autoshare-samba/description
A hotplug script to config Samba share automatically.
endef
define Build/Compile
endef
define Package/autoshare-samba/install
$(INSTALL_DIR) $(1)/etc/hotplug.d/block
$(INSTALL_BIN) ./files/20-smb $(1)/etc/hotplug.d/block/20-smb
endef
$(eval $(call BuildPackage,autoshare-samba))

View File

@ -0,0 +1,114 @@
#!/bin/sh
#
# D-Team Technology Co.,Ltd. ShenZhen
# 作者:Vic
#
# 警告:对着屏幕的哥们,我们允许你使用此脚本,但不允许你抹去作者的信息,请保留这段话。
#
. /lib/functions.sh
. /lib/functions/service.sh
global=0
config_file="/etc/config/samba4"
[ ! -f /etc/config/samba4 ] && {
echo "
config samba
option workgroup 'WORKGROUP'
option charset 'UTF-8'
option description 'Samba on OpenWRT'
" > $config_file
}
wait_for_init() {
for i in `seq 30`
do
[ -e /tmp/procd.done ] || {
sleep 1; continue;
}
return
done
}
smb_handle() {
config_get path $1 path
if [ "$path" = "$2" ] ;then
global=1
fi
}
chk_en() {
config_get_bool autoshare $1 autoshare 1
[ $autoshare -eq 0 ] && exit
}
config_load samba4
config_foreach chk_en samba4
device=`basename $DEVPATH`
case "$ACTION" in
add)
case "$device" in
sd*);;
md*);;
hd*);;
*) return;;
esac
path="/dev/$device"
wait_for_init
cat /proc/mounts | while read j
do
str=${j%% *}
if [ "$str" == $path ];then
strr=${j#* }
target=${strr%% *}
global=0
config_foreach smb_handle sambashare $target
name=${target#*/mnt/}
name=$(echo $name | sed -e "s/^\///")
if [ $global -eq 0 ] ;then
echo -e "\n\nconfig sambashare" >> $config_file
echo -e "\toption auto '1'" >> $config_file
echo -e "\toption name '$name'" >> $config_file
echo -e "\toption path '$target'" >> $config_file
echo -e "\toption read_only 'no'" >> $config_file
echo -e "\toption guest_ok 'yes'" >> $config_file
echo -e "\toption create_mask '0666'" >> $config_file
echo -e "\toption dir_mask '0777'" >> $config_file
echo -e "\toption device '$device'" >> $config_file
echo -e "\toption force_root '1'" >> $config_file
/etc/init.d/samba4 reload
return
fi
fi
done
;;
remove)
i=0
while true
do
dev=`uci get samba4.@sambashare[$i].device`
[ $? -ne 0 ] && break
[ "$dev" = "$device" ] && {
auto=`uci get samba4.@sambashare[$i].auto`
[ $auto = "1" ] && {
mount_dir=`uci get samba4.@sambashare[$i].name`
uci delete samba4.@sambashare[$i]
uci commit
/etc/init.d/samba4 reload
return
}
}
let i+=1
done
;;
esac

41
bpytop/Makefile Normal file
View File

@ -0,0 +1,41 @@
# SPDX-License-Identifier: GPL-3.0-only
#
# Copyright (C) 2021 ImmortalWrt.org
include $(TOPDIR)/rules.mk
PKG_NAME:=bpytop
PKG_VERSION:=1.0.67
PKG_RELEASE:=$(AUTORELEASE)
PYPI_NAME:=bpytop
PKG_HASH:=skip
PKG_LICENSE:=Apache-2.0
PKG_LICENSE_FILES:=LICENSE
include ../../lang/python/pypi.mk
include $(INCLUDE_DIR)/package.mk
include ../../lang/python/python3-package.mk
define Package/bpytop
SECTION:=admin
CATEGORY:=Administration
TITLE:=Python port of bashtop
URL:=https://github.com/aristocratos/bpytop
DEPENDS:=+python3-psutil +python3-setuptools
endef
define Package/bpytop/description
Resource monitor that shows usage and stats for
processor, memory, disks, network and processes.
endef
define Py3Package/bpytop/install
$(INSTALL_DIR) $(1)/usr/share
$(CP) $(PKG_BUILD_DIR)/themes $(1)/usr/share/bpytop
endef
$(eval $(call Py3Package,bpytop))
$(eval $(call BuildPackage,bpytop))
$(eval $(call BuildPackage,bpytop-src))

79
cdnspeedtest/Makefile Normal file
View File

@ -0,0 +1,79 @@
#
# Copyright (C) 2021 ImmortalWrt
# <https://immortalwrt.org>
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=CloudflareSpeedTest
PKG_VERSION:=1.5.1
PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/XIU2/CloudflareSpeedTest/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=skip
PKG_LICENSE:=GPL-3.0
PKG_LICENSE_FILE:=LICENSE
PKG_MAINTAINER:=CN_SZTL <cnsztl@immortalwrt.org>
PKG_CONFIG_DEPENDS:= \
CONFIG_CDNSPEEDTEST_COMPRESS_GOPROXY \
CONFIG_CDNSPEEDTEST_COMPRESS_UPX
PKG_BUILD_DEPENDS:=golang/host
PKG_BUILD_PARALLEL:=1
PKG_USE_MIPS16:=0
GO_PKG:=CloudflareSpeedTest
GO_PKG_LDFLAGS:=-s -w
GO_PKG_LDFLAGS_X:=main.version=v$(PKG_VERSION)
include $(INCLUDE_DIR)/package.mk
include ../../lang/golang/golang-package.mk
define Package/cdnspeedtest
SECTION:=net
CATEGORY:=Network
TITLE:=Getting the fastest ips to your network of CDN
URL:=https://github.com/XIU2/CloudflareSpeedTest
DEPENDS:=$(GO_ARCH_DEPENDS)
endef
define Package/cdnspeedtest/config
config CDNSPEEDTEST_COMPRESS_GOPROXY
bool "Compiling with GOPROXY proxy"
default n
config CDNSPEEDTEST_COMPRESS_UPX
bool "Compress executable files with UPX"
default y
endef
ifeq ($(CONFIG_CDNSPEEDTEST_COMPRESS_GOPROXY),y)
export GO111MODULE=on
export GOPROXY=https://goproxy.baidu.com
endif
define Build/Compile
$(call GoPackage/Build/Compile)
ifeq ($(CONFIG_CDNSPEEDTEST_COMPRESS_UPX),y)
$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/CloudflareSpeedTest
endif
endef
define Package/cdnspeedtest/install
$(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/CloudflareSpeedTest $(1)/usr/bin/cdnspeedtest
$(INSTALL_DIR) $(1)/usr/share/CloudflareSpeedTest
$(INSTALL_DATA) $(PKG_BUILD_DIR)/ip.txt $(1)/usr/share/CloudflareSpeedTest/
$(INSTALL_DATA) $(PKG_BUILD_DIR)/ipall.txt $(1)/usr/share/CloudflareSpeedTest/
$(INSTALL_DATA) $(PKG_BUILD_DIR)/ipv6.txt $(1)/usr/share/CloudflareSpeedTest/
endef
$(eval $(call BuildPackage,cdnspeedtest))

266
cups/Makefile Normal file
View File

@ -0,0 +1,266 @@
#
# Copyright (C) 2006-2016 OpenWrt.org
# Copyright (C) 2016 lede-project.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=cups
PKG_VERSION:=2.3.0
PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-source.tar.gz
PKG_SOURCE_URL:=https://github.com/apple/cups/releases/download/v$(PKG_VERSION)
PKG_MD5SUM:=skip
TARGET_LDFLAGS+=-Wl,-rpath-link=$(STAGING_DIR)/usr/lib
include $(INCLUDE_DIR)/package.mk
define Package/cups/Default
URL:=http://www.cups.org/
SUBMENU:=Printing
endef
define Package/cups
$(call Package/cups/Default)
SECTION:=net
CATEGORY:=Network
DEPENDS:=+libcups +libusb-1.0 +libstdcpp
TITLE:=Common UNIX Printing System (daemon)
endef
define Package/cups/description
Common UNIX Printing System (daemon)
endef
define Package/cups/conffiles
/etc/cups/classes.conf
/etc/cups/cupsd.conf
/etc/cups/printers.conf
endef
define Package/cups-bsd
$(call Package/cups/Default)
SECTION:=net
CATEGORY:=Network
DEPENDS:=+libcups
TITLE:=Common UNIX Printing System - BSD commands (old)
endef
define Package/cups-bsd/description
Common UNIX Printing System - BSD commands (old)
endef
define Package/cups-client
$(call Package/cups/Default)
SECTION:=net
CATEGORY:=Network
DEPENDS:=+libcups +libcupsimage
TITLE:=Common UNIX Printing System - Client commands
endef
define Package/cups-client/conffiles
/etc/cups/client.conf
endef
define Package/cups-client/description
Common UNIX Printing System - Client commands
endef
define Package/cups-filters
$(call Package/cups/Default)
SECTION:=net
CATEGORY:=Network
DEPENDS:=+libcupsimage
TITLE:=Common UNIX Printing System - Filter
endef
define Package/cups-filters/description
Common UNIX Printing System - Filter
endef
define Package/cups-ppdc
$(call Package/cups/Default)
SECTION:=net
CATEGORY:=Network
DEPENDS:=+libcups +zlib +libpthread +libpng +libjpeg +libstdcpp
TITLE:=Common UNIX Printing System - PPDC utils
endef
define Package/cups-ppdc/description
Common UNIX Printing System - PPDC utils
endef
define Package/libcups
$(call Package/cups/Default)
SECTION:=libs
CATEGORY:=Libraries
DEPENDS:=+zlib +libpthread +libpng +libjpeg
TITLE:=Common UNIX Printing System - Core library
endef
define Package/libcups/description
Common UNIX Printing System - Core library
endef
define Package/libcupsimage
$(call Package/cups/Default)
SECTION:=libs
CATEGORY:=Libraries
DEPENDS:=+libcups
TITLE:=Common UNIX Printing System - Image library
endef
define Package/libcupsimage/description
Common UNIX Printing System - Image library
endef
define Build/Configure
$(call Build/Configure/Default, \
--with-cups-user="nobody" \
--with-cups-group="nogroup" \
--with-system-groups="root" \
--with-pdftops="none" \
--without-perl \
--without-python \
--without-php \
--enable-default-shared \
--enable-shared \
--enable-image \
--enable-libusb \
--disable-acl \
--disable-dnssd \
--disable-dbus \
--disable-avahi \
--disable-launchd \
--disable-ldap \
--disable-pam \
--disable-slp \
--disable-gnutls \
--disable-openssl \
--disable-cdsassl \
--disable-ssl \
--disable-gssapi \
--disable-tiff, \
UNAME="Linux" \
LIBS="$(TARGET_LDFLAGS) -lz -lpng -ljpeg" \
)
endef
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
$(TARGET_CONFIGURE_OPTS) \
DSTROOT="$(PKG_INSTALL_DIR)" \
STRIP="/bin/true" \
all install
endef
define Package/cups/install
rm -rf $(1)/etc/cups
$(INSTALL_DIR) $(1)/etc/cups
$(CP) $(PKG_INSTALL_DIR)/etc/cups/* $(1)/etc/cups/
rm -rf $(1)/etc/cups/certs
ln -sf /tmp $(1)/etc/cups/certs
rm -f $(1)/usr/bin/cups-config
$(INSTALL_DIR) $(1)/usr/lib/cups
$(CP) $(PKG_INSTALL_DIR)/usr/lib/cups/backend $(1)/usr/lib/cups
$(CP) $(PKG_INSTALL_DIR)/usr/lib/cups/cgi-bin $(1)/usr/lib/cups
$(CP) $(PKG_INSTALL_DIR)/usr/lib/cups/daemon $(1)/usr/lib/cups
$(CP) $(PKG_INSTALL_DIR)/usr/lib/cups/driver $(1)/usr/lib/cups
$(CP) $(PKG_INSTALL_DIR)/usr/lib/cups/monitor $(1)/usr/lib/cups
$(INSTALL_DIR) $(1)/usr/share/cups/templates
$(CP) $(PKG_INSTALL_DIR)/usr/share/cups/templates/*.tmpl \
$(1)/usr/share/cups/templates/
$(INSTALL_DIR) $(1)/usr/share/cups/mime
$(CP) $(PKG_INSTALL_DIR)/usr/share/cups/mime/* $(1)/usr/share/cups/mime/
### Do install docs: cups web interface relies on them
$(INSTALL_DIR) $(1)/usr/share/doc/cups
$(CP) $(PKG_INSTALL_DIR)/usr/share/doc/cups/*.*html \
$(1)/usr/share/doc/cups/
$(CP) $(PKG_INSTALL_DIR)/usr/share/doc/cups/*.css \
$(1)/usr/share/doc/cups/
$(CP) $(PKG_INSTALL_DIR)/usr/share/doc/cups/*.txt \
$(1)/usr/share/doc/cups/
$(CP) $(PKG_INSTALL_DIR)/usr/share/doc/cups/images \
$(1)/usr/share/doc/cups/
$(INSTALL_DIR) $(1)/usr/sbin
# overwrite default config with our own
$(CP) ./files/etc/cups/* $(1)/etc/cups/
# install initscript with priority 60
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/cupsd.init $(1)/etc/init.d/cupsd
$(INSTALL_BIN) \
$(PKG_INSTALL_DIR)/usr/sbin/{cupsctl,cupsd} \
$(1)/usr/sbin/
# needed for cups to find usb printers per http://wiki.openwrt.org/doc/howto/cups.server
chmod 700 $(1)/usr/lib/cups/backend/usb
endef
define Package/cups-bsd/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/{lprm,lpq,lpr} $(1)/usr/bin/
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/lpc $(1)/usr/sbin/
endef
define Package/cups-client/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) \
$(PKG_INSTALL_DIR)/usr/bin/{lp,cancel,cupstestppd} \
$(PKG_INSTALL_DIR)/usr/bin/{ipptool,lpoptions,lpstat} \
$(1)/usr/bin/
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) \
$(PKG_INSTALL_DIR)/usr/sbin/{cupsaccept,cupsfilter} \
$(PKG_INSTALL_DIR)/usr/sbin/{lpadmin,lpinfo,lpmove} \
$(1)/usr/sbin/
(cd $(1)/usr/sbin; ln -sf cupsaccept accept; ln -sf cupsaccept cupsenable; ln -sf cupsaccept cupsdisable; ln -sf cupsaccept reject; ln -sf cupsaccept cupsreject;)
$(INSTALL_DIR) $(1)/usr/share/cups/ipptool
$(CP) $(PKG_INSTALL_DIR)/usr/share/cups/ipptool/* \
$(1)/usr/share/cups/ipptool
endef
define Package/cups-filters/install
$(INSTALL_DIR) $(1)/usr/lib/cups/filter
$(CP) $(PKG_INSTALL_DIR)/usr/lib/cups/filter/{commandtops,gziptoany,pstops,rastertoepson,rastertohp,rastertolabel,rastertopwg} \
$(1)/usr/lib/cups/filter
(cd $(1)/usr/lib/cups/filter; ln -sf rastertolabel rastertodymo;)
endef
define Package/cups-ppdc/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) \
$(PKG_INSTALL_DIR)/usr/bin/{ppdc,ppdhtml,ppdi,ppdmerge,ppdpo} \
$(1)/usr/bin/
endef
define Package/libcups/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libcups.so* $(1)/usr/lib/
endef
define Package/libcupsimage/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libcupsimage.so* $(1)/usr/lib/
endef
define Build/InstallDev
$(INSTALL_DIR) $(2)/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/cups-config $(2)/bin/
$(INSTALL_DIR) $(1)/usr/include
$(CP) $(PKG_INSTALL_DIR)/usr/include/cups $(1)/usr/include/
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libcups*.so* $(1)/usr/lib/
endef
$(eval $(call BuildPackage,cups))
$(eval $(call BuildPackage,libcups))
$(eval $(call BuildPackage,libcupsimage))
$(eval $(call BuildPackage,cups-bsd))
$(eval $(call BuildPackage,cups-client))
$(eval $(call BuildPackage,cups-filters))
$(eval $(call BuildPackage,cups-ppdc))

27
cups/files/cupsd.init Normal file
View File

@ -0,0 +1,27 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2006-2011 OpenWrt.org
START=50
start() {
enable=$(uci get cupsd.config.enabled 2>/dev/null)
if [ $enable -eq 1 ]; then
sed -i 's/Port [0-9]*/Port '"$(uci get cupsd.config.port)"'/g' /etc/cups/cupsd.conf
mkdir -m 0755 -p /var/cache/cups
mkdir -m 0755 -p /var/cups
mkdir -m 0755 -p /var/spool/cups/tmp
service_start /usr/sbin/cupsd
fi
}
stop() {
service_stop /usr/sbin/cupsd
kill $(pidof cupsd) >/dev/null 2>&1 || killall -9 cupsd >/dev/null 2>&1
}
reload(){
stop
sleep 2
start
echo "cupsd Server has restarted."
}

View File

@ -0,0 +1,7 @@
########################################################################
# #
# This is a sample class configuration file. This file is included #
# from the main configuration file (cups.conf) and lists all of the #
# printer classes known to the system. #
# #
########################################################################

View File

@ -0,0 +1,9 @@
########################################################################
# #
# This is the CUPS client configuration file. This file is used to #
# define client-specific parameters, such as the default server or #
# default encryption settings. #
# #
########################################################################
Encryption Never

View File

@ -0,0 +1,58 @@
########################################################################
# #
# This is the CUPS configuration file. If you are familiar with #
# Apache or any of the other popular web servers, we've followed the #
# same format. Any configuration variable used here has the same #
# semantics as the corresponding variable in Apache. If we need #
# different functionality then a different name is used to avoid #
# confusion... #
# #
########################################################################
AccessLog syslog
ErrorLog syslog
LogLevel info
PageLog syslog
PreserveJobHistory No
PreserveJobFiles No
AutoPurgeJobs Yes
MaxJobs 25
MaxPrinterHistory 10
#Printcap /etc/printcap
#PrintcapFormat BSD
RequestRoot /var/cups
#RemoteRoot remroot
#User nobody
#Group nogroup
# root permissions required to make cups work with the usb backend
User root
Group root
RIPCache auto
TempDir /var/cups
Port 631
HostNameLookups On
KeepAlive On
# No: "BrowseOrder" "BrowseAllow" "BrowseRemoteProtocols"
Browsing Yes
BrowsingWebIF Yes
BrowseLocalProtocols DNSSD
DefaultShared Yes
WebInterface Yes
Listen /var/run/cups/cups.sock
ServerAlias *
<Location />
Order Allow,Deny
Allow From 127.0.0.1
Allow From 192.168.0.0/16
</Location>
<Location /admin>
AuthType Basic
AuthClass System
Order Allow,Deny
Allow From 127.0.0.1
Allow From 192.168.0.0/16
</Location>

View File

@ -0,0 +1,23 @@
<DefaultPrinter USB>
Info USB Printer
Location
DeviceURI usb:/dev/usb/lp0
State Idle
Accepting Yes
JobSheets none none
QuotaPeriod 0
PageLimit 0
KLimit 0
</Printer>
<Printer LP>
Info Parallel Port Printer
Location
DeviceURI parallel:/dev/printers/0
State Idle
Accepting Yes
JobSheets none none
QuotaPeriod 0
PageLimit 0
KLimit 0
</Printer>

View File

@ -0,0 +1,33 @@
--- a/config-scripts/cups-directories.m4
+++ b/config-scripts/cups-directories.m4
@@ -102,7 +102,7 @@ if test "$libdir" = "\${exec_prefix}/lib"; then
case "$host_os_name" in
linux*)
if test -d /usr/lib64 -a ! -d /usr/lib64/fakeroot; then
- libdir="$exec_prefix/lib64"
+ libdir="$exec_prefix/lib"
fi
;;
esac
--- "a/configure"
+++ "b/configure"
@@ -6188,7 +6188,7 @@ if test "$libdir" = "\${exec_prefix}/lib"; then
case "$host_os_name" in
linux*)
if test -d /usr/lib64 -a ! -d /usr/lib64/fakeroot; then
- libdir="$exec_prefix/lib64"
+ libdir="$exec_prefix/lib"
fi
;;
esac
--- a/cups-config.in
+++ b/cups-config.in
@@ -48,7 +48,7 @@ else
CFLAGS="$CFLAGS -I$includedir"
fi
- if test $libdir != /usr/lib -a $libdir != /usr/lib32 -a $libdir != /usr/lib64; then
+ if test $libdir != /usr/lib -a $libdir != /usr/lib -a $libdir != /usr/lib; then
LDFLAGS="$LDFLAGS -L$libdir"
fi
fi

View File

@ -1,42 +0,0 @@
# 项目迁移了,请看:
项目已经迁移到新地址https://github.com/linkease/nas-packages
# ddnsto-openwrt
ddnsto for openwrt
## 使用方法
把文件夹 ddnsto 拷贝到 Openwrt 源代码的 package/network/services 里面,拷贝之后为:
```
tree package/network/services/ddnsto
package/network/services/ddnsto
├── files
│   ├── ddnsto.config
│   ├── ddnsto.init
│   └── ddnsto.uci-default
└── Makefile
```
### make menuconfig 选择方法
```
make menuconfig
Network --->
Web Servers/Proxies --->
<*> ddnsto....................................... DDNS.to - the reverse proxy
LuCI --->
3. Applications --->
<*> luci-app-ddnsto.................................. LuCI support for ddnsto
```
### 部分 Openwrt 老版本兼容性问题
安装完成点击配置,需要手动运行命令:
```
/etc/init.d/ddnsto enable
```

View File

@ -14,7 +14,7 @@ PKG_VERSION:=0.3.0
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://firmware.koolshare.cn/binary/ddnsto/
PKG_HASH:=cefd2494cb1c21e2c1616290f715dd6415cd460aafc107c38bb9910c13f42448
PKG_HASH:=skip
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-binary-$(PKG_VERSION)

51
default-settings/Makefile Normal file
View File

@ -0,0 +1,51 @@
#
# Copyright (C) 2010-2011 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=default-settings
PKG_VERSION:=1
PKG_RELEASE:=10
include $(INCLUDE_DIR)/package.mk
define Package/default-settings
SECTION:=luci
CATEGORY:=LuCI
TITLE:=Default Settings
MAINTAINER:=Kiddin'
PKGARCH:=all
DEPENDS:=+luci-base
endef
define Package/default-settings/conffiles
/etc/config/base_config
endef
define Build/Compile
endef
define Package/default-settings/install
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_DATA) ./files/uci.defaults $(1)/etc/uci-defaults/95-default-settings
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_DATA) ./files/base_config.conf $(1)/etc/config/base_config
$(INSTALL_DIR) $(1)/lib/wifi
$(INSTALL_DATA) ./files/wifi-init.sh $(1)/lib/wifi/wifi-init.sh
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/wifi-init.init $(1)/etc/init.d/wifi-init
$(INSTALL_DIR) $(1)/etc/rc.d
$(INSTALL_BIN) ./files/opkg.rc.d $(1)/etc/rc.d/S99opkg
$(INSTALL_DIR) $(1)/etc/profile.d
$(INSTALL_BIN) ./files/sysinfo.sh $(1)/etc/profile.d/sysinfo.sh
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n
po2lmo ./po/zh_Hans/default.po $(1)/usr/lib/lua/luci/i18n/default.zh-cn.lmo
endef
$(eval $(call BuildPackage,default-settings))

View File

@ -0,0 +1,3 @@
config status
option version '0'
option base '1'

View File

@ -0,0 +1,93 @@
#!/bin/sh
LOCK=/var/lock/opkgupgrade.lock
BKOPKG="/etc/backup"
# 防止重复启动
[ -f $LOCK ] && exit 1
touch $LOCK
mkdir -p $BKOPKG
if [ ! -f /etc/inited ]; then
[ "$(uci -q get dhcp.@dnsmasq[0].noresolv)" ] && {
uci -q del dhcp.@dnsmasq[0].noresolv
uci commit dhcp
service dnsmasq reload
}
# sh -c "cat '/usr/share/patch/adblock.patch' | patch -d '/' -p1 --forward" >/dev/null 2>&1
fi
if [ ! -f "$BKOPKG/user_installed.opkg" ]; then
touch /etc/inited
fi
function opkgupgrade() {
c1=0
c2=0
c3=0
while ! curl --retry 3 -m 5 https://op.supes.top >/dev/null 2>&1;do
echo "无法连接仓库服务器,请检查网络. $c1" | sed -e "s/^/$(date +%Y-%m-%d" "%H:%M:%S) /" >>/tmp/opkgupdate.log
[ $c1 == 120 ] && return || let c1++
sleep 5
done
while :; do
opkg update | sed -e "s/^/$(date +%Y-%m-%d" "%H:%M:%S) /" >>/tmp/opkgupdate.log 2>&1
if [ "$?" == "0" ]; then
def="$(opkg list-upgradable | cut -f 1 -d ' ' | grep -vE 'opkg|luci-lib-fs|firewall|base-files|luci-base|busybox|dnsmasq-full|coremark|miniupnpd|luci-mod-network|luci-mod-status|luci-mod-system')"
if [ ! -f /etc/inited ]; then
insed="$(cat $BKOPKG/user_installed.opkg)"
fi
upopkg="$insed $def"
if [ "$upopkg" != " " ]; then
for ipk in $upopkg; do
while :; do
opkg install --force-overwrite --force-checksum --force-depends $ipk | sed -e "s/^/$(date +%Y-%m-%d" "%H:%M:%S) /" >>/tmp/opkgupdate.log 2>&1 || true
if [[ $ipk == luci-app-* ]]; then
opkg install --force-overwrite --force-checksum luci-i18n-"$(echo $ipk | cut -d - -f 3-4)"-zh-cn | sed -e "s/^/$(date +%Y-%m-%d" "%H:%M:%S) /" >>/tmp/opkgupdate.log 2>&1 || true
fi
[[ "$(opkg list-installed | grep $ipk)" ]] && {
break
}
[ $c2 == 3 ] && {
echo $ipk >> $BKOPKG/failed.txt
sed -i '/$ipk/d' $BKOPKG/user_installed.opkg
break
} || let c2++
sleep 1
rm -f /var/lock/opkg.lock
done
done
rm -f /etc/config/*-opkg
fi
[[ -f $BKOPKG/failed.txt && -f /etc/inited ]] && {
for ipk in $(cat $BKOPKG/failed.txt); do
opkg install --force-overwrite --force-checksum --force-depends $ipk | sed -e "s/^/$(date +%Y-%m-%d" "%H:%M:%S) /" >>/tmp/opkgupdate.log 2>&1 || true
[[ "$(opkg list-installed | grep $ipk)" ]] && {
sed -i '/$ipk/d' $BKOPKG/failed.txt
}
done
mv $BKOPKG/failed.txt $BKOPKG/failed_.txt
}
touch /etc/inited
rm -f /var/lock/opkg.lock
break
fi
[ $c3 == 10 ] && break || let c3++
done
rm -f /var/lock/opkg.lock
}
(
if [[ ! -f /etc/inited || -f $BKOPKG/failed.txt ]]; then
opkgupgrade || true
elif [[ -f /etc/inited && `uci -q get system.@system[0].autoupgrade_pkg || echo "1"` != '0' ]]; then
opkgupgrade || true
fi
rm -f /var/lock/opkg.lock
[[ -f "/bin/coremark" && ! -f "/etc/bench.log" ]] && {
sleep 5
/bin/coremark >/tmp/coremark.log
cat /tmp/coremark.log | grep "CoreMark 1.0" | cut -d "/" -f 1 >/etc/bench.log
sed -i 's/CoreMark 1.0/(CpuMark/g' /etc/bench.log
echo " Scores)" >>/etc/bench.log
}
rm -f $LOCK
) &

View File

@ -0,0 +1,151 @@
#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
export LANG=zh_CN.UTF-8
THIS_SCRIPT="sysinfo"
MOTD_DISABLE=""
SHOW_IP_PATTERN="^[ewr].*|^br.*|^lt.*|^umts.*"
DATA_STORAGE=/userdisk/data
MEDIA_STORAGE=/userdisk/snail
[[ -f /etc/default/motd ]] && . /etc/default/motd
for f in $MOTD_DISABLE; do
[[ $f == $THIS_SCRIPT ]] && exit 0
done
# don't edit below here
function display()
{
# $1=name $2=value $3=red_limit $4=minimal_show_limit $5=unit $6=after $7=acs/desc{
# battery red color is opposite, lower number
if [[ "$1" == "Battery" ]]; then
local great="<";
else
local great=">";
fi
if [[ -n "$2" && "$2" > "0" && (( "${2%.*}" -ge "$4" )) ]]; then
printf "%-14s%s" "$1:"
if awk "BEGIN{exit ! ($2 $great $3)}"; then
echo -ne "\e[0;91m $2";
else
echo -ne "\e[0;92m $2";
fi
printf "%-1s%s\x1B[0m" "$5"
printf "%-11s%s\t" "$6"
return 1
fi
} # display
function get_ip_addresses()
{
local ips=()
for f in /sys/class/net/*; do
local intf=$(basename $f)
# match only interface names starting with e (Ethernet), br (bridge), w (wireless), r (some Ralink drivers use ra<number> format)
if [[ $intf =~ $SHOW_IP_PATTERN ]]; then
local tmp=$(ip -4 addr show dev $intf | awk '/inet/ {print $2}' | cut -d'/' -f1)
# add both name and IP - can be informative but becomes ugly with long persistent/predictable device names
#[[ -n $tmp ]] && ips+=("$intf: $tmp")
# add IP only
[[ -n $tmp ]] && ips+=("$tmp")
fi
done
echo "${ips[@]}"
} # get_ip_addresses
function storage_info()
{
# storage info
RootInfo=$(df -h /)
root_usage=$(awk '/\// {print $(NF-1)}' <<<${RootInfo} | sed 's/%//g')
root_total=$(awk '/\// {print $(NF-4)}' <<<${RootInfo})
# storage info
[ -d /boot ] && {
BootInfo=$(df -h /boot) 2>/dev/null
boot_usage=$(awk '/\// {print $(NF-1)}' <<<${BootInfo} | sed 's/%//g')
boot_total=$(awk '/\// {print $(NF-4)}' <<<${BootInfo})
}
StorageInfo=$(df -h $MEDIA_STORAGE 2>/dev/null | grep $MEDIA_STORAGE)
if [[ -n "${StorageInfo}" && ${RootInfo} != *$MEDIA_STORAGE* ]]; then
media_usage=$(awk '/\// {print $(NF-1)}' <<<${StorageInfo} | sed 's/%//g')
media_total=$(awk '/\// {print $(NF-4)}' <<<${StorageInfo})
fi
StorageInfo=$(df -h $DATA_STORAGE 2>/dev/null | grep $DATA_STORAGE)
if [[ -n "${StorageInfo}" && ${RootInfo} != *$DATA_STORAGE* ]]; then
data_usage=$(awk '/\// {print $(NF-1)}' <<<${StorageInfo} | sed 's/%//g')
data_total=$(awk '/\// {print $(NF-4)}' <<<${StorageInfo})
fi
} # storage_info
# query various systems and send some stuff to the background for overall faster execution.
# Works only with ambienttemp and batteryinfo since A20 is slow enough :)
ip_address=$(get_ip_addresses &)
storage_info
critical_load=$(( 1 + $(grep -c processor /proc/cpuinfo) / 2 ))
# get uptime, logged in users and load in one take
UptimeString=$(uptime | tr -d ',')
time=$(awk -F" " '{print $3" "$4}' <<<"${UptimeString}")
load="$(awk -F"average: " '{print $2}'<<<"${UptimeString}")"
case ${time} in
1:*) # 1-2 hours
time=$(awk -F" " '{print $3" 小时"}' <<<"${UptimeString}")
;;
*:*) # 2-24 hours
time=$(awk -F" " '{print $3" 小时"}' <<<"${UptimeString}")
;;
*day) # days
days=$(awk -F" " '{print $3"天"}' <<<"${UptimeString}")
time=$(awk -F" " '{print $5}' <<<"${UptimeString}")
time="$days "$(awk -F":" '{print $1"小时 "$2"分钟"}' <<<"${time}")
;;
esac
# memory and swap
mem_info=$(LC_ALL=C free -w 2>/dev/null | grep "^Mem" || LC_ALL=C free | grep "^Mem")
memory_usage=$(awk '{printf("%.0f",(($2-($4+$6))/$2) * 100)}' <<<${mem_info})
memory_total=$(awk '{printf("%d",$2/1024)}' <<<${mem_info})
swap_info=$(LC_ALL=C free -m | grep "^Swap")
swap_usage=$( (awk '/Swap/ { printf("%3.0f", $3/$2*100) }' <<<${swap_info} 2>/dev/null || echo 0) | tr -c -d '[:digit:]')
swap_total=$(awk '{print $(2)}' <<<${swap_info})
# display info
display "系统负载" "${load%% *}" "${critical_load}" "0" "" "${load#* }"
printf "运行时间: \x1B[92m%s\x1B[0m\t\t" "$time"
echo "" # fixed newline
display "内存已用" "$memory_usage" "70" "0" " %" " of ${memory_total}MB"
display "交换内存" "$swap_usage" "10" "0" " %" " of $swap_total""Mb"
printf "IP 地址: \x1B[92m%s\x1B[0m" "$ip_address"
echo "" # fixed newline
a=0;b=0;c=0
display "CPU 温度" "$board_temp" "45" "0" "°C" "" ; a=$?
display "环境温度" "$amb_temp" "40" "0" "°C" "" ; b=$?
(( ($a+$b) >0 )) && echo "" # new line only if some value is displayed
display "启动存储" "$boot_usage" "90" "1" "%" " of $boot_total"
display "系统存储" "$root_usage" "90" "1" "%" " of $root_total"
echo ""
display "数据存储" "$data_usage" "90" "1" "%" " of $data_total"
display "媒体存储" "$media_usage" "90" "1" "%" " of $media_total"
echo ""
echo ""

View File

View File

@ -0,0 +1,34 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2020 X-WRT.COM
START=19
boot() {
. /lib/wifi/wifi-init.sh
local base wifi_init
local SSID SSID_PASSWD
base=`uci get base_config.@status[0].base 2>/dev/null`
base=$((base+0))
wifi_init=`uci get base_config.@status[0].wifi_init 2>/dev/null`
wifi_init=$((wifi_init+0))
test $base -lt 1 && {
wifi_init=1 #skip wifi_init=1 hook
}
test $wifi_init -lt 1 && {
wifi_first_init
wifi_init=1
}
uci set base_config.@status[0].wifi_init=$wifi_init
uci commit base_config
#XXX
test -f /rom/etc/uci-defaults/96-wizard-defaults && sh /rom/etc/uci-defaults/96-wizard-defaults
/etc/init.d/wifi-init disable
}

View File

@ -0,0 +1,81 @@
#!/bin/sh
wifi_setup_radio()
{
local radio=$1
uci get wireless.${radio} >/dev/null 2>&1 && {
#FIXME hack
local path
if test -e /sys/kernel/debug/ieee80211/phy0/mt76/dbdc &&
[ "$(readlink /sys/class/ieee80211/phy0/device)" = "$(readlink /sys/class/ieee80211/phy1/device)" ]; then
path="$(uci get wireless.${radio}.path)"
if test -z "${path#*+1}"; then
uci set wireless.${radio}.phy='phy1'
uci set wireless.${radio}.htmode='VHT80'
uci set wireless.${radio}.hwmode='11a'
else
uci set wireless.${radio}.phy='phy0'
uci set wireless.${radio}.htmode='HT20'
uci set wireless.${radio}.hwmode='11g'
fi
uci delete wireless.${radio}.path
fi
uci -q batch <<-EOT
set wireless.${radio}.disabled='0'
set wireless.${radio}.country='CN'
set wireless.${radio}.channel='auto'
EOT
if [ x`uci get wireless.${radio}.hwmode 2>/dev/null` = "x11a" ]; then
uci set wireless.${radio}.txpower='23'
else
uci set wireless.${radio}.txpower='20'
fi
obj=`uci add wireless wifi-iface`
test -n "$obj" && {
uci set wireless.$obj.device="${radio}"
uci set wireless.$obj.network='lan'
uci set wireless.$obj.mode='ap'
if [ x`uci get wireless.${radio}.hwmode 2>/dev/null` = "x11a" ]; then
uci set wireless.$obj.ssid="${SSID}_5G"
else
uci set wireless.$obj.ssid="${SSID}_2.4G"
fi
# uci set wireless.$obj.encryption='psk2'
uci set wireless.$obj.skip_inactivity_poll='1'
uci set wireless.$obj.wpa_group_rekey='0'
uci set wireless.$obj.wpa_pair_rekey='0'
uci set wireless.$obj.wpa_master_rekey='0'
uci set wireless.$obj.disassoc_low_ack='0'
# uci set wireless.$obj.key="${SSID_PASSWD}"
}
}
}
wifi_first_init()
{
SSID="${SSID-$(uci get base_config.@status[0].SSID 2>/dev/null || echo OpenWrt)}"
SSID_PASSWD="${SSID_PASSWD-$(uci get base_config.@status[0].SSID_PASSWD 2>/dev/null || echo 88888888)}"
while uci delete wireless.@wifi-iface[0] >/dev/null 2>&1; do :; done
for radio in radio0 radio1 radio2 radio3 wifi0 wifi1 wifi2 wifi3; do
wifi_setup_radio ${radio}
done
uci commit wireless
# wireless migration
local widx=0
local change=0
while uci rename wireless.@wifi-iface[$widx]=wifinet$widx >/dev/null 2>&1; do widx=$((widx+1)); done
uci changes wireless | tr ".='" " " | while read _ a b; do
if [ "x$a" != "x$b" ]; then
uci commit wireless
change=1
break
fi
done
[ "x$change" = "x0" ] && uci revert wireless
}

View File

@ -0,0 +1,166 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2021-04-12 14:21+0000\n"
"Language: zh_Hans\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 4.5-dev\n"
msgid "Processor"
msgstr "处理器"
msgid "Architecture"
msgstr "架构"
msgid "CPU Temperature"
msgstr "CPU 温度"
msgid "CPU Info"
msgstr "CPU 信息"
msgid "CPU Model"
msgstr "处理器型号"
msgid "CPU frequency"
msgstr "CPU 频率"
msgid "RAM frequency"
msgstr "RAM 频率"
msgid "Flash Size"
msgstr "闪存大小"
msgid "Free Memory"
msgstr "释放内存"
msgid "RUNNING"
msgstr "运行中"
msgid "NOT RUNNING"
msgstr "未运行"
msgid "ZRam Settings"
msgstr "ZRam 设置"
msgid "ZRam Compression Algorithm"
msgstr "ZRam 压缩算法"
msgid "ZRam Compression Streams"
msgstr "ZRam 压缩数据流线程数"
msgid "ZRam Size"
msgstr "ZRam 大小"
msgid "Size of the ZRam device in megabytes"
msgstr "划分给 ZRam 分区的内存大小MB推荐留空由系统自动管理"
msgid "Number of parallel threads used for compression"
msgstr "用于压缩内存数据的CPU并发线程数"
msgid "Swap"
msgstr "虚拟内存"
msgid "Force 40MHz mode"
msgstr "强制 40MHz 频宽"
msgid ""
"Always use 40MHz channels even if the secondary channel overlaps. Using this "
"option does not comply with IEEE 802.11n-2009!"
msgstr "强制启用 40MHz 频宽并忽略辅助信道重叠。此选项可能不兼容某些无线硬件导致无法启用!"
msgid "Disassociate On Low Acknowledgement"
msgstr "弱信号剔除"
msgid "Allow AP mode to disconnect STAs based on low ACK condition"
msgstr "允许 AP 模式基于低 ACK 条件判断剔除弱信号的客户端"
msgid "Running Status"
msgstr "运行状况"
msgid "Online Users"
msgstr "在线用户数"
msgid "DNS Redirect"
msgstr "DNS 重定向"
msgid "Redirect client DNS to dnsmasq"
msgstr "重定向客户端DNS到dnsmasq"
msgid "Enable 256-QAM"
msgstr "启用 256-QAM"
msgid "802.11n 2.4Ghz Only"
msgstr "只适合 802.11n 2.4Ghz"
msgid "Enables The 802.11k standard provides information to discover the best available access point"
msgstr "启用 802.11k 自动寻找发现最佳可用接入点的信息"
msgid "Enable neighbor report via radio measurements"
msgstr "启用无线电测量邻居报告"
msgid "Enable beacon report via radio measurements"
msgstr "启用无线电测量信标报告"
msgid "Enables 802.11v allows client devices to exchange information about the network topology,tating overall improvement of the wireless network."
msgstr "启用 802.11v 将允许客户端设备交换有关网络拓扑的信息,从而全面改善无线网络漫游"
msgid "extended sleep mode for stations"
msgstr "扩展无线休眠节能模式"
msgid "BSS Transition Management"
msgstr "BSS 传输管理"
msgid "UTC time at which the TSF timer is 0"
msgstr "TSF计时器为0的UTC时间"
msgid "Time advertisement"
msgstr "广播同步时间"
msgid "time zone"
msgstr "时区"
msgid "Local time zone as specified in 8.3 of IEEE Std 1003.1-2004"
msgstr "本地时区采用 IEEE Std 1003.1-2004 的 8.3 格式(例如 UTC8"
msgid "Custom Redirect Domain"
msgstr "自定义挟持域名"
msgid "Define a custom domain name and the corresponding PTR record"
msgstr "自定义域名对应的IP地址需要客户端DNS指向本路由"
msgid "Domain Name"
msgstr "域名(不带 HTTP(S)://"
msgid "Comments"
msgstr "备注"
msgid "Retain the current packages"
msgstr "保留已安装软件包"
msgid "Packet Steering"
msgstr "数据包引导"
msgid "Enable packet steering across all CPUs. May help or hinder network speed."
msgstr "启用所有CPU的数据包控制。 可能有助于或阻碍网络速度。"
msgid "Disable IPv6 DNS forwards"
msgstr "禁止解析 IPv6 DNS 记录"
msgid "Filter IPv6(AAAA) DNS Query Name Resolve"
msgstr "过滤掉 IPv6(AAAA) ,只返回 IPv4 DNS 域名记录"
msgid "Minimum TTL to send to clients"
msgstr "客户端缓存的最小 DNS TTL"
msgid "Modify DNS entries minimum TTL (max is 86400, 0 is no modify)"
msgstr "修改发送到客户端的域名记录的 TTL 时间 (最大 86400, 0 表示不修改)"
msgid "Firmware Settings"
msgstr "固件设置"
msgid "Packages Auto Upgrade"
msgstr "软件包自动更新"
msgid "Firmware Upgrade Notice"
msgstr "固件更新提醒"

View File

@ -1,85 +0,0 @@
#
# Copyright (C) 2021 ImmortalWrt
# <https://immortalwrt.org>
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=gost
PKG_VERSION:=2.11.1
PKG_RELEASE:=23
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/ginuerzh/gost/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=skip
PKG_LICENSE:=MIT
PKG_LICENSE_FILE:=LICENSE
PKG_MAINTAINER:=CN_SZTL <cnsztl@immortalwrt.org>
PKG_CONFIG_DEPENDS:= \
CONFIG_GOST_COMPRESS_GOPROXY \
CONFIG_GOST_COMPRESS_UPX
PKG_BUILD_DEPENDS:=golang/host
PKG_BUILD_PARALLEL:=1
PKG_USE_MIPS16:=0
GO_PKG:=github.com/ginuerzh/gost
GO_PKG_BUILD_PKG:=github.com/ginuerzh/gost/cmd/gost
GO_PKG_LDFLAGS:=-s -w
include $(INCLUDE_DIR)/package.mk
include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk
define Package/gost
SECTION:=net
CATEGORY:=Network
TITLE:=GO Simple Tunnel
URL:=https://github.com/ginuerzh/gost
DEPENDS:=$(GO_ARCH_DEPENDS)
endef
define Package/gost/description
A simple security tunnel written in Golang
endef
define Package/gost/config
config GOST_COMPRESS_GOPROXY
bool "Compiling with GOPROXY proxy"
default n
config GOST_COMPRESS_UPX
bool "Compress executable files with UPX"
default y
endef
ifeq ($(CONFIG_GOST_COMPRESS_GOPROXY),y)
export GO111MODULE=on
export GOPROXY=https://goproxy.baidu.com
endif
define Build/Compile
$(call GoPackage/Build/Compile)
ifeq ($(CONFIG_GOST_COMPRESS_UPX),y)
$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/gost
endif
endef
define Package/gost/install
$(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gost $(1)/usr/bin/gost
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) $(CURDIR)/files/gost.config $(1)/etc/config/gost
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) $(CURDIR)/files/gost.init $(1)/etc/init.d/gost
endef
$(eval $(call GoBinPackage,gost))
$(eval $(call BuildPackage,gost))

View File

@ -1,5 +0,0 @@
config gost
option enable '0'
option run_command ''

View File

@ -1,22 +0,0 @@
#!/bin/sh /etc/rc.common
# Created By ImmortalWrt
# https://github.com/project-openwrt
START=90
STOP=10
enable="$(uci get gost.@gost[0].enable)"
run_command="$(uci get gost.@gost[0].run_command)"
start()
{
stop
[ "${enable}" -ne "1" ] && exit 0
/usr/bin/gost ${run_command} &
}
stop()
{
killall -9 "gost" > "/dev/null" 2>&1
}

50
iptvhelper/Makefile Normal file
View File

@ -0,0 +1,50 @@
# Copyright 2019 Shun Li <riverscn@gmail.com>
# Licensed to the public under the GNU General Public License v3.
include $(TOPDIR)/rules.mk
PKG_NAME:=iptvhelper
PKG_VERSION:=0.1.1
PKG_RELEASE:=1
PKG_MAINTAINER:=Shun Li <riverscn@gmail.com>
PKG_LICENSE:=GPL-3.0
include $(INCLUDE_DIR)/package.mk
define Package/iptvhelper
SECTION:=net
CATEGORY:=Network
SUBMENU:=Routing and Redirection
DEPENDS:= \
+ipset \
+iptables
TITLE:=Scripts for configure IPTV easily
MAINTAINER:=Shun Li <riverscn@gmail.com>
PKGARCH:=all
endef
define Package/iptvhelper/description
Scripts for configure IPTV easily
endef
define Package/iptvhelper/conffiles
/etc/config/iptvhelper
/etc/firewall.iptvhelper
endef
define Build/Compile
endef
define Package/iptvhelper/postinst
#!/bin/sh
endef
define Package/iptvhelper/postrm
#!/bin/sh
endef
define Package/iptvhelper/install
$(CP) ./files/* $(1)
endef
$(eval $(call BuildPackage,iptvhelper))

View File

@ -0,0 +1,8 @@
config tvbox 'default'
option disabled '1'
option respawn '1'
option mac '00:00:00:00:00:00'
option ipset '1'
option dns_redir '1'

View File

@ -0,0 +1,2 @@
#!/bin/sh
test -s "/etc/init.d/iptvhelper" && /etc/init.d/iptvhelper reload

View File

@ -0,0 +1,127 @@
#!/bin/sh /etc/rc.common
# Copyright 2019 Shun Li <riverscn@gmail.com>
# Licensed to the public under the GNU General Public License v3.
START=95
USE_PROCD=1
_ipt() {
cmd="$(echo "$@" | sed 's|-A|-D|g;s|-I|-D|g')"
while iptables $cmd &>/dev/null; do
:
done
iptables $@
}
destroy_iptv_ipset() {
for ip_set in $(ipset list | awk '/iptvhelper/ {print $2}'); do ipset destroy $ip_set; done
}
clear_iptv_rules() {
iptables-save --counters | grep -v "iptvhelper-rule" | iptables-restore --counters
}
append_arg() {
local cfg="$1"
local var="$2"
local opt="$3"
local def="$4"
local val
config_get val "$cfg" "$var"
[ -n "$val" -o -n "$def" ] && procd_append_param command $opt "${val:-$def}"
}
append_bool() {
local cfg="$1"
local var="$2"
local opt="$3"
local def="$4"
local val
config_get_bool val "$cfg" "$var" "$def"
[ "$val" = 1 ] && procd_append_param command "$opt"
}
start_instance() {
local cfg="$1"
local aux
config_get_bool aux "$cfg" 'disabled' '0'
[ "$aux" = 1 ] && return 1
logger "iptvhelper.$cfg: instance starting"
local IPTV_MAC
local IPTV_DNS_REDIR
local IPTV_IPSET
config_get IPTV_MAC $cfg mac
config_get IPTV_DNS_REDIR $cfg dns_redir
config_get IPTV_IPSET $cfg ipset
logger "iptvhelper.$cfg: topbox mac=$IPTV_MAC"
if [[ $IPTV_DNS_REDIR == '1' ]]; then
logger "iptvhelper.$cfg: topbox DNS redierct enabled"
_ipt -t nat -A PREROUTING -m mac --mac-source $IPTV_MAC -m comment --comment "iptvhelper-rule" -p udp --dport 53 -j REDIRECT --to-ports 53
fi
if [[ $IPTV_IPSET='1' ]]; then
logger "iptvhelper.$cfg: topbox ipset enabled"
if ! ipset -q list iptvhelper_$cfg >/dev/null; then
ipset create iptvhelper_$cfg nethash
fi
_ipt -t nat -I PREROUTING -m mac --mac-source $IPTV_MAC -m comment --comment "iptvhelper-rule" -m set ! --match-set iptvhelper_$cfg dst -m conntrack --ctstate NEW -j LOG --log-prefix "iptvhelper.$cfg:"
procd_open_instance
procd_set_param command /usr/sbin/iptvhelper.sh $cfg
config_get_bool aux "$cfg" 'respawn' '0'
[ "$aux" = 1 ] && procd_set_param respawn
procd_set_param pidfile /var/run/iptvhelper_$cfg.pid
procd_close_instance
fi
}
service_triggers() {
procd_add_reload_trigger "iptvhelper"
}
start_service() {
logger "iptvhelper: starting"
echo "iptvhelper: starting"
config_load iptvhelper
config_foreach start_instance tvbox
if uci -q show firewall >/dev/null; then
if ! uci -q get firewall.iptvhelper >/dev/null; then
uci -q batch <<-EOF >/dev/null
set firewall.iptvhelper=include
set firewall.iptvhelper.type='script'
set firewall.iptvhelper.path='/etc/firewall.iptvhelper'
set firewall.iptvhelper.family='any'
set firewall.iptvhelper.reload='1'
commit firewall
EOF
fi
fi
}
stop_service() {
if uci -q show firewall >/dev/null; then
if uci -q get firewall.iptvhelper >/dev/null; then
uci delete firewall.iptvhelper
uci commit firewall
fi
fi
for pid in $(ps | grep -v awk | awk '/iptvhelper.sh/ {print $1}'); do kill -9 $pid; done
for pid in $(ps | grep -v awk | awk '/logread -e iptvhelper/ {print $1}'); do kill -9 $pid; done
clear_iptv_rules
destroy_iptv_ipset
logger "iptvhelper: stopped"
echo "iptvhelper: stopped"
}
reload_service() {
logger "iptvhelper: reloading"
echo "iptvhelper: reloading"
stop
start
}

View File

@ -0,0 +1,24 @@
#!/bin/sh
# Copyright 2019 Shun Li <riverscn@gmail.com>
# Licensed to the public under the GNU General Public License v3.
add_to_set() {
local ip=$1
local cfg=$2
local subnet=$ip/24
ping -W1 -c1 $ip &>/dev/null && return
if ! ipset -q test iptvhelper_$cfg $subnet; then
ipset add iptvhelper_$cfg $subnet
echo added $subnet to set iptvhelper_$cfg
fi
}
echo $1
logread -e "iptvhelper\.$1" -f |
while read line; do
ip=$(echo "$line" | sed -r 's|.*DST=([0-9.]+).*|\1|')
echo requested $ip
add_to_set $ip $1 &
done

42
jpcre2/Makefile Normal file
View File

@ -0,0 +1,42 @@
# SPDX-License-Identifier: GPL-3.0-only
#
# Copyright (C) 2021 ImmortalWrt.org
include $(TOPDIR)/rules.mk
PKG_NAME:=jpcre2
PKG_VERSION:=10.32.01
PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/jpcre2/jpcre2/tar.gz/$(PKG_VERSION)?
PKG_HASH:=skip
PKG_LICENSE:=BSD 3-Clause
PKG_LICENSE_FILES:=LICENSE
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
PKG_BUILD_DEPENDS:=pcre2
PKG_BUILD_PARALLEL:=1
PKG_INSTALL:=1
include $(INCLUDE_DIR)/package.mk
define Package/jpcre2
SECTION:=lib
CATEGORY:=Libraries
TITLE:=C++ wrapper for PCRE2 Library
URL:=https://github.com/jpcre2/jpcre2
endef
define Package/jpcre2/description
This provides some C++ wrapper classes/functions to perform regex
operations such as regex match and regex replace.
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/include
$(CP) $(PKG_INSTALL_DIR)/usr/include/jpcre2.hpp $(1)/usr/include/jpcre2.hpp
endef
$(eval $(call BuildPackage,jpcre2))

46
libcron/Makefile Normal file
View File

@ -0,0 +1,46 @@
# SPDX-License-Identifier: GPL-3.0-only
#
# Copyright (C) 2021 ImmortalWrt.org
include $(TOPDIR)/rules.mk
PKG_NAME:=libcron
PKG_VERSION:=1.3.0
PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/PerMalmberg/libcron.git
PKG_SOURCE_DATE:=2020-12-04
PKG_SOURCE_VERSION:=b0046755bda166dde253e33f68a5b0a1c3ed387e
PKG_MIRROR_HASH:=skip
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
PKG_BUILD_PARALLEL:=1
CMAKE_INSTALL:=1
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/libcron
SECTION:=lib
CATEGORY:=Libraries
URL:=https://github.com/PerMalmberg/libcron
TITLE:=A C++ scheduling library using cron formatting
endef
define Package/libcron/description
Libcron offers an easy to use API to add callbacks with corresponding cron-formatted strings.
endef
define Build/Install
$(INSTALL_DIR) $(PKG_INSTALL_DIR)/usr/lib/
$(CP) $(PKG_BUILD_DIR)/libcron/out/Release/liblibcron.a $(PKG_INSTALL_DIR)/usr/lib/
$(INSTALL_DIR) $(PKG_INSTALL_DIR)/usr/include/libcron/
$(CP) $(PKG_BUILD_DIR)/libcron/include/* $(PKG_INSTALL_DIR)/usr/include/
$(CP) $(PKG_BUILD_DIR)/libcron/externals/date/include/* $(PKG_INSTALL_DIR)/usr/include/
endef
$(eval $(call BuildPackage,libcron))

15
luci-app-amule/Makefile Normal file
View File

@ -0,0 +1,15 @@
# Copyright (C) 2016 Openwrt.org
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for Amule
LUCI_DEPENDS:=+amule
LUCI_PKGARCH:=all
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,161 @@
--[[
LuCI - Lua Configuration Interface - amule support
Copyright 2016 maz-1 <ohmygod19993@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
]]--
module("luci.controller.amule", package.seeall)
local uci = luci.model.uci.cursor()
local configdir = uci:get("amule", "main", "config_dir")
function index()
if not nixio.fs.access("/etc/config/amule") then
return
end
entry({"admin", "nas"}, firstchild(), "NAS", 45).dependent = false
local page = entry({"admin", "nas", "amule"}, cbi("amule"), _("aMule Settings"))
page.dependent = true
page.acl_depends = { "luci-app-amule" }
entry( {"admin", "nas", "amule", "logview"}, call("logread") ).leaf = true
entry( {"admin", "nas", "amule", "status"}, call("get_pid") ).leaf = true
entry( {"admin", "nas", "amule", "amulecmd"}, call("amulecmd") ).leaf = true
entry( {"admin", "nas", "amule", "startstop"}, post("startstop") ).leaf = true
entry( {"admin", "nas", "amule", "down_kad"}, post("down_kad") ).leaf = true
entry( {"admin", "nas", "amule", "down_ed2k"}, post("down_ed2k") ).leaf = true
end
-- called by XHR.get from detail_logview.htm
function logread()
-- read application settings
local uci = luci.model.uci.cursor()
local logdir = uci:get("amule", "main", "config_dir") or "/var/run/amule"
uci:unload("amule")
local ldata=nixio.fs.readfile(logdir .. "/logfile")
if not ldata or #ldata == 0 then
ldata="_nodata_"
end
luci.http.write(ldata)
end
-- called by XHR.get from detail_startstop.htm
function startstop()
local pid = get_pid(true)
if pid > 0 then
luci.sys.call("/etc/init.d/amule stop")
nixio.nanosleep(1) -- sleep a second
if nixio.kill(pid, 0) then -- still running
nixio.kill(pid, 9) -- send SIGKILL
end
pid = 0
else
luci.sys.call("/etc/init.d/amule start")
nixio.nanosleep(1) -- sleep a second
pid = tonumber(luci.sys.exec("pidof amuled")) or 0
if pid > 0 and not nixio.kill(pid, 0) then
pid = 0 -- process did not start
end
end
luci.http.write(tostring(pid)) -- HTTP needs string not number
end
function down_kad()
url = uci:get("amule", "main", "kad_nodes_url")
data_path = configdir .. "/nodes.dat"
proto = string.gsub(url, "://%S*", "")
proto_opt = ( proto == "https" ) and " --no-check-certificate" or ""
cmd = "wget -O /tmp/down_nodes.dat \"" .. url .. "\"" .. proto_opt ..
" && cat /tmp/down_nodes.dat > " .. "\"" .. data_path .. "\""
luci.sys.call(cmd)
end
function down_ed2k()
url = uci:get("amule", "main", "ed2k_servers_url")
data_path = configdir .. "/server.met"
proto = string.gsub(url, "://%S*", "")
proto_opt = ( proto == "https" ) and " --no-check-certificate" or ""
cmd = "wget -O /tmp/down_server.met \"" .. url .. "\"" .. proto_opt ..
" && cat /tmp/down_server.met > " .. "\"" .. data_path .. "\""
luci.sys.call(cmd)
end
-- called by XHR.poll from detail_startstop.htm
-- and from lua (with parameter "true")
function get_pid(from_lua)
local pid_amuled = tonumber(luci.sys.exec("pidof amuled")) or 0
local amuled_stat =false
if pid_amuled > 0 and not nixio.kill(pid_amuled, 0) then
pid_amuled = 0
end
if pid_amuled > 0 then
amuled_stat =true
else
amuled_stat =false
end
local pid_amuleweb = tonumber(luci.sys.exec("pidof amuleweb")) or 0
local amuleweb_stat = false
if pid_amuleweb > 0 and not nixio.kill(pid_amuleweb, 0) then
pid_amuleweb = 0
end
if pid_amuleweb > 0 then
amuleweb_stat =true
else
amuleweb_stat =false
end
local status = {
amuled = amuled_stat,
amuled_pid = pid_amuled,
amuleweb = amuleweb_stat
}
if from_lua then
return pid_amuled
else
luci.http.prepare_content("application/json")
luci.http.write_json(status)
end
end
function amulecmd()
local re =""
local rv = { }
local cmd = luci.http.formvalue("cmd")
local full_cmd = "HOME=\""..configdir.. "\" /usr/bin/amulecmd".." -c \""..cmd.."\" 2>&1"
local shellpipe = io.popen(full_cmd,"rw")
re = shellpipe:read("*a")
shellpipe:close()
if not re then
re=""
end
re = string.gsub(re, "This is amulecmd %S*\n", "")
re = string.gsub(re, "Creating client%S*\n", "")
re = string.gsub(re, "Succeeded! Connection established to aMule %S*\n", "")
re = string.gsub(re, "\n", "\r\n")
rv[#rv+1]=re
if #rv > 0 then
luci.http.prepare_content("application/json")
luci.http.write_json(rv)
return
end
luci.http.status(404, "No such device")
end

View File

@ -0,0 +1,456 @@
--[[
LuCI - Lua Configuration Interface - Aria2 support
Copyright 2016 maz-1 <ohmygod19993@gmail.com>
]]--
local sys = require "luci.sys"
local util = require "luci.util"
local uci = require "luci.model.uci".cursor()
ptype = {
"socks5",
"socks4",
"http",
"socks4a",
}
whocan = {
"anyone",
"friends",
"nobody",
}
function titlesplit(Value)
return "<p style=\"font-size:20px;font-weight:bold;color: DodgerBlue\">" .. translate(Value) .. "</p>"
end
m = Map("amule", translate("aMule"), translate("aMule is a ED2K/KAD client for all platforms.") .. "<br/><a href=\"https://github.com/maz-1\">luci interface by maz-1</a>")
m:section(SimpleSection).template = "amule/overview_status"
s = m:section(TypedSection, "amule", translate("aMule Settings"))
s.addremove = false
s.anonymous = true
s:tab("general", translate("General"))
s:tab("connection", translate("Connections"))
s:tab("server", translate("Server"))
s:tab("path_and_file", translate("Path And File"))
s:tab("security", translate("Security"))
s:tab("remote", translate("External Control"))
s:tab("template", translate("Edit Template"))
s:tab("logview", translate("Log File Viewer"))
s:tab("amulecmd", translate("aMule command"))
-- GENERAL --
o = s:taboption("general", Flag, "enabled", translate("Enabled"))
o.rmempty = false
user = s:taboption("general", ListValue, "runasuser", translate("Run daemon as user"))
local p_user
for _, p_user in util.vspairs(util.split(sys.exec("cat /etc/passwd | cut -f 1 -d :"))) do
user:value(p_user)
end
o = s:taboption("general", Value, "config_dir", translate("Configuration directory"))
o.rmempty = false
o.placeholder = "/var/run/amule"
o = s:taboption("general", Value, "mem_percentage", translate("Memory Limit"), translate("Percentage"))
o.rmempty = false
o.placeholder = "50"
o.datatype = "range(1, 99)"
o = s:taboption("general", Value, "nick", translate("Nickname"))
o.placeholder = "http://www.aMule.org"
o = s:taboption("general", Value, "max_upload", translate("Max upload speed"), translate("Unlimited when set to 0"))
o.datatype = "uinteger"
o.rmempty = false
o.placeholder = "0"
o = s:taboption("general", Value, "max_download", translate("Max download speed"), translate("Unlimited when set to 0"))
o.datatype = "uinteger"
o.rmempty = false
o.placeholder = "0"
o = s:taboption("general", Value, "slot_allocation", translate("Slot allocation"))
o.datatype = "uinteger"
o.rmempty = false
o.placeholder = "2"
o = s:taboption("general", Value, "max_connections", translate("Max connections"))
o.datatype = "uinteger"
o.rmempty = false
o.placeholder = "500"
o = s:taboption("general", Value, "max_sources_per_file", translate("Max sources per file"))
o.datatype = "uinteger"
o.rmempty = false
o.placeholder = "300"
-- CONNECTIONS --
o = s:taboption("connection", Value, "port", translate("TCP port"))
o.datatype = "port"
o.rmempty = false
o.placeholder = "4662"
o = s:taboption("connection", Flag, "udp_enable", translate("Enable UDP port"))
o.rmempty = false
o = s:taboption("connection", Value, "udp_port", translate("UDP port"))
o.datatype = "port"
o.rmempty = false
o.placeholder = "4672"
o = s:taboption("connection", Flag, "upnp_enabled", translate("Enable UPnP"))
o.rmempty = false
o = s:taboption("connection", Value, "upnp_tcp_port", translate("UPnP TCP port"))
o.datatype = "port"
o.rmempty = false
o.placeholder = "50000"
o = s:taboption("connection", Value, "address", translate("Bind Address"), translate("Leave blank to bind all"))
o.datatype = "ip4addr"
o.rmempty = true
o = s:taboption("connection", Flag, "auto_connect", translate("Automatically connect"))
o.rmempty = false
o = s:taboption("connection", Flag, "reconnect", translate("Automatically reconnect"))
o.rmempty = false
o = s:taboption("connection", Flag, "connect_to_kad", translate("Connect to Kad network"))
o.rmempty = false
o = s:taboption("connection", Flag, "connect_to_ed2k", translate("Connect to ED2K network"))
o.rmempty = false
s:taboption("connection", DummyValue,"titlesplit1" ,titlesplit(translate("Proxy Configuration")))
o = s:taboption("connection", Flag, "proxy_enable_proxy", translate("Enable proxy"))
o.rmempty = false
o = s:taboption("connection", ListValue, "proxy_type", translate("Proxy type"))
for i,v in ipairs(ptype) do
o:value(v)
end
o.rmempty = false
o = s:taboption("connection", Value, "proxy_name", translate("Proxy name"))
o.rmempty = true
o = s:taboption("connection", Value, "proxy_port", translate("Proxy port"))
o.datatype = "port"
o.rmempty = true
o = s:taboption("connection", Flag, "proxy_enable_password", translate("Proxy requires authentication"))
o.rmempty = true
o = s:taboption("connection", Value, "proxy_user", translate("Proxy user"))
--o:depends("proxy_enable_password", "1")
o.rmempty = true
o = s:taboption("connection", Value, "proxy_password", translate("Proxy password"))
o.password = true
o.rmempty = true
-- SERVER --
o = s:taboption("server", Value, "kad_nodes_url", translate("Kad Nodes Url"), "<input type=\"button\" size=\"0\" title=\""
.. translate("Download now") .. "\" onclick=\"onclick_down_kad(this.id)\" "
.. "value=\"&#10597;&#10597;&#10597;\" "
.. "style=\"font-weight:bold;text-decoration:overline;\""
.. "/>")
o.rmempty = false
o.placeholder = "http://upd.emule-security.org/nodes.dat"
o = s:taboption("server", Value, "ed2k_servers_url", translate("Ed2k Servers List Url"), "<input type=\"button\" size=\"0\" title=\""
.. translate("Download now") .. "\" onclick=\"onclick_down_ed2k(this.id)\" "
.. "value=\"&#10597;&#10597;&#10597;\" "
.. "style=\"font-weight:bold;text-decoration:overline;\""
.. "/>")
o.rmempty = false
o.placeholder = "http://upd.emule-security.org/server.met"
o = s:taboption("server", Flag, "remove_dead_server", translate("Remove Dead Server"))
o.rmempty = false
o = s:taboption("server", Value, "dead_server_retry", translate("Dead Server Retry"))
--o:depends("remove_dead_server", "1")
o.datatype = "uinteger"
o.rmempty = false
o.placeholder = "3"
o.default = "3"
o = s:taboption("server", Flag, "add_server_list_from_server", translate("Update server list when connecting to a server"))
o.rmempty = false
o = s:taboption("server", Flag, "add_server_list_from_client", translate("Update server list when a client connects"))
o.rmempty = false
o = s:taboption("server", Flag, "scoresystem", translate("Use priority system"))
o.rmempty = false
o = s:taboption("server", Flag, "smart_id_check", translate("Use smart LowID check on connect"))
o.rmempty = false
o = s:taboption("server", Flag, "safe_server_connect", translate("Safe connect"))
o.rmempty = false
o = s:taboption("server", Flag, "auto_connect_static_only", translate("Auto connect to servers in static list only"))
o.rmempty = false
o = s:taboption("server", Flag, "manual_high_prio", translate("Set manually added servers to high priority"))
o.rmempty = false
o = s:taboption("server", Flag, "serverlist", translate("Auto update server list at startup"), translate("addresses.dat file"))
o.rmempty = false
addr = s:taboption("server", Value, "addresses", translate("Server addresses"),
translate("Content of addresses.dat. One address per line"))
addr:depends("serverlist", "1")
addr.template = "cbi/tvalue"
addr.rows = 5
addr.rmempty = true
function addr.cfgvalue(self, section)
return nixio.fs.readfile("/etc/amule/addresses.dat")
end
function addr.write(self, section, value)
value = value:gsub("\r\n?", "\n")
nixio.fs.writefile("//etc/amule/addresses.dat", value)
end
-- PATH AND FILE --
o = s:taboption("path_and_file", Value, "temp_dir", translate("Temporary directory"))
o.rmempty = false
o.placeholder = "/var/run/amule/.aMule/Temp"
o = s:taboption("path_and_file", Value, "incoming_dir", translate("Incoming directory"))
o.rmempty = false
o.placeholder = "/var/run/amule/.aMule/Incoming"
shareddir = s:taboption("path_and_file", Value, "shareddir", translate("Shared directory"),
translate("Content of shareddir.dat. One directory per line"))
shareddir.template = "cbi/tvalue"
shareddir.titleref = luci.dispatcher.build_url("admin", "system", "fstab")
shareddir.rows = 5
shareddir.rmempty = true
function shareddir.cfgvalue(self, section)
return nixio.fs.readfile("/etc/amule/shareddir.dat")
end
function shareddir.write(self, section, value)
value = value:gsub("\r\n?", "\n")
nixio.fs.writefile("//etc/amule/shareddir.dat", value)
end
o = s:taboption("path_and_file", Flag, "ich", translate("Intelligent corruption handling (I.C.H.)"))
o.rmempty = false
o = s:taboption("path_and_file", Flag, "a_ich_trust", translate("Advanced I.C.H trusts every hash (not recommended)"))
o.rmempty = false
o = s:taboption("path_and_file", Flag, "add_new_files_paused", translate("Add files to download in pause mode"))
o.rmempty = false
o = s:taboption("path_and_file", Flag, "dap_pref", translate("Add files to download with auto priority"))
o.rmempty = false
o = s:taboption("path_and_file", Flag, "start_next_file", translate("Start next paused file when a file completes"))
o.rmempty = false
o = s:taboption("path_and_file", Flag, "start_next_file_same_cat", translate("Start next paused file from the same category"))
o:depends("start_next_file", "1")
o.rmempty = true
o = s:taboption("path_and_file", Flag, "start_next_file_alpha", translate("Start next paused file in alphabetic order"))
o:depends("start_next_file", "1")
o.rmempty = true
o = s:taboption("path_and_file", Flag, "allocate_full_file", translate("Preallocate disk space for new files"))
o.rmempty = false
o = s:taboption("path_and_file", Value, "min_free_disk_space", translate("Minimum free disk space. in Mbytes"))
o.datatype = "uinteger"
o.placeholder = "1"
o.rmempty = false
o = s:taboption("path_and_file", Flag, "use_src_seed", translate("Save 10 sources on rare files (< 20 sources)"))
o.rmempty = false
o = s:taboption("path_and_file", Flag, "uap_pref", translate("Add new shares with auto priority"))
o.rmempty = false
-- SECURITY --
o = s:taboption("security", Flag, "use_sec_ident", translate("Use secure user identification"))
o.rmempty = false
o = s:taboption("security", Flag, "is_crypt_layer_requested", translate("Use obfuscation for outgoing connections"))
o.rmempty = false
o = s:taboption("security", Flag, "is_client_crypt_layer_required", translate("Accept only obfuscation connections"))
o.rmempty = false
o = s:taboption("security", ListValue, "see_share", translate("Who can see my shared files"))
for i,v in ipairs(whocan) do
o:value(v)
end
o.rmempty = false
s:taboption("security", DummyValue,"titlesplit2" ,titlesplit(translate("IP Filter Configuration")))
shareddir = s:taboption("security", Value, "ipfilter_static", translate("Static IP list for filtering"),
translate("Content of ipfilter_static.dat"))
shareddir.template = "cbi/tvalue"
shareddir.titleref = luci.dispatcher.build_url("admin", "system", "fstab")
shareddir.rows = 5
shareddir.rmempty = true
function shareddir.cfgvalue(self, section)
return nixio.fs.readfile("/etc/amule/ipfilter_static.dat")
end
function shareddir.write(self, section, value)
value = value:gsub("\r\n?", "\n")
nixio.fs.writefile("//etc/amule/ipfilter_static.dat", value)
end
o = s:taboption("security", Flag, "ip_filter_clients", translate("Filter clients by IP"))
o.rmempty = false
o = s:taboption("security", Flag, "ip_filter_servers", translate("Filter servers by IP"))
o.rmempty = false
o = s:taboption("security", Value, "ip_filter_url", translate("IP filter list URL"))
o.rmempty = true
o = s:taboption("security", Flag, "ip_filter_auto_load", translate("Auto-update ipfilter at startup"))
o.rmempty = false
o = s:taboption("security", Value, "filter_level", translate("Filtering Level"))
o.datatype = "range(1, 255)"
o.rmempty = false
o.placeholder = "127"
o = s:taboption("security", Flag, "filter_lan_ips", translate("Always filter LAN IPs"))
o.rmempty = false
o = s:taboption("security", Flag, "paranoid_filtering", translate("Paranoid handling of non-matching IPs"))
o.rmempty = false
o = s:taboption("security", Flag, "ip_filter_system", translate("Use system-wide ipfilter.dat if available"))
o.rmempty = false
-- REMOTE CONTROL --
o = s:taboption("remote", Value, "ec_address", translate("IP of the listening interface for external connection"))
o.datatype = "ip4addr"
o.placeholder = "127.0.0.1"
o.rmempty = true
o = s:taboption("remote", Value, "ec_port", translate("TCP port for EC"))
o.datatype = "port"
o.placeholder = "4712"
o.rmempty = false
o = s:taboption("remote", Flag, "upnp_ec_enabled", translate("Enable upnp port forwarding on the EC port"))
o.rmempty = false
o = s:taboption("remote", Value, "ec_password", translate("EC password"))
o.password = true
o.rmempty = false
s:taboption("remote", DummyValue,"titlesplit3", titlesplit(translate("aMule Web Configuration")))
o = s:taboption("remote", Flag, "web_enabled", translate("Enable web server on startup"))
o.rmempty = false
o = s:taboption("remote", Value, "template", translate("Web template"))
o.rmempty = false
local tpth_suggestions = luci.sys.exec("ls /usr/share/amule/webserver/|sed ':a;N;$!ba;s/\\n/:/g'")
if tpth_suggestions then
for entry in string.gmatch(tpth_suggestions, "[^:]+") do
o:value(entry)
end
end
o = s:taboption("remote", Value, "web_password", translate("Web full rights password"))
o.password = true
o.rmempty = true
o = s:taboption("remote", Flag, "use_low_rights_user", translate("Use low rights user"))
o.rmempty = false
o = s:taboption("remote", Value, "password_low", translate("Web low rights password"))
o.password = true
o.rmempty = true
o = s:taboption("remote", Value, "web_port", translate("Web TCP port"))
o.datatype = "port"
o.placeholder = "4711"
o.rmempty = false
o = s:taboption("remote", Flag, "upnp_web_server_enabled", translate("Enable UPnP port forwarding of the web server port"))
o.rmempty = false
o = s:taboption("remote", Value, "web_upnp_tcp_port", translate("Web UPnP TCP port"))
o.datatype = "port"
o.placeholder = "50001"
o.rmempty = false
o = s:taboption("remote", Value, "page_refresh_time", translate("Page refresh time(in secs)"))
o.datatype = "range(1, 600)"
o.rmempty = false
o.placeholder = "121"
o = s:taboption("remote", Flag, "use_gzip", translate("Enable Gzip compression"))
o.rmempty = false
-- TEMPLATE --
tmpl = s:taboption("template", Value, "_tmpl",
translate("Edit the template that is used for generating the aMule configuration."),
translate("This is the content of the file '/etc/amule/amule.conf.template' from which your amule configuration will be generated. " ..
"Values enclosed by pipe symbols ('|') should not be changed. They get their values from other tabs."))
tmpl.template = "cbi/tvalue"
tmpl.rows = 20
function tmpl.cfgvalue(self, section)
return nixio.fs.readfile("/etc/amule/amule.conf.template")
end
function tmpl.write(self, section, value)
value = value:gsub("\r\n?", "\n")
nixio.fs.writefile("//etc/amule/amule.conf.template", value)
end
-- LOGVIEW --
local lv = s:taboption("logview", DummyValue, "_logview")
lv.template = "amule/detail_logview"
lv.inputtitle = translate("Read / Reread log file")
lv.rows = 50
function lv.cfgvalue(self, section)
return translate("Please press [Read] button")
end
-- AMULECMD --
local cmd = s:taboption("amulecmd", DummyValue, "_amulecmd")
cmd.template = "amule/webshell"
return m

View File

@ -0,0 +1,56 @@
<!-- ++ BEGIN ++ aMule ++ detail_logview.htm ++ -->
<script type="text/javascript">//<![CDATA[
function onclick_logview(section, bottom) {
// get elements
var txt = document.getElementById("cbid.amule.main._logview.txt"); // TextArea
if ( !txt ) { return; } // security check
var lvXHR = new XHR();
lvXHR.get('<%=url('admin/nas/amule/logview')%>', null,
function(x) {
if (x.responseText == "_nodata_")
txt.value = "<%:File not found or empty%>";
else
txt.value = x.responseText;
if (bottom)
txt.scrollTop = txt.scrollHeight;
else
txt.scrollTop = 0; }
);
}
//]]></script>
<%+cbi/valueheader%>
<br />
<%
-- one button on top, one at the buttom
%>
<input class="btn cbi-button cbi-input-button" style="align: center; width: 100%" type="button" onclick="onclick_logview(this.name, false)"
<%=
attr("name", section) .. attr("id", cbid .. ".btn1") .. attr("value", self.inputtitle)
%> />
<br /><br />
<%
-- set a readable style taken from openwrt theme for textarea#syslog
-- in openwrt theme there are problems with a width of 100 so we check for theme and set to lower value
%>
<textarea style="width: <%if media == "/luci-static/openwrt.org" then%>98.7%<%else%>100%<%end%> ; min-height: 500px; border: 3px solid #cccccc; padding: 5px; font-family: monospace; resize: none;" wrap="off" readonly="readonly"
<%=
attr("name", cbid .. ".txt") .. attr("id", cbid .. ".txt") .. ifattr(self.rows, "rows")
%> >
<%-=pcdata(self:cfgvalue(section))-%>
</textarea>
<br /><br />
<%
-- one button on top, one at the buttom
%>
<input class="btn cbi-button cbi-input-button" style="align: center; width: 100%" type="button" onclick="onclick_logview(this.name, true)"
<%= attr("name", section) .. attr("id", cbid .. ".btn2") .. attr("value", self.inputtitle) %> />
<%+cbi/valuefooter%>
<!-- ++ END ++ aMule ++ detail_logview.htm ++ -->

View File

@ -0,0 +1,84 @@
<script type="text/javascript">//<![CDATA[
XHR.poll(5, '<%=luci.dispatcher.build_url("admin/nas/amule/status")%>', null,
function(x, data) {
var tb = document.getElementById('amule_status');
var btn = document.getElementById("amule_startstop");
var btn_tmpl = '<input class="btn cbi-button cbi-button-apply" id="btn_startstop" style="font-size: 100%;" value="PID: NUMBER"type="button" onclick="onclick_startstop(this.id)">'
if (data && tb) {
if (data.amuled) {
var links = '<em><%:aMule daemon is running.%></em>';
if (data.amuleweb) {
links += '<input class="cbi-button mar-10" type="button" value="<%:Open aMuleWeb%>" onclick="openwebui();" />';
}
tb.innerHTML = links;
} else {
tb.innerHTML = '<em><%:aMule daemon is not running.%></em>';
}
if (data.amuled_pid == "0") {
btn.innerHTML = btn_tmpl.replace("PID: NUMBER", "<%:Start aMule%>");
} else {
btn.innerHTML = btn_tmpl.replace("NUMBER", data.amuled_pid);
}
}
}
);
function _data2elements(x, data) {
var btn = document.getElementById("btn_startstop");
if ( ! btn ) { return; } // security check
if (data.amuled_pid == "0") {
btn.value = "<%:Start aMule%>";
btn.className = "cbi-button cbi-button-apply";
btn.disabled = false;
} else {
btn.value = "PID: " + data.amuled_pid;
btn.className = "cbi-button cbi-button-reset";
btn.disabled = false;
}
}
// event handler for start/stop button
function onclick_startstop(id) {
// do start/stop
var btnXHR = new XHR();
btnXHR.post('<%=url('admin/nas/amule/startstop')%>', { token: '<%=token%>' },
function(x, data) { _data2elements(x, data); }
);
}
// event handler for download files
function onclick_down_kad(id) {
if(confirm("<%:Existing file will be overwritten, do you really want to proceed?%>"))
{
var btnXHR = new XHR();
btnXHR.post('<%=url('admin/nas/amule/down_kad')%>', { token: '<%=token%>' },
function(x) {}
);
}
}
function onclick_down_ed2k(id) {
if(confirm("<%:Existing file will be overwritten, do you really want to proceed?%>"))
{
var btnXHR = new XHR();
btnXHR.post('<%=url('admin/nas/amule/down_ed2k')%>', { token: '<%=token%>' },
function(x) {}
);
}
}
function openwebui(){
var url = window.location.host+":<%=luci.sys.exec("uci -q get amule.main.web_port"):gsub("^%s*(.-)%s*$", "%1")%>";
window.open('http://'+url,'target','');
};
//]]>
</script>
<style>.mar-10 {margin-left: 10px; margin-right: 10px;}</style>
<fieldset class="cbi-section">
<legend><%:aMule Status%></legend>
<p id="amule_status">
<em><%:Collecting data...%></em>
</p>
<p id="amule_startstop">
<em><%:Collecting data...%></em>
</p>
</fieldset>

View File

@ -0,0 +1,90 @@
<script type="text/javascript">//<![CDATA[
String.prototype.startsWith = function (str){
return this.indexOf(str) == 0;
};
var iwxhr = new XHR();
function update_status(e) {
if(e!=null && e.keyCode!=13) return false;
/*var cmd = document.getElementById("cmd").value;
if(cmd.startsWith("cd"))
{
newpath = cmd.replace("cd","").replace(" ","");
if(newpath.startsWith("/")){
document.getElementById("currentpath").value = newpath;
}else{
document.getElementById("currentpath").value += newpath;
}
cmd="";
}*/
obj = document.getElementById("screen");
cmdstr=(document.getElementById("cmd").value).replace(/\s+/g,"")
if (cmdstr == "cls" || cmdstr == "clear")
{
obj = document.getElementById("screen");
obj.value = "";
document.getElementById("cmd").value = "";
return false;
}
iwxhr.get('<%=luci.dispatcher.build_url("admin", "nas", "amule", "amulecmd")%>', {cmd: document.getElementById("cmd").value },
function(x, ifc)
{
obj = document.getElementById("screen");
obj.value+=ifc[0];
document.getElementById("cmd").focus();
}
)
if ((document.getElementById("cmd").value).replace(/\s+/g,"") != "")
{
obj.value+="\r\n--------------------------------------------\r\n"+document.getElementById("cmd").value+"\r\n--------------------------------------------\r\n";
document.getElementById("cmd").value = "";
return false;
}
};
function clear_textfield() {
obj = document.getElementById("screen");
obj.value=""
}
//]]></script>
<style>
.cmd_line{
background-color:yellow;
}
#list ul li
{
margin-right:5px;
height:16px;
display:block;
float:left;
word-break: keep-all;
}
#list ul li:hover
{
background:blue;
cursor:pointer;
}
</style>
<div class="cbi-map" id="cbi-system">
<h4><a id="content" name="content"><%:You can call amulecmd commands here to control your amule.%></a></h4>
<h4><a id="content" name="content"><%:Execute 'Help' to get more infomation.%></a></h4>
<textarea id="screen" style="width:100%;height:400px;overflow:auto;font-size:12px;" readonly="readonly" ></textarea>
<br/>
<%=translate("Command: ")%>
<input type="text" id="cmd"/>
<input class="btn cbi-button cbi-input-button" style="align: center; width: 100%" type="button" onclick="update_status(null)"
<%= attr("name", section) .. attr("id", cbid .. ".btn2") .. attr("value", translate("Execute")) %> />
<input class="btn cbi-button cbi-input-button" style="align: center; width: 100%" type="button" onclick="clear_textfield()"
<%= attr("name", section) .. attr("id", cbid .. ".btn3") .. attr("value", translate("Clear")) %> />
<br/>
</div>

View File

@ -0,0 +1,360 @@
msgid "aMule is a ED2K/KAD client for all platforms."
msgstr "aMule是一个跨平台的ED2K/KAD客户端"
msgid "NAS"
msgstr "网络存储"
msgid "General"
msgstr "常规"
msgid "Connections"
msgstr "连接"
msgid "Server"
msgstr "服务器"
msgid "Path And File"
msgstr "路径和文件"
msgid "Security"
msgstr "安全"
msgid "External Control"
msgstr "远程控制"
msgid "Edit Template"
msgstr "编辑配置模版"
msgid "Log File Viewer"
msgstr "日志查看"
msgid "aMule Settings"
msgstr "aMule设置"
msgid "Run daemon as user"
msgstr "运行守护进程的用户"
msgid "Configuration directory"
msgstr "配置目录"
msgid "Nickname"
msgstr "昵称"
msgid "Max upload speed"
msgstr "最大上传速度"
msgid "Max download speed"
msgstr "最大下载速度"
msgid "Unlimited when set to 0"
msgstr "设为0时不限制"
msgid "Slot allocation"
msgstr "槽速度"
msgid "Max connections"
msgstr "最大连接数"
msgid "Max sources per file"
msgstr "单文件最大连接数"
msgid "TCP port"
msgstr "TCP端口"
msgid "UDP port"
msgstr "UDP端口"
msgid "Enable UDP port"
msgstr "启用UDP端口"
msgid "Enable UPnP"
msgstr "启用UPnP"
msgid "UPnP TCP port"
msgstr "UPnP TCP端口"
msgid "Bind Address"
msgstr "地址绑定"
msgid "Leave blank to bind all"
msgstr "留空则全部绑定"
msgid "Default to bind all"
msgstr "默认全部绑定"
msgid "Automatically connect"
msgstr "自动连接"
msgid "Automatically reconnect"
msgstr "自动重连"
msgid "Connect to Kad network"
msgstr "连接到Kad网络"
msgid "Connect to ED2K network"
msgstr "连接到ED2K网络"
msgid "Proxy Configuration"
msgstr "代理设置"
msgid "Enable proxy"
msgstr "启用代理"
msgid "Proxy type"
msgstr "代理类型"
msgid "Proxy name"
msgstr "代理名称"
msgid "Proxy port"
msgstr "代理端口"
msgid "Proxy requires authentication"
msgstr "代理需要认证"
msgid "Proxy user"
msgstr "代理用户"
msgid "Proxy password"
msgstr "代理密码"
msgid "Kad Nodes Url"
msgstr "Kad节点URL"
msgid "Ed2k Servers List Url"
msgstr "Ed2k服务器列表URL"
msgid "Remove Dead Server"
msgstr "删除无效服务器"
msgid "Dead Server Retry"
msgstr "删除前重连次数"
msgid "Update server list when connecting to a server"
msgstr "与服务器连接时更新服务器列表"
msgid "Update server list when a client connects"
msgstr "与其他用户连接时更新服务器列表"
msgid "Use priority system"
msgstr "启用优先级系统"
msgid "Use smart LowID check on connect"
msgstr "智能LOWID检测"
msgid "Safe connect"
msgstr "安全连接"
msgid "Auto connect to servers in static list only"
msgstr "只自动连接到静态列表中的服务器"
msgid "Set manually added servers to high priority"
msgstr "将手动输入的服务器设为高优先级"
msgid "Auto update server list at startup"
msgstr "启动时自动更新服务器列表"
msgid "addresses.dat file"
msgstr "addresses.dat文件"
msgid "Server addresses"
msgstr "服务器地址"
msgid "Content of addresses.dat. One address per line"
msgstr "addresses.dat的内容. 每行一个地址."
msgid "Temporary directory"
msgstr "临时文件夹"
msgid "Incoming directory"
msgstr "下载文件夹"
msgid "Shared directory"
msgstr "共享文件夹"
msgid "Content of shareddir.dat. One directory per line"
msgstr "shareddir.dat的内容. 每行一个目录."
msgid "Intelligent corruption handling (I.C.H.)"
msgstr "智能损坏数据处理(I.C.H.)"
msgid "Advanced I.C.H trusts every hash (not recommended)"
msgstr "高级I.C.H信任全部校验值不推荐"
msgid "Add files to download in pause mode"
msgstr "添加新下载文件时设为暂停"
msgid "Add files to download with auto priority"
msgstr "添加新下载文件时设定优先级为自动"
msgid "Start next paused file when a file completes"
msgstr "一个文件完成时开始下一个暂停的文件"
msgid "Start next paused file from the same category"
msgstr "从同一分类开始下一个暂停的文件"
msgid "Start next paused file in alphabetic order"
msgstr "根据字母顺序开始下一个暂停的文件"
msgid "Preallocate disk space for new files"
msgstr "为新文件预分配磁盘空间"
msgid "Minimum free disk space. in Mbytes"
msgstr "最低剩余空间单位MB"
msgid "Save 10 sources on rare files (< 20 sources)"
msgstr "保存稀有文件少于20个源的十个源"
msgid "Add new shares with auto priority"
msgstr "添加新共享文件时设优先级为自动"
msgid "Use secure user identification"
msgstr "使用安全用户认证"
msgid "Use obfuscation for outgoing connections"
msgstr "为传出连接使用迷惑协议"
msgid "Accept only obfuscation connections"
msgstr "只接受迷惑协议连接"
msgid "Who can see my shared files"
msgstr "谁可查看我的共享文件"
msgid "IP Filter Configuration"
msgstr "IP过滤设置"
msgid "Static IP list for filtering"
msgstr "静态IP过滤列表"
msgid "Content of ipfilter_static.dat"
msgstr "ipfilter_static.dat的内容"
msgid "Filter clients by IP"
msgstr "过滤用户"
msgid "Filter servers by IP"
msgstr "过滤服务器"
msgid "IP filter list URL"
msgstr "过滤列表URL"
msgid "Auto-update ipfilter at startup"
msgstr "自动更新过滤列表"
msgid "Filtering Level"
msgstr "过滤级别"
msgid "Always filter LAN IPs"
msgstr "总是过滤局域网ip地址"
msgid "Paranoid handling of non-matching IPs"
msgstr "处理不匹配的IP"
msgid "Use system-wide ipfilter.dat if available"
msgstr "可用情况下使用系统级的ipfilter.dat"
msgid "IP of the listening interface for external connection"
msgstr "远程连接监听IP"
msgid "TCP port for EC"
msgstr "远程连接TCP端口"
msgid "Enable upnp port forwarding on the EC port"
msgstr "为远程连接端口启用upnp"
msgid "aMule Web Configuration"
msgstr "aMule Web设置"
msgid "EC password"
msgstr "远程连接密码"
msgid "Enable web server on startup"
msgstr "启动时运行Web服务"
msgid "Web template"
msgstr "Web模版"
msgid "Web full rights password"
msgstr "Web最高权限密码"
msgid "Use low rights user"
msgstr "启用低权限用户"
msgid "Web low rights password"
msgstr "Web低权限密码"
msgid "Web TCP port"
msgstr "Web TCP端口"
msgid "Enable UPnP port forwarding of the web server port"
msgstr "为Web服务端口启用UPnP端口转发"
msgid "Web UPnP TCP port"
msgstr "Web服务UPnP的TCP端口"
msgid "Page refresh time(in secs)"
msgstr "页面刷新周期(秒)"
msgid "Enable Gzip compression"
msgstr "启用Gzip压缩"
msgid "Edit the template that is used for generating the aMule configuration."
msgstr "编辑用来生成aMule设置的模板"
msgid "This is the content of the file '/etc/amule/amule.conf.template' from which your amule configuration will be generated. Values enclosed by pipe symbols ('|') should not be changed. They get their values from other tabs."
msgstr "创建aMule设置的 '/etc/amule/amule.conf.template' 文件的内容。被通道符|包围的值不应该在这里改动,请在其他标签修改这些设置。"
msgid "Read / Reread log file"
msgstr "读取/重载日志文件"
msgid "Please press [Read] button"
msgstr "请点击[读取]按钮"
msgid "File not found or empty"
msgstr "文件不存在或为空"
msgid "aMule Status"
msgstr "aMule状态"
msgid "Open aMuleWeb"
msgstr "打开aMuleWeb"
msgid "aMule daemon is running."
msgstr "aMule守护进程正在运行"
msgid "aMule daemon is not running."
msgstr "aMule守护进程未运行"
msgid "Start aMule"
msgstr "启动aMule"
msgid "aMule command"
msgstr "aMule命令"
msgid "aMule Command"
msgstr "aMule命令"
msgid "You can call amulecmd commands here to control your amule."
msgstr "你可以在这里运行amulecmd命令以控制你的aMule"
msgid "Execute 'Help' to get more infomation."
msgstr "执行'Help'命令以获取更多信息"
msgid "Execute"
msgstr "执行"
msgid "Clear"
msgstr "清空"
msgid "Command: "
msgstr "命令: "
msgid "Download now"
msgstr "立即下载"
msgid "Existing file will be overwritten, do you really want to proceed?"
msgstr "已有文件将被覆盖,是否继续?"
msgid "Percentage"
msgstr "百分比"

View File

@ -0,0 +1,206 @@
[eMule]
Nick=|NICK|
MaxUpload=|MAXUPLOAD|
MaxDownload=|MAXDOWNLOAD|
SlotAllocation=|SLOTALLOCATION|
MaxConnections=|MAXCONNECTIONS|
MaxSourcesPerFile=|MAXSOURCESPERFILE|
Port=|PORT|
UDPPort=|UDPPORT|
UDPEnable=|UDPENABLE|
UPnPEnabled=|UPNPENABLED|
UPnPTCPPort=|UPNPTCPPORT|
Address=|ADDRESS|
Autoconnect=|AUTOCONNECT|
Reconnect=|RECONNECT|
ConnectToKad=|CONNECTTOKAD|
ConnectToED2K=|CONNECTTOED2K|
KadNodesUrl=|KADNODESURL|
Ed2kServersUrl=|ED2KSERVERSURL|
RemoveDeadServer=|REMOVEDEADSERVER|
DeadServerRetry=|DEADSERVERRETRY|
AddServerListFromServer=|ADDSERVERLISTFROMSERVER|
AddServerListFromClient=|ADDSERVERLISTFROMCLIENT|
Scoresystem=|SCORESYSTEM|
SmartIdCheck=|SMARTIDCHECK|
SafeServerConnect=|SAFESERVERCONNECT|
AutoConnectStaticOnly=|AUTOCONNECTSTATICONLY|
ManualHighPrio=|MANUALHIGHPRIO|
Serverlist=|SERVERLIST|
TempDir=|TEMPDIR|
IncomingDir=|INCOMINGDIR|
ICH=|ICH|
AICHTrust=|AICHTRUST|
AddNewFilesPaused=|ADDNEWFILESPAUSED|
DAPPref=|DAPPREF|
StartNextFile=|STARTNEXTFILE|
StartNextFileSameCat=|STARTNEXTFILESAMECAT|
StartNextFileAlpha=|STARTNEXTFILEALPHA|
AllocateFullFile=|ALLOCATEFULLFILE|
MinFreeDiskSpace=|MINFREEDISKSPACE|
UAPPref=|UAPPREF|
SeeShare=|SEESHARE|
IPFilterURL=|IPFILTERURL|
IPFilterAutoLoad=|IPFILTERAUTOLOAD|
FilterLevel=|FILTERLANIPS|
FilterLanIPs=|FILTERLANIPS|
ParanoidFiltering=|PARANOIDFILTERING|
IPFilterSystem=|IPFILTERSYSTEM|
FilterMessages=1
FilterAllMessages=0
MessagesFromFriendsOnly=0
MessageFromValidSourcesOnly=1
FilterWordMessages=0
MessageFilter=
ShowMessagesInLog=1
FilterComments=0
CommentFilter=
AppVersion=SVN
QueueSizePref=50
MaxConnectionsPerFiveSeconds=20
ServerKeepAliveTimeout=0
CheckDiskspace=1
PreviewPrio=0
FileBufferSizePref=16
OSDirectory=/var/run/amule
OnlineSignature=0
OnlineSignatureUpdate=5
EnableTrayIcon=0
MinToTray=0
ConfirmExit=1
StartupMinimized=0
3DDepth=10
ToolTipDelay=1
ShowOverhead=0
ShowInfoOnCatTabs=1
VerticalToolbar=0
GeoIPEnabled=1
VideoPlayer=
StatGraphsInterval=3
statsInterval=30
DownloadCapacity=300
UploadCapacity=100
StatsAverageMinutes=5
VariousStatisticsMaxValue=100
ShareHiddenFiles=0
AutoSortDownloads=0
NewVersionCheck=1
AdvancedSpamFilter=1
MessageUseCaptchas=1
Language=
SplitterbarPosition=75
YourHostname=
DateTimeFormat=%A, %x, %X
AllcatType=0
ShowAllNotCats=0
SmartIdState=0
DropSlowSources=0
ShowRatesOnTitle=0
GeoLiteCountryUpdateUrl=http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
StatsServerName=Shorty's ED2K stats
StatsServerURL=http://ed2k.shortypower.dyndns.org/?hash=
CreateSparseFiles=1
[Browser]
OpenPageInTab=1
CustomBrowserString=
[Proxy]
ProxyEnableProxy=|PROXYENABLEPROXY|
ProxyType=|PROXYTYPE|
ProxyName=|PROXYNAME|
ProxyPort=|PROXYPORT|
ProxyEnablePassword=|PROXYENABLEPASSWORD|
ProxyUser=|PROXYUSER|
ProxyPassword=|PROXYPASSWORD|
[DLP]
CheckModString=1
CheckUsername=1
CheckUserHash=1
CheckHelloTag=1
CheckInfoTag=1
CheckVeryCDMod=0
CheckGhostMod=1
[ExternalConnect]
ECAddress=|ECADDRESS|
ECPort=|ECPORT|
UPnPECEnabled=|UPNPECENABLED|
ECPassword=|ECPASSWORD|
UseSrcSeeds=|USESRCSEED|
UseSecIdent=|USESECIDENT|
IpFilterClients=|IPFILTERCLIENTS|
IpFilterServers=|IPFILTERSERVERS|
AcceptExternalConnections=1
ShowProgressBar=1
ShowPercent=1
TransmitOnlyUploadingClients=0
[WebServer]
Enabled=|WEBENABLED|
Template=|TEMPLATE|
Password=|WEBPASSWORD|
UseLowRightsUser=|USELOWRIGHTSUSER|
PasswordLow=|PASSWORDLOW|
Port=|WEBPORT|
UPnPWebServerEnabled=|UPNPWEBSERVERENABLED|
WebUPnPTCPPort=|WEBUPNPTCPPORT|
PageRefreshTime=|PAGEREFRESHTIME|
UseGzip=|USEGZIP|
Path=amuleweb
[GUI]
HideOnClose=0
[Razor_Preferences]
FastED2KLinksHandler=1
[SkinGUIOptions]
Skin=
[Statistics]
MaxClientVersions=0
[Obfuscation]
IsCryptLayerRequested=|ISCRYPTLAYERREQUESTED|
IsClientCryptLayerRequired=|ISCLIENTCRYPTLAYERREQUIRED|
IsClientCryptLayerSupported=1
CryptoPaddingLenght=254
CryptoKadUDPKey=281625462
[PowerManagement]
PreventSleepWhileDownloading=0
[UserEvents]
[UserEvents/DownloadCompleted]
CoreEnabled=0
CoreCommand=
GUIEnabled=0
GUICommand=
[UserEvents/NewChatSession]
CoreEnabled=0
CoreCommand=
GUIEnabled=0
GUICommand=
[UserEvents/OutOfDiskSpace]
CoreEnabled=0
CoreCommand=
GUIEnabled=0
GUICommand=
[UserEvents/ErrorOnCompletion]
CoreEnabled=0
CoreCommand=
GUIEnabled=0
GUICommand=
[HTTPDownload]
URL_1=

View File

@ -0,0 +1,71 @@
config amule 'main'
option enabled '0'
option runasuser 'amule'
option config_dir '/var/run/amule'
option mem_percentage '50'
option nice '10'
option ionice_flags '-c 3'
option nick 'http://www.aMule.org'
option max_upload '0'
option max_download '0'
option slot_allocation '2'
option max_connections '500'
option max_sources_per_file '300'
option port '4662'
option udp_enable '1'
option udp_port '4672'
option upnp_tcp_port '50000'
option auto_connect '1'
option reconnect '1'
option connect_to_kad '1'
option connect_to_ed2k '1'
option kad_nodes_url 'http://upd.emule-security.org/nodes.dat'
option ed2k_servers_url 'http://upd.emule-security.org/server.met'
option remove_dead_server '1'
option dead_server_retry '3'
option scoresystem '1'
option smart_id_check '1'
option use_sec_ident '1'
option is_crypt_layer_requested '1'
option ip_filter_clients '1'
option ip_filter_servers '1'
option ip_filter_auto_load '1'
option filter_level '127'
option filter_lan_ips '1'
option paranoid_filtering '1'
option ec_port '4712'
option ec_password '12345678'
option ich '1'
option dap_pref '1'
option start_next_file '1'
option min_free_disk_space '1'
option use_src_seed '1'
option temp_dir '/var/run/amule/Temp'
option incoming_dir '/var/run/amule/Incoming'
option proxy_enable_proxy '0'
option add_server_list_from_server '0'
option add_server_list_from_client '0'
option safe_server_connect '0'
option auto_connect_static_only '0'
option manual_high_prio '0'
option serverlist '0'
option a_ich_trust '0'
option add_new_files_paused '0'
option allocate_full_file '0'
option uap_pref '0'
option is_client_crypt_layer_required '0'
option see_share 'nobody'
option ip_filter_system '0'
option upnp_ec_enabled '0'
option web_enabled '0'
option upnp_enabled '0'
option proxy_type 'socks5'
option template 'default'
option use_low_rights_user '0'
option web_port '44711'
option upnp_web_server_enabled '0'
option web_upnp_tcp_port '50001'
option page_refresh_time '121'
option use_gzip '0'

View File

@ -0,0 +1,14 @@
#!/bin/sh
# Copyright (C) 2007 OpenWrt.org
/etc/init.d/amule enabled && {
[ "$ACTION" = "ifup" ] && {
/etc/init.d/amule start
}
[ "$ACTION" = "ifdown" ] && {
/etc/init.d/amule stop
}
}

View File

@ -0,0 +1,179 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2010-2015 OpenWrt.org
START=99
USE_PROCD=1
LIST_SEP="
"
service_triggers() {
procd_add_reload_trigger amule
}
unregex() {
echo "$1" | sed -e 's/[]\/()$*.^|[]/\\&/g'
}
option_word_to_digit() {
word=$(grep -ioE "\b$2=\S+" "$1"|awk -F= '{print $2}')
digit=$(echo "$3" |grep -oE "$word/\S+"|awk -F'/' '{print $2}')
sed -i "s/\b$2=$word\b/$2=$digit/g" "$1"
}
encrypt_password() {
pass_notencryted=$(grep -ioE "\b$2=[^\n]+" "$1"|sed "s/.*$2=//g")
pass_encryted=$(echo -n $pass_notencryted|md5sum|grep -oE "[a-z0-9]{32}")
[[ -z $pass_notencryted ]] || sed -i "s/\b$2=$(unregex $pass_notencryted)/$2=$pass_encryted/g" "$1"
}
write_dat_file() {
if [[ -s "$1" ]] ; then
cat "$1" > "$2"
else
[[ -s "$2" ]] && cat "$2" > "$1"
fi
}
set_params() {
cat /etc/amule/amule.conf.template > "$config_file"
local p; local v; local s="$1"; shift
for p in $*; do
config_get v "$s" "$p"
IFS="$LIST_SEP"
for v in $v; do
[ -n "$v" ] && (
sed -i "s;|$(echo $p|tr '[a-z]' '[A-Z]'|sed -e 's|_||g')|;$(unregex $v);g" "$config_file"
)
done
unset IFS
done
#delete unreplaced placeholders
sed -i "s;=|[A-Z0-9]*|;=;g" "$config_file"
#convert some options to digit
option_word_to_digit "$config_file" "ProxyType" "socks5/0 socks4/1 http/2 socks4a/3"
option_word_to_digit "$config_file" "SeeShare" "anyone/0 friends/1 nobody/2"
#encrypt password
encrypt_password "$config_file" "ECPassword"
encrypt_password "$config_file" "Password"
encrypt_password "$config_file" "PasswordLow"
}
section_enabled() {
config_get_bool enabled "$1" 'enabled' 0
[ $enabled -gt 0 ]
}
set_owner() {
case $(echo "$1"|grep -oE "^/[^/]+") in
"/var"|"/tmp"|"/mnt"|"root")
cur_user=$(ls -w50 -ld "$1"|awk '{print $3}')
cur_group=$(ls -w50 -ld "$1"|awk '{print $4}')
[[ $cur_user == $2 ]] || ( chown -R $2 "$1" )
[[ $cur_group == $3 ]] || ( chgrp -R $3 "$1" )
;;
*)
false
;;
esac
}
amule() {
local cfg="$1"
local USE
local runasuser
local incoming_dir config_dir temp_dir
local mem_percentage
local config_overwrite nice ionice_flags
local cmdline
section_enabled "$section" || return 1
config_get config_dir "$cfg" 'config_dir' '/var/run/amule'
config_get runasuser "$cfg" 'runasuser' 'daemon'
config_get incoming_dir "$cfg" 'incoming_dir' "$config_dir/Incoming"
config_get temp_dir "$cfg" 'temp_dir' "$config_dir/Temp"
config_get mem_percentage "$cfg" 'mem_percentage' '50'
config_get config_overwrite "$cfg" config_overwrite 1
config_get nice "$cfg" nice "-19"
config_get ionice_flags "$cfg" ionice_flags ''
group=$(id -Gn $runasuser)
case $(echo "$config_dir"|grep -oE "^/[^/]+") in
"/var"|"/tmp"|"/mnt"|"/root"|"/home")
true
;;
*)
echo "You should set config_dir to subfolders under /var, /tmp ,/mnt or /root"
return 1
;;
esac
which ionice > /dev/null || ionice_flags=''
local MEM=$(sed -ne 's!^MemTotal:[[:space:]]*\([0-9]*\) kB$!\1!p' /proc/meminfo)
if test "$MEM" -gt 1;then
USE=$(expr $MEM \* $mem_percentage \* 10)
fi
config_file="$config_dir/amule.conf"
#[ -d "$config_dir" ] || {
mkdir -m 0755 -p "$config_dir"
chmod g+s "$config_dir"
chown $group:$runasuser "$config_dir"
touch "$config_file" "$config_dir/addresses.dat" "$config_dir/shareddir.dat" \
"$config_dir/ipfilter_static.dat"
[ -d "$config_dir/.aMule" ] || ln -s ./ $config_dir/.aMule
#[ -z "$runasuser" ] || set_owner "$config_dir" $runasuser $group
#}
touch "$config_file"
write_dat_file /etc/amule/addresses.dat "$config_dir/addresses.dat"
write_dat_file /etc/amule/shareddir.dat "$config_dir/shareddir.dat"
write_dat_file /etc/amule/ipfilter_static.dat "$config_dir/ipfilter_static.dat"
#[ "$config_overwrite" == 0 ] || {
set_params "$cfg" $(uci show amule|awk -F'[.=]' '{print $3}'|tr '\n' ' ')
#}
HOME="$config_dir" /usr/bin/amulecmd --create-config-from="$config_file"
cmdline="/usr/bin/amuled -c $config_dir"
[ "$ionice_flags" ] && cmdline="ionice $ionice_flags $cmdline"
procd_open_instance
procd_set_param command $cmdline
procd_set_param respawn retry=60
procd_set_param user "$runasuser"
procd_set_param nice "$nice"
if test -z "$USE";then
procd_set_param limits core="0 0"
else
procd_set_param limits core="0 0" as="$USE $USE"
logger -t amule "Starting with $USE virt mem"
fi
procd_add_jail amule log
procd_add_jail_mount_rw $config_file
procd_add_jail_mount_rw $incoming_dir
procd_add_jail_mount_rw $temp_dir
procd_close_instance
}
start_service() {
killall -9 amuleweb >/dev/null 2>&1
config_load 'amule'
config_foreach amule 'amule'
}
restart() {
stop
sleep 2
start
}

View File

@ -0,0 +1,25 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@amule[-1]
add ucitrack amule
set ucitrack.@amule[-1].init=amule
commit ucitrack
EOF
while [ ! $(grep -e "amule" ${IPKG_INSTROOT}/etc/passwd) ]
do
gid=$(awk -v min=1000 -v max=1500 'BEGIN{srand(); print int(min+rand()*(max-min+1))}')
echo amule:x:0:0:99999:7::: >> ${IPKG_INSTROOT}/etc/shadow
grep -e ":$gid:" ${IPKG_INSTROOT}/etc/passwd || ( \
echo "amule:x:$gid:amule" >> ${IPKG_INSTROOT}/etc/group ; \
echo "amule:x:$gid:$gid:amule:/var/run/amule:/bin/false" >> ${IPKG_INSTROOT}/etc/passwd )
done
mkdir -p ${IPKG_INSTROOT}/etc/amule/
touch ${IPKG_INSTROOT}/etc/amule/addresses.dat
touch ${IPKG_INSTROOT}/etc/amule/ipfilter_static.dat
touch ${IPKG_INSTROOT}/etc/amule/shareddir.dat
rm -f /tmp/luci-indexcache
exit 0

View File

@ -0,0 +1,11 @@
{
"luci-app-amule": {
"description": "Grant UCI access for luci-app-amule",
"read": {
"uci": [ "amule" ]
},
"write": {
"uci": [ "amule" ]
}
}
}

View File

@ -0,0 +1,64 @@
# Copyright (C) 2018-2019 Lienol
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-autoipsetadder
PKG_VERSION:=1.0
PKG_RELEASE:=7
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/luci-app-autoipsetadder
SECTION:=luci
CATEGORY:=LuCI
SUBMENU:=3. Applications
TITLE:=LuCI Support for autoipsetadder
PKGARCH:=all
DEPENDS:= +httping +curl
endef
define Package/luci-app-autoipsetadder/description
LuCI support for autoipsetadder
endef
define Build/Prepare
endef
define Build/Compile
endef
define Package/luci-app-autoipsetadder/conffiles
/etc/config/autoipsetadder
endef
define Package/luci-app-autoipsetadder/install
$(INSTALL_DIR) $(1)/usr/lib/lua/luci
cp -pR ./luasrc/* $(1)/usr/lib/lua/luci
$(INSTALL_DIR) $(1)/
cp -pR ./root/* $(1)/
endef
define Package/luci-app-autoipsetadder/postinst
#!/bin/sh
/etc/init.d/autoipsetadder enable >/dev/null 2>&1
/etc/init.d/autoipsetadder start
rm -f /tmp/luci-indexcache
rm -f /tmp/luci-modulecache/*
exit 0
endef
define Package/luci-app-autoipsetadder/prerm
#!/bin/sh
if [ -z "$${IPKG_INSTROOT}" ]; then
/etc/init.d/autoipsetadder disable
/etc/init.d/autoipsetadder stop
fi
exit 0
endef
$(eval $(call BuildPackage,luci-app-autoipsetadder))

View File

@ -0,0 +1,4 @@
# luci-app-autoipsetadder
需要ipset china 和 ipset gfwlist<br>
更多信息https://github.com/rufengsuixing/auto-ipsetadder-for-openwrt
![Screenshot_2019-12-27 newifi-d1 - 基础设置 - LuCI(1)](https://user-images.githubusercontent.com/22387141/71496667-63eafb80-288f-11ea-93b7-52b154450d2b.png)

View File

@ -0,0 +1,56 @@
module("luci.controller.autoipsetadder",package.seeall)
local io = require "io"
local fs=require"nixio.fs"
local sys=require"luci.sys"
local uci=require"luci.model.uci".cursor()
function index()
entry({"admin","services","autoipsetadder"},firstchild(),_("autoipsetadder"),30).dependent=true
entry({"admin","services","autoipsetadder","autoipsetadder"},cbi("autoipsetadder"),_("Base Setting"),1)
entry({"admin","services","autoipsetadder","status"},call("act_status")).leaf=true
entry({"admin", "services", "autoipsetadder", "getlog"}, call("get_log"))
entry({"admin", "services", "autoipsetadder", "dodellog"}, call("do_del_log"))
entry({"admin", "services", "autoipsetadder", "debugip"}, call("do_debug_ip"))
end
function act_status()
local e={}
e.running=luci.sys.call("pgrep -f /usr/bin/autoipsetadder/autoaddlist.sh >/dev/null")==0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function do_del_log()
local logfile=uci:get("autoipsetadder","autoipsetadder","logfile") or "/tmp/addlist.log"
nixio.fs.writefile(logfile,"")
luci.http.prepare_content("application/json")
luci.http.write('')
end
function do_debug_ip()
luci.http.prepare_content("text/plain; charset=utf-8")
local a=sys.exec("/usr/bin/autoipsetadder/debugip.sh")
if (a=="") then
a="noproblem"
end
luci.http.write(a)
end
function get_log()
local logfile,fdp
logfile=uci:get("autoipsetadder","autoipsetadder","logfile") or "/tmp/addlist.log"
luci.http.prepare_content("text/plain; charset=utf-8")
if not fs.access(logfile) then
luci.http.write("")
return
end
if fs.access("/var/run/lucilogreload") then
fdp=0
fs.remove("/var/run/lucilogreload")
else
fdp=tonumber(fs.readfile("/var/run/lucilogpos")) or 0
end
local f=io.open(logfile, "r+")
f:seek("set",fdp)
local a=f:read(2048000) or ""
fdp=f:seek()
fs.writefile("/var/run/lucilogpos",tostring(fdp))
f:close()
luci.http.write(a)
end

View File

@ -0,0 +1,97 @@
require("luci.sys")
require("luci.util")
local fs=require"nixio.fs"
local uci=require"luci.model.uci".cursor()
local m,s,o
m = Map("autoipsetadder", translate("ipsetautoadder"))
m.description = translate("自动将联不通的域名加入ipset")
m:section(SimpleSection).template = "autoipsetadder/status"
s = m:section(TypedSection, "autoipsetadder")
s.anonymous=true
s.addremove=false
---- enable
o = s:option(Flag, "enabled", translate("启用"))
o.default = 0
o.rmempty = false
---- logview
o=s:option(TextValue, "show", "日志")
o.template = "autoipsetadder/check"
---- logpath
o = s:option(Value, "logfile", translate("Runtime log file"))
o.datatype = "string"
o.default="/tmp/addlist.log"
o.optional = false
o.validate=function(self, value)
if fs.stat(value,"type")=="dir" then
fs.rmdir(value)
end
if fs.stat(value,"type")=="dir" then
if m.message then
m.message =m.message.."\nerror!log file is a dir"
else
m.message ="error!log file is a dir"
end
return nil
end
return value
end
---- dnsmasq log
o = s:option(Value, "dnslogfile", translate("dnsmasq log file"))
o.datatype = "string"
o.optional = false
o.default="/tmp/dnsmasq.log"
o.validate=function(self, value)
if fs.stat(value,"type")=="dir" then
fs.rmdir(value)
end
if fs.stat(value,"type")=="dir" then
if m.message then
m.message =m.message.."\nerror!log file is a dir"
else
m.message ="error!log file is a dir"
end
return nil
end
return value
end
---- crontab
o = s:option(MultiValue, "crontab", translate("Crontab task"),translate("Please change time and args in crontab"))
o:value("autodeldnslog",translate("Auto del dnsmasq log"))
o:value("autotaillog",translate("Auto tail runtime log"))
o.widget = "checkbox"
o.default = "autodeldnslog autotaillog"
o.rmempty= true
o = s:option(MultiValue, "config", translate("the way add to gfwlist"))
o:value("nochina",translate("no china ip"))
o:value("pingadd",translate("5ping loss1-4"))
o:value("packetpass",translate("packet >12 pass"))
o.widget = "checkbox"
o.default = "nochina pingadd packetpass"
o.rmempty=true
---- apply
nixio.fs.writefile("/var/run/lucilogreload","")
function m.on_commit(map)
local ucitracktest=uci:get("autoipsetadder","autoipsetadder","ucitracktest")
if ucitracktest=="1" then
return
elseif ucitracktest=="0" then
io.popen("/etc/init.d/autoipsetadder reload &")
else
if (fs.access("/var/run/AdGucitest")) then
uci:set("autoipsetadder","autoipsetadder","ucitracktest","0")
io.popen("/etc/init.d/autoipsetadder reload &")
else
fs.writefile("/var/run/AdGucitest","")
if (ucitracktest=="2") then
uci:set("autoipsetadder","autoipsetadder","ucitracktest","1")
else
uci:set("autoipsetadder","autoipsetadder","ucitracktest","2")
end
end
uci:save("autoipsetadder")
uci:commit("autoipsetadder")
end
end
return m

View File

@ -0,0 +1,62 @@
<%+cbi/valueheader%>
<%uci=require"luci.model.uci".cursor()%>
<%nixio=require"nixio"%>
<%if uci:get("autoipsetadder","autoipsetadder","enabled")=="1" then%>
<textarea id="cbid.logview.1.conf" class="cbi-input-textarea" style="width: 100%;display:inline" data-update="change" rows="10" cols="60" readonly="readonly" > </textarea>
<input type="checkbox" value="reverse" onclick=" return reverselog()" style="vertical-align:middle;height: auto;" checked><%:reverse%></input>
<input type="button" class="cbi-button cbi-button-apply" id="apply_update_button" value="dellog" onclick=" return apply_del_log() "/>
<input type="button" class="cbi-button cbi-button-apply" id="apply_update_button" value="debug" onclick=" return debug_ip() "/>
<textarea id="cbid.logview.2.conf" class="cbi-input-textarea" style="width: 100%;display:none" data-update="change" rows="10" cols="60" readonly="readonly" > </textarea>
<script type="text/javascript">//<![CDATA[
var islogreverse = true;
function apply_del_log(){
XHR.get('<%=url([[admin]], [[services]], [[autoipsetadder]], [[dodellog]])%>',null,function(x, data){
var lv = document.getElementById('cbid.logview.1.conf');
lv.innerHTML="";
}
);
return
}
function reverselog(){
var lv = document.getElementById('cbid.logview.1.conf');
lv.innerHTML=lv.innerHTML.split('\n').reverse().join('\n')
if (islogreverse){
islogreverse=false;
}else{
islogreverse=true;
}
return
}
function debug_ip(){
var lv2 = document.getElementById('cbid.logview.2.conf');
lv2.style.display="inline"
XHR.get('<%=url([[admin]], [[services]], [[autoipsetadder]], [[debugip]])%>',null,function(x, data){
var lv2 = document.getElementById('cbid.logview.2.conf');
lv2.innerHTML = x.responseText;
}
);
return
}
function poll_check(){
XHR.poll(3, '<%=url([[admin]], [[services]], [[autoipsetadder]], [[getlog]])%>', null,
function(x, data) {
var lv = document.getElementById('cbid.logview.1.conf');
if (x.responseText && lv) {
if (islogreverse){
lv.innerHTML = x.responseText.split('\n').reverse().join('\n')+lv.innerHTML;
}else{
lv.innerHTML += x.responseText;
}
}
}
);}
poll_check();
//]]>
</script>
<%end%>
<%+cbi/valuefooter%>

View File

@ -0,0 +1,22 @@
<script type="text/javascript">//<![CDATA[
XHR.poll(3, '<%=url([[admin]], [[services]], [[autoipsetadder]], [[status]])%>', null,
function(x, data) {
var tb = document.getElementById('autoipsetadder_status');
if (data && tb) {
if (data.running) {
var links = '<em><b><font color=green>autoipsetadder <%:RUNNING%></font></b></em>';
tb.innerHTML = links;
} else {
tb.innerHTML = '<em><b><font color=red>autoipsetadder <%:NOT RUNNING%></font></b></em>';
}
}
}
);
//]]>
</script>
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
<fieldset class="cbi-section">
<p id="autoipsetadder_status">
<em><%:Collecting data...%></em>
</p>
</fieldset>

View File

@ -0,0 +1,2 @@
config autoipsetadder 'autoipsetadder'
option enabled '0'

View File

@ -0,0 +1,126 @@
#!/bin/sh /etc/rc.common
USE_PROCD=1
START=99
STOP=01
CRON_FILE=/etc/crontabs/root
CONFIGURATION=autoipsetadder
EXTRA_COMMANDS="test_crontab"
EXTRA_HELP="
test_crontab"
set_dnsmasq_log()
{
sed -i '/log-facility/d' /etc/dnsmasq.conf
sed -i '/log-queries/d' /etc/dnsmasq.conf
uci set dhcp.@dnsmasq[0].logfacility='/tmp/dnsmasq.log'
uci delete dhcp.@dnsmasq[0].logqueries
echo log-queries >> /etc/dnsmasq.conf
uci commit dhcp
/etc/init.d/dnsmasq reload
}
stop_dnsmasq_log()
{
sed -i '/log-queries/d' /etc/dnsmasq.conf
uci delete dhcp.@dnsmasq[0].logfacility
uci commit dhcp
/etc/init.d/dnsmasq reload
}
reload_service()
{
rm -f /var/run/AdGucitest 2>/dev/null
kill $(cat /var/run/autoipsetadder.pid)
start
}
service_triggers() {
procd_add_reload_trigger "$CONFIGURATION"
}
start_service() {
# Reading config
config_load "${CONFIGURATION}"
mkdir -p /tmp/run/autoipsetadder
local enabled
config_get_bool enabled $CONFIGURATION enabled 0
do_crontab
if [ "$enabled" == "1" ]; then
set_dnsmasq_log
procd_open_instance
procd_set_param respawn
# pass config to script on start
procd_set_param command sh /usr/bin/autoipsetadder/autoaddlist.sh
procd_close_instance
echo "autoipsetadder turn on"
echo "enabled=$enabled"
else
stop_dnsmasq_log
echo "autoipsetadder turn off"
echo "enabled=$enabled"
fi
}
stop_service()
{
config_load "${CONFIGURATION}"
stop_dnsmasq_log
do_crontab
kill $(cat /var/run/autoipsetadder.pid)
echo "autoipsetadder turn off"
echo "enabled="$enabled""
}
do_crontab(){
config_get_bool enabled $CONFIGURATION enabled 0
#config_get logfile $CONFIGURATION logfile "/tmp/addlist.log"
#config_get dnslogfile $CONFIGURATION dnslogfile "/tmp/dnsmasq.log"
config_get crontab $CONFIGURATION crontab ""
cronreload=0
findstr="echo qingkong > \$(uci get autoipsetadder.autoipsetadder.dnslogfile)"
default="0 * * * * echo qingkong > \$(uci get autoipsetadder.autoipsetadder.dnslogfile)"
#[ -n "$lastdnslogfile" ] && findstr="echo qingkong > $lastdnslogfile" && [ "$lastdnslogfile" != "$dnslogfile" ] && replace="${lastdnslogfile//\//\\/}/${dnslogfile//\//\\/}"
[ "$enabled" == "0" ] || [ "${crontab//autodeldnslog/}" == "$crontab" ] && cronenable=0 || cronenable=1
crontab_editor
#[ "$lastdnslogfile" != "$dnslogfile" ] && uci set autoipsetadder.autoipsetadder.lastdnslogfile="$dnslogfile" && commit=1
findstr="/usr/bin/autoipsetadder/tailto.sh [0-9]* \$(uci get autoipsetadder.autoipsetadder.logfile)"
default="0 0 * * * /usr/bin/autoipsetadder/tailto.sh 2000 \$(uci get autoipsetadder.autoipsetadder.logfile)"
#[ -n "$lastlogfile" ] && findstr="/usr/bin/autoipsetadder/tailto.sh [0-9]* $lastlogfile" && [ "$lastlogfile" != "$logfile" ] && replace="${lastlogfile//\//\\/}/${logfile//\//\\/}"
[ "$enabled" == "0" ] || [ "${crontab//autotaillog/}" == "$crontab" ] && cronenable=0 || cronenable=1
crontab_editor
#[ -n "$logfile" ] && [ "$lastlogfile" != "$logfile" ] && uci set autoipsetadder.autoipsetadder.lastlogfile="$logfile" && commit=1
[ "$cronreload" -gt 0 ] && /etc/init.d/cron restart
#[ "$commit" -gt 0 ] && uci commit autoipsetadder
}
crontab_editor(){
local testline reload
local line="$(grep "$findstr" $CRON_FILE)"
[ -n "$replace" ] && [ -n "$line" ] && eval testline="\${line//$replace}" && [ "$testline" != "$line" ] && line="$testline" && reload="1" && replace=""
if [ "${line:0:1}" != "#" ]; then
if [ $cronenable -eq 1 ]; then
[ -z "$line" ] && line="$default" && reload="1"
if [ -n "$reload" ]; then
sed -i "\,$findstr,d" $CRON_FILE
echo "$line" >> $CRON_FILE
cronreload=$((cronreload+1))
fi
elif [ -n "$line" ]; then
sed -i "\,$findstr,d" $CRON_FILE
echo "#$line" >> $CRON_FILE
cronreload=$((cronreload+1))
fi
else
if [ $cronenable -eq 1 ]; then
sed -i "\,$findstr,d" $CRON_FILE
echo "${line:1}" >> $CRON_FILE
cronreload=$((cronreload+1))
elif [ -z "$reload" ]; then
sed -i "\,$findstr,d" $CRON_FILE
echo "$line" >> $CRON_FILE
fi
fi
}
test_crontab(){
config_load "${CONFIGURATION}"
do_crontab
}

View File

@ -0,0 +1,11 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@autoipsetadder[-1]
add ucitrack autoipsetadder
set ucitrack.@autoipsetadder[-1].init=autoipsetadder
commit ucitrack
EOF
rm -f /tmp/luci-indexcache
exit 0

View File

@ -0,0 +1,164 @@
#!/bin/sh
PATH="/usr/sbin:/usr/bin:/sbin:/bin"
logfile=$(uci get autoipsetadder.autoipsetadder.logfile)
[ -z "$logfile" ] && logfile="/tmp/addlist.log"
dnslogfile=$(uci get autoipsetadder.autoipsetadder.dnslogfile)
[ -z "$logfile" ] && dnslogfile="/tmp/dnsmasq.log"
config=$(uci get autoipsetadder.autoipsetadder.config 2>/dev/null)
[ "${config//nochina/}" == "$config" ] && nochina="0" || nochina="1"
[ "${config//packetpass/}" == "$config" ] && packetpass="0" || packetpass="1"
(tail -F $dnslogfile & echo $! >/var/run/autoipsetadder.pid ) | awk -v nochina="$nochina" -v packetpass="$packetpass" -F "[, ]+" '/reply/{
ip=$8;
if (ip=="" || ip=="127.0.0.1"|| ip=="0.0.0.0")
{
next;
}
if (index(ip,"<CNAME>")!=0)
{
if (cname==1)
{
next;
}
cname=1;
domain=$6;
#第一次cname时锁定域名防止解析cname对其改动
next;
}
#以上获得上行是否为cname本行不是cname执行以下内容
#lastdomain记录上次非cname的域名与本次域名对比
if(lastdomain!=$6){
for (ipindex in ipcache)
{
delete ipcache[ipindex];
}
ipcount=0;
createpid=1;
#上行非cname并且不是同cname解析域名的多个ip更新域名清理同域名免试flag
if (cname!=1)
{
domain=$6;
testall=0;
}}
ipcount++;
cname=0;
lastdomain=$6
#去除非ipv4
if (index(ip,".")==0)
{
next;
}
#不重复探测ip
if (!(ip in a))
{
#包数>12的同域名放过
if (passdomain==domain)
{
print(ip" "domain" pass by same domain ok");
a[ip]=domain;
next;
}
if (nochina==1){
"ipset test china "ip" 2>&1"| getline ipset;
close("ipset test china "ip" 2>&1");
if (index(ipset,"Warning")!=0){
print("china "ip" pass");
a[ip]=domain;
next;
}}
"ipset test gfwlist "ip" 2>&1"| getline ipset;
close("ipset test gfwlist "ip" 2>&1");
if (index(ipset,"Warning")!=0){
print("gfwlist "ip" pass");
a[ip]=domain;
next;
}
#ip压入缓存用于未检测到443/80的缓存
ipcache[ipcount]=ip;
if (testall==0){
tryhttps=0;
tryhttp=0;
#探测 nf_conntrack 的443/80
while ("grep "ip" /proc/net/nf_conntrack"| getline ret > 0)
{
split(ret, b," +");
split(b[11], pagnum,"=");
#包数>12的放过
if (packetpass==1 && pagnum[2]>12)
{
print("pass by packets="pagnum[2]" "ip" "domain);
for (ipindex in ipcache)
{
a[ipcache[ipindex]]=domain;
delete ipcache[ipindex];
}
passdomain=domain;
close("grep "ip" /proc/net/nf_conntrack");
ipcount--;
next;
}
if (b[8]=="dst="ip)
{
if (b[10]=="dport=443"){
tryhttps=1;
break;
}
else if (b[10]=="dport=80"){
tryhttp=1;
}
}
}
close("grep "ip" /proc/net/nf_conntrack");
}else{
if (testall==443)
{
tryhttps=1
}else{
tryhttp=1
}
}
if (tryhttps==1)
{ if (createpid==1)
{
print "">"/tmp/run/autoipsetadder/"domain
close("/tmp/run/autoipsetadder/"domain);
print("create"domain);
print(ip" "domain" 443"ipcount-1);
a[ip]=domain;
#正在使用的ip用最大延迟最后探测减少打断tcp的可能
system("/usr/bin/autoipsetadder/testip.sh "ip" "domain" 443 "ipcount-1" &");
delete ipcache[ipcount];
createpid=0;
}
#未检测到443/80同域名缓存的ip进行测试ipindex-1为测试延迟时间
for (ipindex in ipcache){
print(ipcache[ipindex]" "domain" 443 "ipindex-1);
a[ipcache[ipindex]]=domain;
system("/usr/bin/autoipsetadder/testip.sh "ipcache[ipindex]" "domain" 443 "ipindex-1" &");
delete ipcache[ipindex];
}
#后续同域名ip免nf_conntrack测试
testall=443;
}
else if (tryhttp==1)
{
if (createpid==1)
{
print "">"/tmp/run/autoipsetadder/"domain
close("/tmp/run/autoipsetadder/"domain);
print("create"domain);
print(ip" "domain" 80 "ipcount-1);
a[ip]=domain;
system("/usr/bin/autoipsetadder/testip.sh "ip" "domain" 80 "ipcount-1" &");
delete ipcache[ipcount];
createpid=0;
}
for (ipindex in ipcache){
print(ipcache[ipindex]" "domain" 80 "ipindex-1);
a[ipcache[ipindex]]=domain;
system("/usr/bin/autoipsetadder/testip.sh "ipcache[ipindex]" "domain" 80 "ipindex-1" &");
delete ipcache[ipindex];
}
testall=80;
}}
}' >> $logfile

View File

@ -0,0 +1,56 @@
#!/bin/sh
PATH="/usr/sbin:/usr/bin:/sbin:/bin"
dlchina=$1;
logfile=$(uci get autoipsetadder.autoipsetadder.logfile)
[ -z "$logfile" ] && logfile="/tmp/addlist.log"
dnslogfile=$(uci get autoipsetadder.autoipsetadder.dnslogfile)
[ -z "$logfile" ] && dnslogfile="/tmp/dnsmasq.log"
ipset list gfwlist | awk -v dlchina="$dlchina" -v dnslogfile="$dnslogfile" -v logfile="$logfile" '{
if (index($0,".")==0)
{
next;
}
if ($0=="127.0.0.1") {system("ipset d gfwlist 127.0.0.1");next;}
"ipset test whitelist "$0" 2>&1"| getline ipset;
close("ipset test whitelist "$0" 2>&1");
if (index(ipset,"Warning")==0){
white=0;
}else{
white=1;
}
"ipset test china "$0" 2>&1"| getline ipset;
close("ipset test china "$0" 2>&1");
if (index(ipset,"Warning")!=0){
china=1;
}
else{
china=0;
}
if (white==1)
{
if (china==0)
{
print("warning white ip not china"$0);
ret=system("grep "$0" "logfile);
if (ret!=0)
{
ret=system("grep "$0" "dnslogfile);
}
}
}else if (china==1)
{
print("warning china ip not white"$0);
ret=system("grep "$0" "logfile)
if (ret!=0)
{
ret=system("grep "$0" "dnslogfile);
}
if (dlchina)
{
system("ipset del gfwlist "$0);
}
}
}'

Some files were not shown because too many files have changed in this diff Show More