📄 netlink_socket.c
字号:
#include <asm/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <err.h>
#include <stdio.h>
#include <netinet/in.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <signal.h>
//#include <fcntl.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <net/ppp_defs.h>
#include <linux/if.h>
#include <linux/if_ppp.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> // for O_RDWR
#include <errno.h> // for errno
#include<time.h>
#include<stdlib.h>
#include "Netlink_Socket.h"
#include "wcommon.h"
#include "syslog.h"
//#include "Bcmnvram.h"
// netlink socket 用于应用与内核通信
int NetlinkOpen()
{
int sockfd;
struct sockaddr_nl addr;
// create netlink socket
sockfd = socket(AF_NETLINK,SOCK_RAW,MYPROTO);
if (sockfd<0)
{
perror( "socket error" );
return sockfd;
}
memset((void *)&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_pid = getpid(); // 用于区分不同的接收者或发送者的一个标识
// 如果希望内核处理消息或多播消息,就把该字段设置为 0
// 多线程的时候, 可以这样设 pthread_self() << 16 | getpid();
addr.nl_groups = 1; // 调用者不加入任何多播组
// kill "Address already in use" error message
//*
{
int tr = 1;
fcntl( sockfd, F_SETFD, 1 );
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &tr, sizeof(int)) == -1) {
perror("setsockopt");
return -1;
}
}
//*/
// 把一个打开的 netlink socket 与 netlink 源 socket 地址绑定在一起
if ( bind(sockfd,(struct sockaddr *)&addr,sizeof(addr))<0 )
{
close( sockfd );
perror( "bind error" );
return -1;
}
return sockfd;
}
void NetlinkClose(int sockfd)
{
Print( "Close sockfd: %d", sockfd );
if ( sockfd<0 )
return;
close( sockfd );
}
/*
static struct sockaddr_nl src_addr, dest_addr;
static struct nlmsghdr *nlh;
static struct iovec iov;
static struct msghdr msg;
static int sock_fd;
#define MAX_NL_MSG_LEN 1024
cprintf("\nEnter recv_msg........\n");
sock_fd = socket(AF_NETLINK, SOCK_RAW, 17);
if(sock_fd < 0){
printf("socket failed......\n");
return -1;
}
Print("sock_fd:%d", sock_fd);
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); // self pid
src_addr.nl_groups = 1;
if(bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr)) < 0){
close(sock_fd);
printf("bind failed......\n");
return -1;
}
Print("bind success.");
memset(&dest_addr, 0, sizeof(dest_addr));
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_NL_MSG_LEN));
if(!nlh){
close(sock_fd);
printf("alloc failed......\n");
return -1;
}
memset(nlh, 0, NLMSG_SPACE(MAX_NL_MSG_LEN));
char msg2ker = 0x01;
memcpy(NLMSG_DATA(nlh), &msg2ker, 1);
nlh->nlmsg_len = NLMSG_LENGTH(1);
nlh->nlmsg_pid = getpid(); // self pid
nlh->nlmsg_flags = 0;
iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
Print("Send msg...");
int kk = sendmsg(sock_fd, &msg, 0);
Print("kk=%d", kk);
memset(nlh, 0, NLMSG_SPACE(MAX_NL_MSG_LEN));
iov.iov_base = (void *)nlh;
iov.iov_len = NLMSG_SPACE(MAX_NL_MSG_LEN);
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
{
char *data;
cprintf("Going to recvmsg........\n");
if(recvmsg(sock_fd, &msg, 0) <= 0){
printf("recvmsg error........continue\n");
//continue;
}
data = (char *)NLMSG_DATA(nlh);
Print("data: %d", data[0]);
}
printf("Exit??????.........\n");
close(sock_fd);
//*/
int NetlinkSendData( int sockfd, unsigned char *buffer, int len )
{
struct iovec iov;
struct nlmsghdr *nlhdr;
struct msghdr msg;
struct sockaddr_nl dest_addr;
if ( buffer==NULL || len <= 0 || sockfd<0 )
{
printf("para error.");
return -1;
}
//printf( "%d, %d, %d\n", buffer[0], len, sockfd );
nlhdr = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_MSGSIZE));
if ( nlhdr == NULL )
{
close( sockfd );
perror("malloc error.");
return -1;
}
memset( nlhdr, 0, NLMSG_SPACE(MAX_MSGSIZE) );
memcpy( NLMSG_DATA(nlhdr), buffer, len );
nlhdr->nlmsg_len = NLMSG_LENGTH( len );
nlhdr->nlmsg_pid = getpid(); /* self pid */
nlhdr->nlmsg_flags = 0;
iov.iov_base = (void *)nlhdr;
iov.iov_len = nlhdr->nlmsg_len;
// memset( &dest_addr, 0, sizeof(dest_addr) );
// dest_addr.nl_family = AF_NETLINK;
// dest_addr.nl_pid = 0; // For linux Kernel
// dest_addr.nl_groups = 0; /* unicast */
memset( &msg, 0, sizeof(msg) );
// msg.msg_name = (void *)&dest_addr;
// msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
int ret = sendmsg(sockfd, &msg, 0);
if (ret<0)
{
free( nlhdr );
perror( "sendmsg error" );
return ret;
}
free( nlhdr );
return 0;
}
int NetlinkRecvData( int sockfd, unsigned char *buffer, int *len )
{
struct iovec iov;
struct nlmsghdr *nlhdr;
struct msghdr msg;
struct sockaddr_nl src_addr = {0};
int nLen;
if ( buffer==NULL || len==NULL || sockfd<0 )
{
printf("parameter error.");
return -1;
}
// nLen = *len;
// printf("%d, %d, %d", sockfd, buffer[0], *len );
nlhdr = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_MSGSIZE));
if ( nlhdr == NULL )
{
Perror( "malloc error." );
close ( sockfd );
return -1;
}
memset( nlhdr, 0, NLMSG_SPACE(MAX_MSGSIZE) );
// memcpy( NLMSG_DATA(nlhdr), buffer, len );
// nlhdr->nlmsg_len = NLMSG_LENGTH( len );
// nlhdr->nlmsg_pid = getpid(); /* self pid */
// nlhdr->nlmsg_flags = 0;
iov.iov_base = (void *)nlhdr;
iov.iov_len = NLMSG_SPACE(MAX_MSGSIZE);
// memset( &dest_addr, 0, sizeof(dest_addr) );
// dest_addr.nl_family = AF_NETLINK;
// dest_addr.nl_pid = getpid();
// dest_addr.nl_groups = 0; /* unicast */
memset( (void *)&msg, 0, sizeof(msg) );
msg.msg_name = (void *)&src_addr;
msg.msg_namelen = sizeof(src_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
int ret = recvmsg(sockfd, &msg, 0);
if (ret<0)
{
free( nlhdr );
Perror( "recvmsg error" );
Info( "sockfd=%d, ret=%d\n", sockfd, ret );
close(sockfd);
Info( "sockfd=%d\n", sockfd );
// return ret;
return -1;
}
//printf("nlhdr->nlmsg_len:%d, sizeof(struct nlmsghdr): %d iov.iov_len:%d\n",
// nlhdr->nlmsg_len, sizeof(struct nlmsghdr), iov.iov_len );
//nLen = nlhdr->nlmsg_len-sizeof(struct nlmsghdr);
nLen = nlhdr->nlmsg_len;
if ( nLen > *len ) nLen = *len;
Info ( "nlen=%d, \n", nLen );
if ( nLen != 1 )
return -1;
memcpy( buffer, NLMSG_DATA(nlhdr), nLen );
free( nlhdr );
*len = nLen;
return nLen;
}
int GetFlowData( int unit, int *rx_bytes, int *tx_bytes )
{
// #ifdef W_TEST
// //srand((int)time(0));
// //*rx_bytes = rand();
// //*tx_bytes = rand();
// *rx_bytes = 0;
// *tx_bytes = 0;
// return 0;
// #else
int fd = socket (AF_INET, SOCK_DGRAM, 0);
struct ifpppstatsreq req;
if (fd < 0) {
Print("GetFlowData fd:%d\n", fd);
perror ("socket for getting flow");
fd = -1;
return -1;
}
memset (&req, 0, sizeof (req));
req.stats_ptr = (caddr_t) &req.stats;
//strncpy (req.ifr__name, ifname, sizeof (req.ifr__name));
sprintf( req.ifr__name, "ppp%d", unit );
// dPrint("ioctl....");
if (ioctl (fd, SIOCGPPPSTATS, &req) < 0) {
perror ("ioctl (SIOCGPPPSTATS)");
close( fd );
return -2;
}
*rx_bytes = req.stats.p.ppp_ibytes;
*tx_bytes = req.stats.p.ppp_obytes;
close( fd );
return 0;
//#endif
}
// int main()
// {
//
// int sockfd = NetlinkOpen();
//
// NetlinkSendData( sockfd, "ok", 2 );
// //int NetlinkRecvData( int sockfd, unsigned char *buffer, int *len );
//
// NetlinkClose(sockfd);
//
// return 1;
// }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int FileGetSize( char * filename )
{
FILE *fp;
int len;
if ( filename==NULL )
return -1;
fp=fopen( filename, "r" );
fseek( fp, 0, SEEK_END );
len = ftell( fp );
fclose(fp);
return len;
}
// read whole file
int FileReadWhole( const char *fn, char * str, int size )
{
FILE * fp;
char line[256];
int len = 0, tlen;
if (fn==NULL||str==NULL)
{
printf("parameter error.\n");
return -1;
}
//fp = fopen( "file.txt", "a" ); //append
fp = fopen( fn, "r" );
if ( fp==NULL )
{
perror( "open file failure" );
return -2;
}
while( !feof(fp) )
{
if ( fgets( line, 256, fp ) != NULL )
{
tlen = strlen(line);
if ( len+tlen > size )
{
printf("data too long.\n");
return -3;
}
strncpy( str+len, line, tlen );
len += tlen;
}
}
fclose( fp );
str[len] = '\0';
return len;
}
// read whole file
// 有换行问题
char* FileReadWholeEx( const char *fn )
{
FILE * fp;
char line[256];
int len = 0, tlen;
int filesize;
char * buf;
if (fn==NULL )
{
printf("parameter error.\n");
return NULL;
}
// get file size
fp = fopen( fn, "r" );
if ( fp==NULL )
{
perror( "open file failure" );
return NULL;
}
fseek( fp, 0, SEEK_END );
filesize = ftell( fp );
fseek( fp, 0, SEEK_SET );
// malloc buf
filesize *= 2; // increase size
buf = (char *)malloc( filesize );
if ( buf==NULL ) return NULL;
memset( buf, 0, filesize );
// read file to buf add s\r
//*
while( !feof(fp) )
{
if ( fgets( line, 256, fp ) != NULL )
{
tlen = sprintf( buf+len, "%s", line );
len += tlen;
// add \r
buf[len-1] = '\r';
buf[len] = '\n';
len++;
}
}
//*/
// fread( buf, filesize, 1, fp );
fclose( fp );
// buf[len] = '\0';
return buf;
}
// 查找str中子串s的个数
int strstrcnt( const char*str, const char*s)
{
char *p=(char*)str;
int count=0;
if ( str==NULL || s==NULL )
return -1;
do{
p=strstr(p,s);
if( p )
{
p+=strlen(s);
count++;
}
}while( p );
return count;
}
int FileWrite( const char *fn, const char * str )
{
FILE *fp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -