Files
documents/linx_serial/serial.md
Xu, Shunxuan 3bd169d971 [Bug #2716] 修改序列号整体结构图
修改:     images/new_serialnum.odg
	修改:     images/new_serialnum.png
	修改:     serial.md

Signed-off-by: Xu, Shunxuan <sxxu@linx-info.com>
2016-03-18 15:13:00 +08:00

203 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 新版Linx_serialnum设计说明书 #
## 1 引言 ##
### 1.1 编写目的 ###
本文档为新版序列号设计说明文档,作为编码、文档编写、及测试的依据。
### 1.2 项目概述 ###
* 为便于技术支持的实施,修改添加序列号不需重启即可生效的机制。
* 修改新版序列号的key原序列号在新系统中将不再适用。
* 原序列号只有在开机启动时才会触发检测/proc/cmdline中序列号是否正确正确则网络可启用。新添加的序列号检测机制当触发linxsn_trigger时会调用函数检测/etc/default/grub中配置的序列号若正确则网络可启用。
## 2 总体设计 ##
1. 原有机制的兼容
保留原有的开机启动检测内核参数(/proc/cmdline)中的序列号是否正确的检测机制。
2. 更换原序列号的加密密钥key
由于序列号生成工具外流导致对外安装的系统管理缺失。故需将序列号工具进行后台管理更换密钥key只有通过odoo进行申请才会由后台工具生成可用序列号。
3. 添加开机状态下添加序列号生效机制
由于序列号配置后需要重启系统才能生效,导致实施时间拉长,降低效率。为提高实施效率及查看序列号信息,添加序列号检测记录/proc/linxsn和不需重启系统的序列号生效机制。
4. 添加生成虚拟机序列号
通过uuid加密换算出的序列号便于管理虚拟机系统安装。
5. 添加虚拟机序列号检测
添加虚拟机序列号检测机制若为虚拟机则序列号为通过uuid进行生成相对应的要添加虚拟机序列号检测。原序列号类型分为时间序列号和mac地址永久序列号
6. 无root模式下的配置问题
在无root模式下需sysadmin用户可对序列号进行修改及触发生效。
### 2.1 总体结构图 ###
总体结构框架图:
![new_linx_serialnum](images/new_serialnum.png)
检测序列号详解图:
![new_linx_serialnum](images/check_serial.png)
添加需求及限制条件:(待补充)
* 在/proc/linxsn中记录序列号、为时间序列号到期时间或者永久序列号。
* 当检测为时间序列号时,检测出时间何时到期,打印提示。
* 添加虚拟机序列号检测(新类型序列号检测为虚拟机则通过uuid生成序列号)。序列号会有三种类型时间序列号、mac地址永久序列号、虚拟机序列号。
### 2.2 运行环境 ###
该软件系统的运行环境Linx-6.0.42.41
## 3 功能模块设计实现 ##
逐个说明各个模块的实现设计。
### 3.1 cmdline内核参数检测机制 ###
原有序列号检测机制:开机启动网络时,检测/proc/cmdline内核参数中的序列号。获取到序列号后通过解密检测序列号是否正确。可参考内核序列号的pantch:linx_serial.patch
```C
// __setup这条宏在Linux Kernel中使用最多的地方就是定义处理Kernel的启动参数的函数及数据结构宏定义如下
#define __setup(str, fn) \
__setup_param(str, fn, fn, 0)
```
截取如下为获取/proc/cmdline中的序列号:
```C
static int __init linxsn_setup(char *str)
{
unsigned int len;
memset(linxsn_buf, 0, LINXSN_LEN + 1);
len = strlen(str);
if ((len == LINXSN_LEN)||(len == OLD_LINXSN_LEN)) {
strcpy(linxsn_buf, str);
} else {
printk(KERN_WARNING "linx serial number length does \
not match, the length shuld be %d instead of %d", LINXSN_LEN, len);
}
linx_debug("linxsn_buf: %s", linxsn_buf);
return 1;
}
__setup("linx_serial=", linxsn_setup);
```
### 3.2 获取配置文件序列号参数 ###
内核中打开文件函数filp_open()在kernel中可以打开文件其原形如下
```C
struct file* filp_open(const char* filename, int open_mode, int mode);
```
该函数返回strcut file*结构指针供后继函数操作使用该返回值用IS_ERR()来检验其有效性。
参数说明
filename 表明要打开或创建文件的名称(包括路径部分)。在内核中打开的文件时需要注意打开的时机,很容易出现需要打开文件的驱动很早就加载并打开文件,但需要打开的文件所在设备还没有挂载到文件系统中,而导致打开失败。
open_mode 文件的打开方式其取值与标准库中的open相应参数类似可以取O_CREAT,O_RDWR,O_RDONLY等。
mode 创建文件时使用设置创建文件的读写权限其它情况可以匆略设为0
### 3.3 触发检测机制 ###
proc文件的创建。创建方法是调用以下函数
```C
static inline struct proc_dir_entry *proc_create\
(const char *name, mode_t mode,struct proc_dir_entry *parent, const struct file_operations *proc_fops);
/*
name就是要创建的文件名。
mode是文件的访问权限以UGO的模式表示。
parent与proc_mkdir中的parent类似。也是父文件夹的proc_dir_entry对象。
proc_fops就是该文件的操作函数。
*/
```
mytest_proc_fops的定义。
```C
static const struct file_operations mytest_proc_fops = {
.open = mytest_proc_open,
.read = seq_read,
.write = mytest_proc_write, //做此函数去判断写入的触发值,正确则调用函数处理
.llseek = seq_lseek,
.release = single_release,
};
```
### 3.4 网络ioctl调用检测序列号机制 ###
在网络的ioctl函数中添加序列号检测通过判断检测序列号的返回值确定网络是否可用。
查看下述代码只需在触发检测中检测序列号正确则调用函数设置check_linxsn_flag=1即可。
```C
diff -Nurp linux-2.6.32.41.orig//net/ipv4/devinet.c linux-2.6.32.41/net/ipv4/devinet.c
--- linux-2.6.32.41.orig//net/ipv4/devinet.c 2013-06-19 01:12:17.000000000 +0000
+++ linux-2.6.32.41/net/ipv4/devinet.c 2013-06-19 01:50:08.000000000 +0000
@@ -62,6 +62,19 @@
#include <net/rtnetlink.h>
#include <net/net_namespace.h>
+#ifdef CONFIG_LINX_SERIAL
+#include <linux/security.h>
+
+/*
+ * check_linxsn_flag
+ * 0: need first linx_serial_check
+ * 1: linxsn check correct
+ * 2: linxsn check incorrect
+ *
+ */
+static int check_linxsn_flag = 0;
+#endif
+
static struct ipv4_devconf ipv4_devconf = {
.data = {
[NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
@@ -590,6 +603,19 @@ int devinet_ioctl(struct net *net, unsig
char *colon;
int ret = -EFAULT;
int tryaddrmatch = 0;
+#ifdef CONFIG_LINX_SERIAL
+ if (check_linxsn_flag == 0) {
+ ret = linx_serial_check();
+ if (ret == -1) {
+ check_linxsn_flag = 2;
+ printk(KERN_INFO "linx serial number check failed.");
+ return -EINVAL;
+ }
+ check_linxsn_flag = 1;
+ } else if (check_linxsn_flag == 2) {
+ return -EINVAL;
+ }
+#endif
/*
* Fetch the caller's info block into kernel space
```