secgateway/Platform/user/netlink_uapi/libnetlinku.c

872 lines
20 KiB
C
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.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <net/if_arp.h>
#include <linux/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/uio.h>
#include <linux/types.h>
#include "libnetlinku.h"
#include "commuapinl.h"
#ifndef SOL_NETLINK
#define SOL_NETLINK 270
#endif
#ifndef NETLINK_EXT_ACK
#define NETLINK_EXT_ACK 11
#endif
#if 0
struct nlumsg_list {
struct list_head list;
struct nlmsghdr *n;
};
#endif
#define NETLINK_COMM_FAMILY_NUM (NETLINK_COMMMAX_MAX_FAMILY - NETLINK_COMMMAX_MIN_FAMILY -1)
#define NETLINK_COMM_FAMILY_INDEX(family) (family - NETLINK_COMMMAX_MIN_FAMILY -1)
struct upmnl_handle * gcommnl[NETLINK_COMM_FAMILY_NUM][COMMLIBNLGRP_MAX] = {0};/*包含单播和组播一起组0是单播1开始是组播*/
int rcvbuf = 1024 * 1024;
struct upmnl_handle * commnl_get_handle(int protocol,unsigned int group)
{
struct upmnl_handle * handle = NULL;
handle = gcommnl[NETLINK_COMM_FAMILY_INDEX(protocol)][group];
//printf("get handle proto %d,group%d,handle = %p.\r\n",NETLINK_COMM_FAMILY_INDEX(protocol),group,handle);
return handle;
}
void commnl_del_handle(int protocol,unsigned int group)
{
gcommnl[NETLINK_COMM_FAMILY_INDEX(protocol)][group] = NULL;
return;
}
int commnl_add_handle(struct upmnl_handle * handle,int protocol,unsigned int group)
{
if(commnl_get_handle(protocol,group) != NULL)
{
printf("handel already exist,proto:%d,group%d.\r\n",protocol,group);
return -1;
}
//printf("add handle %p proto %d,group%d\r\n",handle,NETLINK_COMM_FAMILY_INDEX(protocol),group);
gcommnl[NETLINK_COMM_FAMILY_INDEX(protocol)][group]= handle;
return 0;
}
void printf_mem(unsigned char * p,int len)
{
int num = 0;
for(num = 0; num<len; num++)
{
printf("%02x ",*(p+num));
if(((num+1)%16 == 0) || ((num+1 ) == len))
{
printf("\r\n");
}
}
return;
}
void test_handle_add_get()
{
struct upmnl_handle handle ={
.proto = NETLINK_COMMCFG};
struct upmnl_handle *phandle =NULL;
int ret = -1;
/*test*/
ret = commnl_add_handle(&handle,NETLINK_COMMCFG,0);
if(ret < 0)
printf("commnl_add_handle failed.\r\n");
phandle = commnl_get_handle(NETLINK_COMMCFG,0);
if(phandle == NULL)
printf("commnl_get_handle faild\r\n.");
commnl_del_handle(NETLINK_COMMCFG,0);
phandle = NULL;
phandle = commnl_get_handle(NETLINK_COMMCFG,0);
if(phandle == NULL)
printf("commnl_get_handle faild\r\n.");
return ;
}
int commnl_addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
int alen)
{
int len = RTA_LENGTH(alen);
struct rtattr *rta;
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
fprintf(stderr,
"addattr_l ERROR: message exceeded bound of %d\n",
maxlen);
return -1;
}
rta = NLMSG_TAIL(n);
rta->rta_type = type;
rta->rta_len = len;
if (alen)
memcpy(RTA_DATA(rta), data, alen);
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
return 0;
}
int commnl_addattr(struct nlmsghdr *n, int maxlen, int type)
{
return commnl_addattr_l(n, maxlen, type, NULL, 0);
}
int commnl_addattr8(struct nlmsghdr *n, int maxlen, int type, __u8 data)
{
return commnl_addattr_l(n, maxlen, type, &data, sizeof(__u8));
}
int commnl_addattr16(struct nlmsghdr *n, int maxlen, int type, __u16 data)
{
return commnl_addattr_l(n, maxlen, type, &data, sizeof(__u16));
}
int commnl_addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data)
{
return commnl_addattr_l(n, maxlen, type, &data, sizeof(__u32));
}
int commnl_addattr64(struct nlmsghdr *n, int maxlen, int type, __u64 data)
{
return commnl_addattr_l(n, maxlen, type, &data, sizeof(__u64));
}
int commnl_addattrstrz(struct nlmsghdr *n, int maxlen, int type, const char *str)
{
return commnl_addattr_l(n, maxlen, type, str, strlen(str)+1);
}
int commnl_open_byproto( unsigned int subscriptions,int protocol)
{
socklen_t addr_len;
int sndbuf = 32768;
int one = 1;
struct upmnl_handle * upmh = NULL;
struct timeval timeout={1,10000};//10ms
printf("commnl_open_byproto begin:protocol=%d,subscriptions=%d\r\n",protocol,subscriptions);
upmh = calloc(1,sizeof(struct upmnl_handle) );
if(upmh == NULL)
{
printf("commnl_new_handle calloc mem error protocol:%d,group:%d.\r\n",protocol,subscriptions);
return -1;
}
upmh->local.nl_family = AF_NETLINK;
upmh->local.nl_groups = subscriptions;
upmh->local.nl_pid = getpid();
upmh->proto = protocol;
upmh->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
if (upmh->fd < 0) {
perror("Cannot open netlink socket");
goto ERR;
}
if (setsockopt(upmh->fd, SOL_SOCKET, SO_SNDBUF,
&sndbuf, sizeof(sndbuf)) < 0) {
perror("SO_SNDBUF");
goto ERR;
}
if (setsockopt(upmh->fd, SOL_SOCKET, SO_RCVBUF,
&rcvbuf, sizeof(rcvbuf)) < 0) {
perror("SO_RCVBUF");
goto ERR;
}
if (setsockopt(upmh->fd, SOL_SOCKET, SO_RCVTIMEO,
&timeout, sizeof(timeout)) < 0) {
perror("SO_RCVTIMEO");
goto ERR;
}
/* Older kernels may no support extended ACK reporting */
if (setsockopt(upmh->fd, SOL_NETLINK, NETLINK_EXT_ACK,
&one, sizeof(one))){
perror("NETLINK_EXT_ACK");
goto ERR;
}
memset(&upmh->local, 0, sizeof(upmh->local));
upmh->local.nl_family = AF_NETLINK;
upmh->local.nl_pid = getpid();
upmh->local.nl_groups = subscriptions;
if (bind(upmh->fd, (struct sockaddr *)&(upmh->local),
sizeof(upmh->local)) < 0) {
perror("Cannot bind netlink socket");
//printf("Cannot bind netlink socket\r\n");
goto ERR;
}
addr_len = sizeof(upmh->local);
if (getsockname(upmh->fd, (struct sockaddr *)&upmh->local,
&addr_len) < 0) {
perror("Cannot getsockname");
goto ERR;
}
if (addr_len != sizeof(upmh->local)) {
fprintf(stderr, "Wrong address length %d\n", addr_len);
goto ERR;
}
if (upmh->local.nl_family != AF_NETLINK) {
fprintf(stderr, "Wrong address family %d\n",
upmh->local.nl_family);
goto ERR;
}
upmh->seq = time(NULL);
commnl_add_handle(upmh, protocol, subscriptions);
printf("commnl_open_byproto succes.\r\n");
return 0;
ERR:
if (upmh->fd >= 0) {
close(upmh->fd);
upmh->fd = -1;
}
if(NULL != upmh){
free(upmh);
}
commnl_del_handle(protocol, subscriptions);
return -1;
}
void commnl_close( unsigned int subscriptions,int protocol)
{
struct upmnl_handle *upmh = commnl_get_handle(protocol,subscriptions);
if (upmh->fd >= 0) {
close(upmh->fd);
upmh->fd = -1;
}
commnl_del_handle(upmh->proto, upmh->local.nl_groups);
free(upmh);
return;
}
int commcfgnl_open()
{
return commnl_open_byproto(0, NETLINK_COMMCFG);
}
void commcfgnl_close()
{
commnl_close(0,NETLINK_COMMCFG);
return;
}
int pdelivnl_open(unsigned int group)
{
return commnl_open_byproto(group, NETLINK_PDELIVERY);
}
void pdelivnl_close(unsigned int group)
{
commnl_close(group,NETLINK_PDELIVERY);
return;
}
int commnl_send(struct upmnl_handle *nl, struct nlmsghdr *n)
{
int ret = -1;
//if(n->nlmsg_flags |NLM_F_ACK)
ret = send(nl->fd, n, n->nlmsg_len, 0);
}
int commcfg_send(struct nlmsghdr *n)
{
struct upmnl_handle *nl = NULL;
nl = commnl_get_handle(NETLINK_COMMCFG,0);
if(nl == NULL)
{
printf("err:pdeliv_talk faid,pdeliv netlink has not open.\r\n");
return -1;
}
return(commnl_send(nl,n));
}
int pdelivnl_send(int group,struct nlmsghdr *n)
{
struct upmnl_handle *nl = NULL;
nl = commnl_get_handle(NETLINK_PDELIVERY,group);
if(nl == NULL)
{
printf("err:pdeliv_talk faid,pdeliv netlink has not open.\r\n");
return -1;
}
return(commnl_send(nl,n));
}
static int __commnl_recvmsg(int fd, struct msghdr *msg, int flags)
{
int len = 0;
unsigned int num = COMMNL_TALKRCV_TIMEOUT;/*timeout*/
do {
len = recvmsg(fd, msg, flags);
#if 1
num --;
if(num ==0)
break;
#endif
printf("__rtnl_recvmsg return num %d.\r\n",num);
} while (len < 0 && (errno == EINTR || errno == EAGAIN));/*超时*/
if (len < 0) {
fprintf(stderr, "netlink receive error %s (%d)\n",
strerror(errno), errno);
return -errno;
}
if (len == 0) {
fprintf(stderr, "EOF on netlink\n");
return -ENODATA;
}
return len;
}
static int commnl_recvmsg(int fd, struct msghdr *msg, char **answer)
{
struct iovec *iov = msg->msg_iov;
char *buf;
int len;
struct nlmsghdr *recv_hdr;
iov->iov_base = NULL;
iov->iov_len = 0;
len = __commnl_recvmsg(fd, msg, MSG_PEEK | MSG_TRUNC);
if (len < 0)
return len;
if (len < 32768)
len = 32768;
buf = malloc(len);
if (!buf) {
fprintf(stderr, "malloc error: not enough buffer\n");
return -ENOMEM;
}
iov->iov_base = buf;
iov->iov_len = len;
len = __commnl_recvmsg(fd, msg, 0);
if (len < 0) {
free(buf);
return len;
}
if (answer)
*answer = buf;
else
free(buf);
recv_hdr = (struct nlmsghdr *)(*answer);
return len;
}
static int __commnl_talk_iov(struct upmnl_handle *rtnl, struct iovec *iov,
size_t iovlen, struct nlmsghdr **answer,
bool show_rtnl_err, nl_ext_ack_fn_t errfn)
{
struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
struct iovec riov;
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = iov,
.msg_iovlen = iovlen,
};
unsigned int seq = 0;
struct nlmsghdr *h;
int i, status;
char *buf;
for (i = 0; i < iovlen; i++) {
h = iov[i].iov_base;
h->nlmsg_seq = seq = ++rtnl->seq;
if (answer == NULL)
h->nlmsg_flags |= NLM_F_ACK;
}
status = sendmsg(rtnl->fd, &msg, 0);
if (status < 0) {
perror("Cannot talk to rtnetlink");
return -1;
}
else{
printf("__commnl_talk_iov send msg sucess.\r\n");
}
/* change msg to use the response iov */
msg.msg_iov = &riov;
msg.msg_iovlen = 1;
i = 0;
while (1) {
next:
printf("talk recvmsg-ing...\r\n");
status = commnl_recvmsg(rtnl->fd, &msg, &buf);
++i;
if (status < 0)
{
printf("__commnl_talk_iov: commnl_recvmsg return error=%d...\r\n",status);
return status;
}
if (msg.msg_namelen != sizeof(nladdr)) {
fprintf(stderr,
"sender address length == %d\n",
msg.msg_namelen);
exit(1);
}
for (h = (struct nlmsghdr *)buf; status >= sizeof(*h); ) {
int len = h->nlmsg_len;
int l = len - sizeof(*h);
if (l < 0 || len > status) {
if (msg.msg_flags & MSG_TRUNC) {
fprintf(stderr, "Truncated message\n");
free(buf);
return -1;
}
fprintf(stderr,
"!!!malformed message: len=%d\n",
len);
exit(1);
}
/*单播消息pid必须正确*/
if (nladdr.nl_pid != 0 ||
h->nlmsg_pid != rtnl->local.nl_pid ||
h->nlmsg_seq > seq || h->nlmsg_seq < seq - iovlen) {
/* Don't forget to skip that message. */
status -= NLMSG_ALIGN(len);
h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
printf("__commnl_talk_iov recv a msg,but not to me:h->nlmsg_pid=%d,local_pid=%d,h->nlmsg_seq=%d,seq=%d.\r\n",
h->nlmsg_pid,rtnl->local.nl_pid,h->nlmsg_seq,seq);
continue;
}
if (h->nlmsg_type == NLMSG_ERROR) {
printf("nltalk recv a ack msg.\r\n");
struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(h);
int error = err->error;
if (l < sizeof(struct nlmsgerr)) {
fprintf(stderr, "ERROR truncated\n");
free(buf);
return -1;
}
if (!error) {
/* check messages from kernel */
//nl_dump_ext_ack(h, errfn);
} else {
//errno = -error;
//if (rtnl->proto != NETLINK_SOCK_DIAG && show_rtnl_err)
//rtnl_talk_error(h, err, errfn);
}
if (answer)
*answer = (struct nlmsghdr *)buf;
else
free(buf);
if (i < iovlen)
goto next;
return error ? -i : 0;
}
if (answer) {
*answer = (struct nlmsghdr *)buf;
return 0;/*find the first onegive it to user.*/
}
fprintf(stderr, "Unexpected reply!!!\n");
status -= NLMSG_ALIGN(len);
h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
printf("goto next nlmsghdr");
}
free(buf);
if (msg.msg_flags & MSG_TRUNC) {
fprintf(stderr, "Message truncated\n");
continue;
}
if (status) {
fprintf(stderr, "!!!Remnant of size %d\n", status);
exit(1);
}
}
}
static int __commnl_talk(struct upmnl_handle *nl, struct nlmsghdr *n,
struct nlmsghdr **answer,
bool show_rtnl_err, nl_ext_ack_fn_t errfn)
{
struct iovec iov = {
.iov_base = n,
.iov_len = n->nlmsg_len
};
return __commnl_talk_iov(nl, &iov, 1, answer, show_rtnl_err, errfn);
}
int commnl_talk(struct upmnl_handle *nl, struct nlmsghdr *n,
struct nlmsghdr **answer)
{
return __commnl_talk(nl, n, answer, true, NULL);
}
int pdeliv_talk(int group,struct nlmsghdr *n, struct nlmsghdr **answer)
{
struct upmnl_handle *nl = NULL;
nl = commnl_get_handle(NETLINK_PDELIVERY,group);
if(nl == NULL)
{
printf("pdeliv_talk faid,pdeliv netlink has not open.\r\n");
return -1;
}
printf("pdeliv_talk send msg type=%d,len=%d.\r\n",n->nlmsg_type,n->nlmsg_len);
return(commnl_talk(nl,n,answer));
}
int commcfg_talk(struct nlmsghdr *n, struct nlmsghdr **answer)
{
struct upmnl_handle *nl = NULL;
nl = commnl_get_handle(NETLINK_COMMCFG,0);
if(nl == NULL)
{
printf("commcfg_talk faid,commcfg netlink has not open.\r\n");
return -1;
}
printf("commcfg_talk send msg type=%d,len=%d.\r\n",n->nlmsg_type,n->nlmsg_len);
return(commnl_talk(nl,n,answer));
}
int pdelivnl_listen(int group,
pdelivnl_listen_filter_t handler,
void *jarg)
{
struct upmnl_handle *nl = NULL;
printf("pdelivnl_listen:.\r\n");
nl = commnl_get_handle(NETLINK_PDELIVERY,group);
if(nl == NULL)
{
printf("pdelivnl_listen faid,pdeliv netlink has not open.\r\n");
return -1;
}
return(conmnl_listen(nl,handler,jarg));
}
int conmnl_listen(struct upmnl_handle *nl,
pdelivnl_listen_filter_t handler,
void *jarg)
{
int status;
struct nlmsghdr *h;
struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
struct iovec iov;
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
char buf[16384];
char cmsgbuf[BUFSIZ];
//printf("conmnl_listen begin.\r\n");
#if 0
if (nl->flags & RTNL_HANDLE_F_LISTEN_ALL_NSID) {
msg.msg_control = &cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
}
#endif
iov.iov_base = buf;
while (1) {
struct pdelivnl_ctrl_data ctrl;
struct cmsghdr *cmsg;
//printf("pdelivnl_listen recvmsg....\r\n");
iov.iov_len = sizeof(buf);
//status = recvmsg(nl->fd, &msg, MSG_WAITALL);
if(nl->fd <= 0)
{
printf("conmnl_listen fd is closed,fd = %d,exist listen.\r\rn",nl->fd);
return 0;
}
status = recvmsg(nl->fd, &msg, MSG_WAITFORONE);
if (status < 0) {
if (errno == EINTR || errno == EAGAIN)/*超时*/
continue;
fprintf(stderr, "netlink receive error: %s (%d)\n",
strerror(errno), errno);
if (errno == ENOBUFS)
continue;
return -1;
}
if (status == 0) {
fprintf(stderr, "EOF on netlink\n");
return -1;
}
if (msg.msg_namelen != sizeof(nladdr)) {
fprintf(stderr,
"Sender address length == %d\n",
msg.msg_namelen);
exit(1);
}
#if 0
if (nl->flags & RTNL_HANDLE_F_LISTEN_ALL_NSID) {
memset(&ctrl, 0, sizeof(ctrl));
ctrl.nsid = -1;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg;
cmsg = CMSG_NXTHDR(&msg, cmsg))
if (cmsg->cmsg_level == SOL_NETLINK &&
cmsg->cmsg_type == NETLINK_LISTEN_ALL_NSID &&
cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
int *data = (int *)CMSG_DATA(cmsg);
ctrl.nsid = *data;
}
}
#endif
#if 1
//printf("pdelivnl_listen prase msg:\r\n");
for (h = (struct nlmsghdr *)buf; status >= sizeof(*h); ) {
int err;
int len = h->nlmsg_len;
int l = len - sizeof(*h);
if (l < 0 || len > status) {
//if (msg.msg_flags & MSG_TRUNC) {
//fprintf(stderr, "Truncated message\n");
//return -1;
//}
fprintf(stderr,
"!!!malformed message: len=%d\n",
len);
exit(1);
}
err = handler(&ctrl, h, jarg);
if (err < 0)
return err;
status -= NLMSG_ALIGN(len);
h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
}
#endif
//if (msg.msg_flags & MSG_TRUNC) {
//fprintf(stderr, "Message truncated\n");
//continue;
//}
if (status) {
fprintf(stderr, "!!!Remnant of size %d\n", status);
exit(1);
}
}
}
#if 0
int upnl_dump_type(struct upmnl_handle *upmh, unsigned int type)
{
struct {
struct nlmsghdr nlh;
//struct rtgenmsg g;
} req;
struct sockaddr_nl nladdr;
memset(&nladdr, 0, sizeof(nladdr));
memset(&req, 0, sizeof(req));
nladdr.nl_family = AF_NETLINK;
req.nlh.nlmsg_len = sizeof(req);
req.nlh.nlmsg_type = type;
req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
req.nlh.nlmsg_pid = 0;
//req.nlh.nlmsg_seq = upmh->rtnl_dump = ++(upmh->rtnl_seq);
req.nlh.nlmsg_seq = 1;
//req.g.rtgen_family = AF_INET;
return sendto(upmh->fd, &req, sizeof(req), 0,
(struct sockaddr*)&nladdr, sizeof(nladdr));
}
#endif
int pdeliv_main(pdelivnl_listen_filter_t process_pkt)
{
int ret = -1;
printf("pdeliv_main begin:\r\n");
/*创建通道*/
ret = pdelivnl_open(PDNLGRP_ALLRAW);
if(ret < 0)
{
printf("pdelivnl_open fail,exit.\r\n");
return -1;
}
/*接收报文*/
pdelivnl_listen(PDNLGRP_ALLRAW,process_pkt,NULL);
/*关闭netlink通道*/
pdelivnl_close(PDNLGRP_ALLRAW);
printf("pdeliv_main exit!\r\n");
return 0;
}
void nl_debugfs(struct nlmsghdr *n)
{
struct netlink_debugfs *debugfs_total =NULL;
struct netlink_debugfs *debugfs_msgtype =NULL;
int msg_len = 0;
debugfs_total = (struct netlink_debugfs *)NLMSG_DATA(n);/*msg data*/
msg_len = (n)->nlmsg_len - NLMSG_HDRLEN; /*msg_len*/
debugfs_msgtype = debugfs_total+1;
printf("netlink total msg stats:\r\n");
printf(" rev_total = %d\n",debugfs_total->rev_total);
printf(" rev_cb_sucess = %d\n",debugfs_total->rev_cb_sucess);
printf(" rev_cb_fail = %d\n",debugfs_total->rev_cb_fail);
printf(" rev_drop_total = %d\n",debugfs_total->rev_drop_total);
printf(" rev_drop_nodoit = %d\n",debugfs_total->rev_drop_nodoit);
printf(" send_succ = %d\n",debugfs_total->send_succ);
printf(" send_fail = %d\n",debugfs_total->send_fail);
printf("netlink msg stats:\r\n");
printf(" rev_total = %d\n",debugfs_msgtype->rev_total);
printf(" rev_cb_sucess = %d\n",debugfs_msgtype->rev_cb_sucess);
printf(" rev_cb_fail = %d\n",debugfs_msgtype->rev_cb_fail);
printf(" rev_drop_total = %d\n",debugfs_msgtype->rev_drop_total);
printf(" rev_drop_nodoit = %d\n",debugfs_msgtype->rev_drop_nodoit);
printf(" send_succ = %d\n",debugfs_msgtype->send_succ);
printf(" send_fail = %d\n",debugfs_msgtype->send_fail);
return;
}
void nl_debugfs_extack(struct nlmsghdr *n)
{
//struct netlink_debugfs *debugfs_statis =NULL;
char * rcv_cookies = NULL;
int msg_len = 0;
struct nlmsgerr *errmsg = NULL;
struct rtattr * cookies = NULL;
int cookies_len = 0;
char * ptr;
printf("nl_debugfs_extack said:\r\nmsgtype=%d,msglen=%d\r\n",n->nlmsg_type,n->nlmsg_len);
errmsg = (struct nlmsgerr *)NLMSG_DATA(n);/*msg data*/
msg_len = (n)->nlmsg_len - NLMSG_HDRLEN; /*msg_len*/
printf("ack result=%d,ack msgtype:%d\r\n",errmsg->error,errmsg->msg.nlmsg_type);
if(errmsg->error == 0)/*ack result is SUCESS*/
{
ptr = (char * )errmsg + sizeof(struct nlmsgerr);
cookies = (struct rtattr *)ptr;
//if(NLMSGERR_ATTR_COOKIE == cookies->rta_type)
{
cookies_len = cookies->rta_len;
rcv_cookies = RTA_DATA(cookies);
printf("nl_debugfs_extack rcv cookies:%s.\r\n",rcv_cookies);
}
}
else{
printf("nl_debugfs kernel said fail,error =%d.\r\n",errmsg->error);
}
return;
}