diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2012-07-02 19:18:00 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2012-07-02 19:18:00 +0400 |
commit | 046642d5729493b25e5fba4b11c507fe3d2e2687 (patch) | |
tree | 4118ed7e1e890f76140ffb4e243a2eec5f0f841e /accel-pppd/libnetlink | |
parent | 7c245028fe4c54d61f2e0c67f709999af5fea40a (diff) | |
download | accel-ppp-046642d5729493b25e5fba4b11c507fe3d2e2687.tar.gz accel-ppp-046642d5729493b25e5fba4b11c507fe3d2e2687.zip |
ipoe: integrating accel-pppd and ipoe kernel module
Diffstat (limited to 'accel-pppd/libnetlink')
-rw-r--r-- | accel-pppd/libnetlink/genl.c | 108 | ||||
-rw-r--r-- | accel-pppd/libnetlink/genl.h | 6 | ||||
-rw-r--r-- | accel-pppd/libnetlink/libnetlink.c | 2 |
3 files changed, 115 insertions, 1 deletions
diff --git a/accel-pppd/libnetlink/genl.c b/accel-pppd/libnetlink/genl.c new file mode 100644 index 0000000..7d74556 --- /dev/null +++ b/accel-pppd/libnetlink/genl.c @@ -0,0 +1,108 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <syslog.h> +#include <fcntl.h> +#include <net/if_arp.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <string.h> +#include <errno.h> +#include <time.h> +#include <sys/uio.h> +#include <linux/genetlink.h> + +#include "triton.h" +#include "log.h" + +#include "libnetlink.h" + +#define GENL_MAX_FAM_GRPS 128 + +int __export genl_resolve_mcg(const char *family, const char *name, int *fam_id) +{ + struct rtnl_handle rth; + struct nlmsghdr *nlh; + struct genlmsghdr *ghdr; + struct rtattr *tb[CTRL_ATTR_MAX + 1]; + struct rtattr *tb2[GENL_MAX_FAM_GRPS + 1]; + struct rtattr *tb3[CTRL_ATTR_MCAST_GRP_MAX + 1]; + struct rtattr *attrs; + int i, len, ret = -1; + struct { + struct nlmsghdr n; + char buf[4096]; + } req; + + if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC)) { + log_error("genl: cannot open rtnetlink\n"); + return -1; + } + + nlh = &req.n; + nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + nlh->nlmsg_type = GENL_ID_CTRL; + + ghdr = NLMSG_DATA(&req.n); + ghdr->cmd = CTRL_CMD_GETFAMILY; + + addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME, family, strlen(family) + 1); + + if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) { + log_error("genl: error talking to kernel\n"); + goto out; + } + + if (nlh->nlmsg_type != GENL_ID_CTRL) { + log_error("genl: not a controller message %d\n", nlh->nlmsg_type); + goto out; + } + + ghdr = NLMSG_DATA(nlh); + + if (ghdr->cmd != CTRL_CMD_NEWFAMILY) { + log_error("genl: unknown controller command %d\n", ghdr->cmd); + goto out; + } + + len = nlh->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN); + + if (len < 0) { + log_error("genl: wrong controller message len %d\n", len); + goto out; + } + + attrs = (struct rtattr *)((char *)ghdr + GENL_HDRLEN); + parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len); + + if (!tb[CTRL_ATTR_FAMILY_ID]) { + log_error("genl: missing CTRL_FAMILY_ID attribute\n"); + goto out; + } + + if (!tb[CTRL_ATTR_MCAST_GROUPS]) + goto out; + + if (fam_id) + *fam_id = *(uint32_t *)(RTA_DATA(tb[CTRL_ATTR_FAMILY_ID])); + + parse_rtattr_nested(tb2, GENL_MAX_FAM_GRPS, tb[CTRL_ATTR_MCAST_GROUPS]); + + for (i = 1; i < GENL_MAX_FAM_GRPS; i++) { + if (tb2[i]) { + parse_rtattr_nested(tb3, CTRL_ATTR_MCAST_GRP_MAX, tb2[i]); + if (!tb3[CTRL_ATTR_MCAST_GRP_ID] || !tb3[CTRL_ATTR_MCAST_GRP_NAME]) + continue; + if (strcmp(RTA_DATA(tb3[CTRL_ATTR_MCAST_GRP_NAME]), name)) + continue; + ret = *(uint32_t *)(RTA_DATA(tb3[CTRL_ATTR_MCAST_GRP_ID])); + break; + } + } + +out: + + rtnl_close(&rth); + return ret; +} diff --git a/accel-pppd/libnetlink/genl.h b/accel-pppd/libnetlink/genl.h new file mode 100644 index 0000000..5239d86 --- /dev/null +++ b/accel-pppd/libnetlink/genl.h @@ -0,0 +1,6 @@ +#ifndef __GENL_H +#define __GENL_H + +int genl_resolve_mcg(const char *family, const char *name, int *fam_id); + +#endif diff --git a/accel-pppd/libnetlink/libnetlink.c b/accel-pppd/libnetlink/libnetlink.c index 55a1a67..808e433 100644 --- a/accel-pppd/libnetlink/libnetlink.c +++ b/accel-pppd/libnetlink/libnetlink.c @@ -652,7 +652,7 @@ int __export rta_addattr_l(struct rtattr *rta, int maxlen, int type, return 0; } -int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) +int __export parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) { memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); while (RTA_OK(rta, len)) { |