Add generic netlink infrastructure
This commit is contained in:
parent
60329986b2
commit
5db476bb6e
3 changed files with 86 additions and 4 deletions
88
l2tpns.c
88
l2tpns.c
|
|
@ -38,6 +38,7 @@
|
|||
#include <libcli.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/genetlink.h>
|
||||
|
||||
#include "md5.h"
|
||||
#include "dhcp6.h"
|
||||
|
|
@ -64,6 +65,7 @@ uint32_t call_serial_number = 0;
|
|||
// Globals
|
||||
configt *config = NULL; // all configuration
|
||||
int rtnlfd = -1; // route netlink socket
|
||||
int genlfd = -1; // generic netlink socket
|
||||
int tunfd = -1; // tun interface file handle. (network device)
|
||||
int udpfd[MAX_UDPFD + 1] = INIT_TABUDPFD; // array UDP file handle + 1 for lac udp
|
||||
int udplacfd = -1; // UDP LAC file handle
|
||||
|
|
@ -79,6 +81,7 @@ time_t basetime = 0; // base clock
|
|||
char hostname[MAXHOSTNAME] = ""; // us.
|
||||
static int tunidx; // ifr_ifindex of tun device
|
||||
int rtnlseqnum = 0; // route netlink sequence number
|
||||
int genlseqnum = 0; // generic netlink sequence number
|
||||
int min_initok_rtnlseqnum = 0; // minimun seq number for messages after init is ok
|
||||
static int syslog_log = 0; // are we logging to syslog
|
||||
FILE *log_stream = 0; // file handle for direct logging (i.e. direct into file, not via syslog).
|
||||
|
|
@ -241,8 +244,12 @@ struct Tringbuffer *ringbuffer = NULL;
|
|||
#endif
|
||||
|
||||
static ssize_t rtnetlink_send(struct nlmsghdr *nh);
|
||||
static int netlink_handle_ack(struct nlmsghdr *nh, int min_initok_nlseqnum, char *tun_nl_phase_msg[]);
|
||||
static ssize_t genetlink_send(struct nlmsghdr *nh);
|
||||
static ssize_t genetlink_recv(void *buf, ssize_t len);
|
||||
static int netlink_handle_ack(struct nlmsghdr *nh, int gen, int min_initok_nlseqnum, char *tun_nl_phase_msg[]);
|
||||
static void rtnetlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen);
|
||||
static void genetlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen);
|
||||
static int genetlink_getattr(struct nlmsghdr *nh, int type, void *data, int alen);
|
||||
static void cache_ipmap(in_addr_t ip, sessionidt s);
|
||||
static void uncache_ipmap(in_addr_t ip);
|
||||
static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s);
|
||||
|
|
@ -630,6 +637,23 @@ static void initnetlink(void)
|
|||
LOG(0, 0, 0, "Can't bind route netlink socket: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
genlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
|
||||
if (genlfd < 0)
|
||||
{
|
||||
LOG(0, 0, 0, "Can't create generic netlink socket: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(&nladdr, 0, sizeof(nladdr));
|
||||
nladdr.nl_family = AF_NETLINK;
|
||||
nladdr.nl_pid = getpid();
|
||||
|
||||
if (bind(genlfd, (struct sockaddr *)&nladdr, sizeof(nladdr)) < 0)
|
||||
{
|
||||
LOG(0, 0, 0, "Can't bind generic netlink socket: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -660,6 +684,13 @@ static ssize_t rtnetlink_send(struct nlmsghdr *nh)
|
|||
return netlink_send(rtnlfd, &rtnlseqnum, nh);
|
||||
}
|
||||
|
||||
//
|
||||
// Send message to the generic netlink socket
|
||||
static ssize_t genetlink_send(struct nlmsghdr *nh)
|
||||
{
|
||||
return netlink_send(genlfd, &genlseqnum, nh);
|
||||
}
|
||||
|
||||
//
|
||||
// Receive a message from a netlink socket
|
||||
static ssize_t netlink_recv(int fd, void *buf, ssize_t len)
|
||||
|
|
@ -685,9 +716,16 @@ static ssize_t rtnetlink_recv(void *buf, ssize_t len)
|
|||
return netlink_recv(rtnlfd, buf, len);
|
||||
}
|
||||
|
||||
//
|
||||
// Receive a message from the generic netlink socket
|
||||
static ssize_t genetlink_recv(void *buf, ssize_t len)
|
||||
{
|
||||
return netlink_recv(genlfd, buf, len);
|
||||
}
|
||||
|
||||
//
|
||||
// Look ack netlink message for errors
|
||||
static int netlink_handle_ack(struct nlmsghdr *nh, int min_initok_nlseqnum, char *tun_nl_phase_msg[])
|
||||
static int netlink_handle_ack(struct nlmsghdr *nh, int gen, int min_initok_nlseqnum, char *tun_nl_phase_msg[])
|
||||
{
|
||||
if (nh->nlmsg_type == NLMSG_ERROR)
|
||||
{
|
||||
|
|
@ -701,7 +739,13 @@ static int netlink_handle_ack(struct nlmsghdr *nh, int min_initok_nlseqnum, char
|
|||
}
|
||||
else
|
||||
{
|
||||
LOG(0, 0, 0, "For netlink request %d, got a netlink error: %s\n", errmsg->msg.nlmsg_type, strerror(-errmsg->error));
|
||||
if (gen)
|
||||
{
|
||||
struct genlmsghdr *glh = NLMSG_DATA(&errmsg->msg);
|
||||
LOG(0, 0, 0, "For generic netlink request %d on %d, got a netlink error: %s\n", glh->cmd, errmsg->msg.nlmsg_type, strerror(-errmsg->error));
|
||||
}
|
||||
else
|
||||
LOG(0, 0, 0, "For netlink request %d, got a netlink error: %s\n", errmsg->msg.nlmsg_type, strerror(-errmsg->error));
|
||||
errno = -errmsg->error;
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -732,6 +776,42 @@ static void rtnetlink_addattr(struct nlmsghdr *nh, int type, const void *data, i
|
|||
nh->nlmsg_len = NLMSG_ALIGN(nh->nlmsg_len) + RTA_ALIGN(len);
|
||||
}
|
||||
|
||||
//
|
||||
// Add an attribute to a message for a generic netlink socket
|
||||
static void genetlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen)
|
||||
{
|
||||
int len = NLA_HDRLEN + alen;
|
||||
struct nlattr *nla;
|
||||
|
||||
nla = (struct nlattr *)(((void *)nh) + NLMSG_ALIGN(nh->nlmsg_len));
|
||||
nla->nla_type = type;
|
||||
nla->nla_len = len;
|
||||
memcpy((char*)nla + NLA_HDRLEN, data, alen);
|
||||
nh->nlmsg_len = NLMSG_ALIGN(nh->nlmsg_len) + NLA_ALIGN(len);
|
||||
}
|
||||
|
||||
//
|
||||
// Find attribute from a message
|
||||
static int genetlink_getattr(struct nlmsghdr *nh, int type, void *attr, int alen)
|
||||
{
|
||||
char *glh = NLMSG_DATA(nh);
|
||||
char *data = glh + GENL_HDRLEN;
|
||||
char *data_end = data + nh->nlmsg_len - NLMSG_HDRLEN - GENL_HDRLEN;
|
||||
struct nlattr *ah;
|
||||
|
||||
for (ah = (void*) data; (char*) ah < data_end; ah = (void*) ((char *) ah + NLA_ALIGN(ah->nla_len)))
|
||||
{
|
||||
if ((ah->nla_type & NLA_TYPE_MASK) == type)
|
||||
{
|
||||
if (ah->nla_len != NLA_HDRLEN + alen)
|
||||
LOG(0, 0, 0, "Erroneous attribute %d size\n", type);
|
||||
memcpy(attr, ((char*) ah + NLA_HDRLEN), alen);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// messages corresponding to different phases seq number
|
||||
static char *tun_rtnl_phase_msg[] = {
|
||||
"initialized",
|
||||
|
|
@ -4391,7 +4471,7 @@ static void mainloop(void)
|
|||
{
|
||||
struct nlmsghdr *nh = (struct nlmsghdr *)p;
|
||||
s = rtnetlink_recv(p, size_bufp);
|
||||
netlink_handle_ack(nh, min_initok_rtnlseqnum, tun_rtnl_phase_msg);
|
||||
netlink_handle_ack(nh, 0, min_initok_rtnlseqnum, tun_rtnl_phase_msg);
|
||||
n--;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
1
l2tpns.h
1
l2tpns.h
|
|
@ -1038,6 +1038,7 @@ extern struct Tstats *_statistics;
|
|||
extern in_addr_t my_address;
|
||||
extern int clifd;
|
||||
extern int rtnlfd;
|
||||
extern int genlfd;
|
||||
extern int epollfd;
|
||||
extern FILE *log_stream;
|
||||
|
||||
|
|
|
|||
1
util.c
1
util.c
|
|
@ -121,6 +121,7 @@ pid_t fork_and_close()
|
|||
#endif /* BGP */
|
||||
|
||||
if (rtnlfd != -1) close(rtnlfd);
|
||||
if (genlfd != -1) close(genlfd);
|
||||
if (pppoediscfd != -1) close(pppoediscfd);
|
||||
if (pppoesessfd != -1) close(pppoesessfd);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue