⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libnetlink.c

📁 busybox最新版的源码:学习和应用的好东东,多的不说了,大家看后再说吧
💻 C
字号:
/* vi: set sw=4 ts=4: *//* * libnetlink.c	RTnetlink service routines. * *		This program is free software; you can redistribute it and/or *		modify it under the terms of the GNU General Public License *		as published by the Free Software Foundation; either version *		2 of the License, or (at your option) any later version. * * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> * */#include <sys/socket.h>#include <sys/uio.h>#include "libbb.h"#include "libnetlink.h"void rtnl_close(struct rtnl_handle *rth){	close(rth->fd);}int xrtnl_open(struct rtnl_handle *rth/*, unsigned subscriptions*/){	socklen_t addr_len;	memset(rth, 0, sizeof(rth));	rth->fd = xsocket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);	memset(&rth->local, 0, sizeof(rth->local));	rth->local.nl_family = AF_NETLINK;	/*rth->local.nl_groups = subscriptions;*/	xbind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local));	addr_len = sizeof(rth->local);	if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0)		bb_perror_msg_and_die("cannot getsockname");	if (addr_len != sizeof(rth->local))		bb_error_msg_and_die("wrong address length %d", addr_len);	if (rth->local.nl_family != AF_NETLINK)		bb_error_msg_and_die("wrong address family %d", rth->local.nl_family);	rth->seq = time(NULL);	return 0;}int xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int type){	struct {		struct nlmsghdr nlh;		struct rtgenmsg g;	} req;	struct sockaddr_nl nladdr;	memset(&nladdr, 0, sizeof(nladdr));	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 = rth->dump = ++rth->seq;	req.g.rtgen_family = family;	return xsendto(rth->fd, (void*)&req, sizeof(req),				 (struct sockaddr*)&nladdr, sizeof(nladdr));}int rtnl_send(struct rtnl_handle *rth, char *buf, int len){	struct sockaddr_nl nladdr;	memset(&nladdr, 0, sizeof(nladdr));	nladdr.nl_family = AF_NETLINK;	return xsendto(rth->fd, buf, len, (struct sockaddr*)&nladdr, sizeof(nladdr));}int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len){	struct nlmsghdr nlh;	struct sockaddr_nl nladdr;	struct iovec iov[2] = { { &nlh, sizeof(nlh) }, { req, len } };	struct msghdr msg = {		(void*)&nladdr, sizeof(nladdr),		iov,	2,		NULL,	0,		0	};	memset(&nladdr, 0, sizeof(nladdr));	nladdr.nl_family = AF_NETLINK;	nlh.nlmsg_len = NLMSG_LENGTH(len);	nlh.nlmsg_type = type;	nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;	nlh.nlmsg_pid = 0;	nlh.nlmsg_seq = rth->dump = ++rth->seq;	return sendmsg(rth->fd, &msg, 0);}static int rtnl_dump_filter(struct rtnl_handle *rth,		int (*filter)(struct sockaddr_nl *, struct nlmsghdr *n, void *),		void *arg1/*,		int (*junk)(struct sockaddr_nl *, struct nlmsghdr *n, void *),		void *arg2*/){	char buf[8192];	struct sockaddr_nl nladdr;	struct iovec iov = { buf, sizeof(buf) };	while (1) {		int status;		struct nlmsghdr *h;		struct msghdr msg = {			(void*)&nladdr, sizeof(nladdr),			&iov,	1,			NULL,	0,			0		};		status = recvmsg(rth->fd, &msg, 0);		if (status < 0) {			if (errno == EINTR)				continue;			bb_perror_msg("OVERRUN");			continue;		}		if (status == 0) {			bb_error_msg("EOF on netlink");			return -1;		}		if (msg.msg_namelen != sizeof(nladdr)) {			bb_error_msg_and_die("sender address length == %d", msg.msg_namelen);		}		h = (struct nlmsghdr*)buf;		while (NLMSG_OK(h, status)) {			int err;			if (nladdr.nl_pid != 0 ||			    h->nlmsg_pid != rth->local.nl_pid ||			    h->nlmsg_seq != rth->dump) {/*				if (junk) {					err = junk(&nladdr, h, arg2);					if (err < 0)						return err;				} */				goto skip_it;			}			if (h->nlmsg_type == NLMSG_DONE) {				return 0;			}			if (h->nlmsg_type == NLMSG_ERROR) {				struct nlmsgerr *l_err = (struct nlmsgerr*)NLMSG_DATA(h);				if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {					bb_error_msg("ERROR truncated");				} else {					errno = -l_err->error;					bb_perror_msg("RTNETLINK answers");				}				return -1;			}			err = filter(&nladdr, h, arg1);			if (err < 0)				return err;skip_it:			h = NLMSG_NEXT(h, status);		}		if (msg.msg_flags & MSG_TRUNC) {			bb_error_msg("message truncated");			continue;		}		if (status) {			bb_error_msg_and_die("remnant of size %d!", status);		}	}}int xrtnl_dump_filter(struct rtnl_handle *rth,		int (*filter)(struct sockaddr_nl *, struct nlmsghdr *n, void *),		void *arg1){	int ret = rtnl_dump_filter(rth, filter, arg1/*, NULL, NULL*/);	if (ret < 0)		bb_error_msg_and_die("dump terminated");	return ret;}int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,	      unsigned groups, struct nlmsghdr *answer,	      int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *),	      void *jarg){	int status;	unsigned seq;	struct nlmsghdr *h;	struct sockaddr_nl nladdr;	struct iovec iov = { (void*)n, n->nlmsg_len };	char   buf[8192];	struct msghdr msg = {		(void*)&nladdr, sizeof(nladdr),		&iov,	1,		NULL,	0,		0	};	memset(&nladdr, 0, sizeof(nladdr));	nladdr.nl_family = AF_NETLINK;	nladdr.nl_pid = peer;	nladdr.nl_groups = groups;	n->nlmsg_seq = seq = ++rtnl->seq;	if (answer == NULL) {		n->nlmsg_flags |= NLM_F_ACK;	}	status = sendmsg(rtnl->fd, &msg, 0);	if (status < 0) {		bb_perror_msg("cannot talk to rtnetlink");		return -1;	}	iov.iov_base = buf;	while (1) {		iov.iov_len = sizeof(buf);		status = recvmsg(rtnl->fd, &msg, 0);		if (status < 0) {			if (errno == EINTR) {				continue;			}			bb_perror_msg("OVERRUN");			continue;		}		if (status == 0) {			bb_error_msg("EOF on netlink");			return -1;		}		if (msg.msg_namelen != sizeof(nladdr)) {			bb_error_msg_and_die("sender address length == %d", msg.msg_namelen);		}		for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {			int l_err;			int len = h->nlmsg_len;			int l = len - sizeof(*h);			if (l<0 || len>status) {				if (msg.msg_flags & MSG_TRUNC) {					bb_error_msg("truncated message");					return -1;				}				bb_error_msg_and_die("malformed message: len=%d!", len);			}			if (nladdr.nl_pid != peer ||			    h->nlmsg_pid != rtnl->local.nl_pid ||			    h->nlmsg_seq != seq) {				if (junk) {					l_err = junk(&nladdr, h, jarg);					if (l_err < 0) {						return l_err;					}				}				continue;			}			if (h->nlmsg_type == NLMSG_ERROR) {				struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);				if (l < sizeof(struct nlmsgerr)) {					bb_error_msg("ERROR truncated");				} else {					errno = -err->error;					if (errno == 0) {						if (answer) {							memcpy(answer, h, h->nlmsg_len);						}						return 0;					}					bb_perror_msg("RTNETLINK answers");				}				return -1;			}			if (answer) {				memcpy(answer, h, h->nlmsg_len);				return 0;			}			bb_error_msg("unexpected reply!");			status -= NLMSG_ALIGN(len);			h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));		}		if (msg.msg_flags & MSG_TRUNC) {			bb_error_msg("message truncated");			continue;		}		if (status) {			bb_error_msg_and_die("remnant of size %d!", status);		}	}}int addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data){	int len = RTA_LENGTH(4);	struct rtattr *rta;	if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)		return -1;	rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));	rta->rta_type = type;	rta->rta_len = len;	memcpy(RTA_DATA(rta), &data, 4);	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;	return 0;}int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen){	int len = RTA_LENGTH(alen);	struct rtattr *rta;	if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)		return -1;	rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));	rta->rta_type = type;	rta->rta_len = len;	memcpy(RTA_DATA(rta), data, alen);	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;	return 0;}int rta_addattr32(struct rtattr *rta, int maxlen, int type, uint32_t data){	int len = RTA_LENGTH(4);	struct rtattr *subrta;	if (RTA_ALIGN(rta->rta_len) + len > maxlen) {		return -1;	}	subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));	subrta->rta_type = type;	subrta->rta_len = len;	memcpy(RTA_DATA(subrta), &data, 4);	rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len;	return 0;}int rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen){	struct rtattr *subrta;	int len = RTA_LENGTH(alen);	if (RTA_ALIGN(rta->rta_len) + len > maxlen) {		return -1;	}	subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));	subrta->rta_type = type;	subrta->rta_len = len;	memcpy(RTA_DATA(subrta), data, alen);	rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len;	return 0;}int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len){	while (RTA_OK(rta, len)) {		if (rta->rta_type <= max) {			tb[rta->rta_type] = rta;		}		rta = RTA_NEXT(rta,len);	}	if (len) {		bb_error_msg("deficit %d, rta_len=%d!", len, rta->rta_len);	}	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -