在linux kernel中netlink的使用示例
生活随笔
收集整理的這篇文章主要介紹了
在linux kernel中netlink的使用示例
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
文章目錄
- 1、在socket.h中,INET協(xié)議族的定義
- 2、以PF_ALG為例,注冊(cè)一個(gè)netlink驅(qū)動(dòng),在af_alg.c中:
- 3、以PF_ALG為例,寫(xiě)一個(gè)userspace調(diào)用程序
思考
userspace和kernel space通信的方式有哪些? 應(yīng)用程序是如何調(diào)用到驅(qū)動(dòng)的?
[答案]內(nèi)核與用戶(hù)空間通信有很多種通信方式,netlink是其中一種,其余的還有/proc、ioctl、sockopt、共享內(nèi)存等等。netlink的特點(diǎn)是異步全雙工
1、在socket.h中,INET協(xié)議族的定義
如果我們要實(shí)現(xiàn)一個(gè)新的netlink驅(qū)動(dòng),在后面添加一個(gè)PF協(xié)議號(hào)即可
/* Supported address families. */ #define AF_UNSPEC 0 #define AF_UNIX 1 /* Unix domain sockets */ #define AF_LOCAL 1 /* POSIX name for AF_UNIX */ #define AF_INET 2 /* Internet IP Protocol */ #define AF_AX25 3 /* Amateur Radio AX.25 */ #define AF_IPX 4 /* Novell IPX */ #define AF_APPLETALK 5 /* AppleTalk DDP */ #define AF_NETROM 6 /* Amateur Radio NET/ROM */ #define AF_BRIDGE 7 /* Multiprotocol bridge */ #define AF_ATMPVC 8 /* ATM PVCs */ #define AF_X25 9 /* Reserved for X.25 project */ #define AF_INET6 10 /* IP version 6 */ #define AF_ROSE 11 /* Amateur Radio X.25 PLP */ #define AF_DECnet 12 /* Reserved for DECnet project */ #define AF_NETBEUI 13 /* Reserved for 802.2LLC project*/ #define AF_SECURITY 14 /* Security callback pseudo AF */ #define AF_KEY 15 /* PF_KEY key management API */ #define AF_NETLINK 16 #define AF_ROUTE AF_NETLINK /* Alias to emulate 4.4BSD */ #define AF_PACKET 17 /* Packet family */ #define AF_ASH 18 /* Ash */ #define AF_ECONET 19 /* Acorn Econet */ #define AF_ATMSVC 20 /* ATM SVCs */ #define AF_RDS 21 /* RDS sockets */ #define AF_SNA 22 /* Linux SNA Project (nutters!) */ #define AF_IRDA 23 /* IRDA sockets */ #define AF_PPPOX 24 /* PPPoX sockets */ #define AF_WANPIPE 25 /* Wanpipe API Sockets */ #define AF_LLC 26 /* Linux LLC */ #define AF_IB 27 /* Native InfiniBand address */ #define AF_MPLS 28 /* MPLS */ #define AF_CAN 29 /* Controller Area Network */ #define AF_TIPC 30 /* TIPC sockets */ #define AF_BLUETOOTH 31 /* Bluetooth sockets */ #define AF_IUCV 32 /* IUCV sockets */ #define AF_RXRPC 33 /* RxRPC sockets */ #define AF_ISDN 34 /* mISDN sockets */ #define AF_PHONET 35 /* Phonet sockets */ #define AF_IEEE802154 36 /* IEEE802154 sockets */ #define AF_CAIF 37 /* CAIF sockets */ #define AF_ALG 38 /* Algorithm sockets */ #define AF_NFC 39 /* NFC sockets */ #define AF_VSOCK 40 /* vSockets */ #define AF_MAX 41 /* For now.. *//* Protocol families, same as address families. */ #define PF_UNSPEC AF_UNSPEC #define PF_UNIX AF_UNIX #define PF_LOCAL AF_LOCAL #define PF_INET AF_INET #define PF_AX25 AF_AX25 #define PF_IPX AF_IPX #define PF_APPLETALK AF_APPLETALK #define PF_NETROM AF_NETROM #define PF_BRIDGE AF_BRIDGE #define PF_ATMPVC AF_ATMPVC #define PF_X25 AF_X25 #define PF_INET6 AF_INET6 #define PF_ROSE AF_ROSE #define PF_DECnet AF_DECnet #define PF_NETBEUI AF_NETBEUI #define PF_SECURITY AF_SECURITY #define PF_KEY AF_KEY #define PF_NETLINK AF_NETLINK #define PF_ROUTE AF_ROUTE #define PF_PACKET AF_PACKET #define PF_ASH AF_ASH #define PF_ECONET AF_ECONET #define PF_ATMSVC AF_ATMSVC #define PF_RDS AF_RDS #define PF_SNA AF_SNA #define PF_IRDA AF_IRDA #define PF_PPPOX AF_PPPOX #define PF_WANPIPE AF_WANPIPE #define PF_LLC AF_LLC #define PF_IB AF_IB #define PF_MPLS AF_MPLS #define PF_CAN AF_CAN #define PF_TIPC AF_TIPC #define PF_BLUETOOTH AF_BLUETOOTH #define PF_IUCV AF_IUCV #define PF_RXRPC AF_RXRPC #define PF_ISDN AF_ISDN #define PF_PHONET AF_PHONET #define PF_IEEE802154 AF_IEEE802154 #define PF_CAIF AF_CAIF #define PF_ALG AF_ALG #define PF_NFC AF_NFC #define PF_VSOCK AF_VSOCK #define PF_MAX AF_MAX/* Maximum queue length specifiable by listen. */ #define SOMAXCONN 1282、以PF_ALG為例,注冊(cè)一個(gè)netlink驅(qū)動(dòng),在af_alg.c中:
static const struct net_proto_family alg_family = {.family = PF_ALG,.create = alg_create,.owner = THIS_MODULE, };static int __init af_alg_init(void) { ......err = sock_register(&alg_family); ...... }在alg_create中,將alg_proto_ops和alg_proto綁定在一起,然后實(shí)現(xiàn)各個(gè)ops子函數(shù) static const struct proto_ops alg_proto_ops = {.family = PF_ALG,.owner = THIS_MODULE,.connect = sock_no_connect,.socketpair = sock_no_socketpair,.getname = sock_no_getname,.ioctl = sock_no_ioctl,.listen = sock_no_listen,.shutdown = sock_no_shutdown,.getsockopt = sock_no_getsockopt,.mmap = sock_no_mmap,.sendpage = sock_no_sendpage,.sendmsg = sock_no_sendmsg,.recvmsg = sock_no_recvmsg,.poll = sock_no_poll,.bind = alg_bind,.release = af_alg_release,.setsockopt = alg_setsockopt,.accept = alg_accept, };static struct proto alg_proto = {.name = "ALG",.owner = THIS_MODULE,.memory_allocated = &alg_memory_allocated,.obj_size = sizeof(struct alg_sock), };3、以PF_ALG為例,寫(xiě)一個(gè)userspace調(diào)用程序
aes_128_cbc_oper —>linux_af_alg_skcipher—>linux_af_alg_socket
建立一個(gè)socket會(huì)話的大概流程:
socket(AF_ALG,...) bind() setsockopt accept sendmsg recvmsg相關(guān)代碼
static int linux_af_alg_socket(const char *type, const char *name) {struct sockaddr_alg sa;int s;s = socket(AF_ALG, SOCK_SEQPACKET, 0);if (s < 0) {LogErr("%s: Failed to open AF_ALG socket: %s\n",__func__, strerror(errno));return -1;}os_memset(&sa, 0, sizeof(sa));sa.salg_family = AF_ALG;os_strlcpy((char *) sa.salg_type, type, sizeof(sa.salg_type));os_strlcpy((char *) sa.salg_name, name, sizeof(sa.salg_name));if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {LogErr("%s: Failed to bind AF_ALG socket(%s,%s): %s\n",__func__, (char *) sa.salg_type, (char *) sa.salg_name, strerror(errno));close(s);return -1;}return s; }static struct linux_af_alg_skcipher *linux_af_alg_skcipher(const char *alg, const u8 *key, size_t key_len) {struct linux_af_alg_skcipher *skcipher;skcipher = os_zalloc(sizeof(*skcipher));if (!skcipher)goto fail;skcipher->t = -1;skcipher->s = linux_af_alg_socket(TYPE_NAME, alg);if (skcipher->s < 0)goto fail;if (setsockopt(skcipher->s, SOL_ALG, ALG_SET_KEY, key, key_len) < 0) {LogErr("%s: setsockopt(ALG_SET_KEY) failed: %s\n",__func__, strerror(errno));goto fail;}skcipher->t = accept(skcipher->s, NULL, NULL);if (skcipher->t < 0) {LogErr("%s: accept on AF_ALG socket failed: %s\n",__func__, strerror(errno));goto fail;}return skcipher; fail:linux_af_alg_skcipher_deinit(skcipher);return NULL; }static int aes_128_cbc_oper(char *alg_name, const u8 *key,size_t key_len, int enc, const u8 *iv, u8 *data, size_t data_len) {struct linux_af_alg_skcipher *skcipher;char buf[100];struct iovec io[1];struct msghdr msg;struct cmsghdr *hdr;ssize_t ret;u32 *op;struct af_alg_iv *alg_iv;size_t iv_len = AES_BLOCK_SIZE;skcipher = linux_af_alg_skcipher(alg_name, key, key_len);//alg_name = "__cbc-aes-asr-ce"if (!skcipher)return -1;io[0].iov_base = (void *) data;io[0].iov_len = data_len;os_memset(&msg, 0, sizeof(msg));os_memset(buf, 0, sizeof(buf));msg.msg_control = buf;msg.msg_controllen = CMSG_SPACE(sizeof(u32)) +CMSG_SPACE(sizeof(*alg_iv) + iv_len);msg.msg_iov = io;msg.msg_iovlen = 1;hdr = CMSG_FIRSTHDR(&msg);hdr->cmsg_level = SOL_ALG;hdr->cmsg_type = ALG_SET_OP;hdr->cmsg_len = CMSG_LEN(sizeof(u32));op = (u32 *) CMSG_DATA(hdr);*op = enc ? ALG_OP_ENCRYPT : ALG_OP_DECRYPT;hdr = CMSG_NXTHDR(&msg, hdr);hdr->cmsg_level = SOL_ALG;hdr->cmsg_type = ALG_SET_IV;hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);if(NULL != iv){alg_iv->ivlen = iv_len;os_memcpy(alg_iv->iv, iv, iv_len);}else{alg_iv->ivlen = 0;}ret = sendmsg(skcipher->t, &msg, 0);if (ret < 0) {LogErr("%s: sendmsg failed: %s\n",__func__, strerror(errno));linux_af_alg_skcipher_deinit(skcipher);return -1;}ret = recvmsg(skcipher->t, &msg, 0);if (ret < 0) {LogErr("%s: recvmsg failed: %s\n",__func__, strerror(errno));linux_af_alg_skcipher_deinit(skcipher);return -1;}if ((size_t) ret < data_len) {LogErr("%s: recvmsg not return full data (%d/%d)\n",__func__, (int) ret, (int) data_len);linux_af_alg_skcipher_deinit(skcipher);return -1;}//s_to_binary(data,data_len);linux_af_alg_skcipher_deinit(skcipher);return 0; }總結(jié)
以上是生活随笔為你收集整理的在linux kernel中netlink的使用示例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: android指纹fingerprint
- 下一篇: [ARM异常]-linux中(aarch