Linux添加新协议

添加协议号

\include\linux\socket.h中定义了地址协议族,修改AF_MAX+1(地址协议族数),并加上自己的协议族

1
2
3
4
5
6
7
8
9
10
11
12
#define AF_KCM		41	/* Kernel Connection Multiplexor*/
#define AF_QIPCRTR 42 /* Qualcomm IPC Router */
#define AF_AS 43 /* 新协议*/

#define AF_MAX 44 /* For now.. */

#define PF_AS AF_AS /* 新协议*/

/* Protocol families, same as address families. */
#define PF_UNSPEC AF_UNSPEC
#define PF_UNIX AF_UNIX
#define PF_LOCAL AF_LOCAL

​ 通过添加协议号的方式,需要重新编译内核

编译内核

下载linux源码,进入源码根目录编译

1
2
3
4
5
6
su
make menuconfig
make -j 32
make modules_install
make install
make headers_install INSTALL_HDR_PATH=/usr

然后重启,查看新内核版本

1
2
zjw@ubuntu:~$ uname -r
4.10.0

添加新协议模块

添加一个空协议 aproto.c,大部分函数是空函数。根据/net/rds.c修改的,将原来rds改成asAF_INET改成AF_AS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/gfp.h>
#include <linux/in.h>
#include <linux/poll.h>
#include <net/sock.h>
#include <linux/init.h>

static int as_release(struct socket *sock)
{
return 0;
}
static int as_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
return 0;
}
static int as_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
return 0;
}
static int as_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
{
int ret =0;
return ret;
}
static int as_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int msg_flags)
{
int ret =0;
return ret;
}
static unsigned int as_poll(struct file *file, struct socket *sock,
poll_table *wait)
{
int ret = 0;
return ret;
}
static int as_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
return -ENOIOCTLCMD;
}

static int as_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, unsigned int optlen)
{
int ret =0 ;
return ret;
}

static int as_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
int ret = 0;
return ret;

}
static int as_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags)
{
int ret =0 ;
return ret;
}

static struct proto as_proto = {
.name = "A_PROTO",
.owner = THIS_MODULE,
.obj_size = sizeof(struct sock),
};

static const struct proto_ops as_proto_ops = {
.family = AF_AS, // 自定义协议族
.owner = THIS_MODULE,
.release = as_release,
.bind = as_bind,
.connect = as_connect,
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.getname = as_getname,
.poll = as_poll,
.ioctl = as_ioctl,
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = as_setsockopt,
.getsockopt = as_getsockopt,
.sendmsg = as_sendmsg,
.recvmsg = as_recvmsg,
.mmap = sock_no_mmap,
.sendpage = sock_no_sendpage,
};


static int __as_create(struct socket *sock, struct sock *sk, int protocol)
{
struct as_sock *as;

sock_init_data(sock, sk);
sock->ops = &as_proto_ops;
sk->sk_protocol = protocol;
return 0;
}

static int as_create(struct net *net, struct socket *sock, int protocol,
int kern)
{
struct sock *sk;

if (sock->type != SOCK_SEQPACKET || protocol)
return -ESOCKTNOSUPPORT;

sk = sk_alloc(net, AF_AS, GFP_ATOMIC, &as_proto, kern);
if (!sk)
return -ENOMEM;

return __as_create(sock, sk, protocol);
}


static const struct net_proto_family as_family_ops = {
.family = AF_AS,
.create = as_create,
.owner = THIS_MODULE,
};


static int __init as_init(void)
{
int ret;
printk(KERN_INFO "as_init\n");

ret = proto_register(&as_proto, 1); //注册协议
if (ret)
{
printk(KERN_ERR "proto_register ERROR\n");
goto out;
}
ret = sock_register(&as_family_ops);
if (ret)
{
printk(KERN_ERR "sock_register ERROR\n");
goto out;
}
goto out;
printk(KERN_INFO "device has been registered\n");
out:
return ret;
}

static void __exit as_exit(void){
printk(KERN_INFO "aproto exit\n");
}

module_init(as_init);
module_exit(as_exit);

#define DRV_RELDATE "2017/12/07"
MODULE_AUTHOR("Jingwei Zheng");
MODULE_DESCRIPTION("AS:A NEW PROTOCOL" DRV_RELDATE);

应用程序

1
2
3
4
#define AF_AS 43
...
socket_fd = socket(AF_AS, SOCK_SEQPACKET, 0)
...