请教linux下netlink编程问题

tuohaijun 2008-05-29 10:04:50
各位:
老师给了一段代码,是使用netink实现用户空间与内核空间通信的,代码我贴过来了,请大家帮我分析一下。
struct nfnl_subsys_handle {
struct nfnl_handle *nfnlh;
u_int32_t subscriptions;
u_int8_t subsys_id;
u_int8_t cb_count;
struct nfnl_callback *cb; /* array of callbacks */
};

struct nfct_handle
{
struct nfnl_handle *nfnlh;
struct nfnl_subsys_handle *nfnlssh_ct;
nfct_handler handler; /* netlink handler */
};


#define NFNL_MAX_SUBSYS 16 /* enough for now */
struct nfnl_handle {
int fd;
struct sockaddr_nl local;
struct sockaddr_nl peer;
u_int32_t subscriptions;
u_int32_t seq;
u_int32_t dump;
struct nlmsghdr *last_nlhdr;
struct nfnl_subsys_handle subsys[NFNL_MAX_SUBSYS+1];
};

struct nfct_handle *nfct_open(u_int8_t subsys_id, unsigned int subscriptions)
{
struct nfnl_handle *nfnlh = nfnl_open();
struct nfct_handle *cth;

if (!nfnlh)
return NULL;
cth = (struct nfct_handle *) malloc(sizeof(struct nfct_handle));
if (!cth)
return NULL;
memset(cth, 0, sizeof(*cth));
cth->nfnlh = nfnlh;
if (subsys_id == 0 || subsys_id == NFNL_SUBSYS_CTNETLINK)
{
cth->nfnlssh_ct = nfnl_subsys_open(cth->nfnlh, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_MAX, subscriptions);
if (!cth->nfnlssh_ct)
{
if (cth->nfnlssh_ct)
{
nfnl_subsys_close(cth->nfnlssh_ct);
cth->nfnlssh_ct = NULL;
}
free(cth);
}
}
if (!cth)
nfnl_close(nfnlh);
return cth;
}

static int recalc_rebind_subscriptions(struct nfnl_handle *nfnlh)
{
int i, err;
u_int32_t new_subscriptions = nfnlh->subscriptions;

for (i = 0; i < NFNL_MAX_SUBSYS; i++)
new_subscriptions |= nfnlh->subsys[i].subscriptions;


nfnlh->local.nl_groups = new_subscriptions;
err = bind(nfnlh->fd, (struct sockaddr *)&nfnlh->local,
sizeof(nfnlh->local));
if (err < 0) {
syslog(LOG_DEBUG, "bind(netlink): %s\n", strerror(errno));
return err;
}

nfnlh->subscriptions = new_subscriptions;

return 0;
}

/**
* nfnl_open - open a netlink socket
*
* nfnlh: libnfnetlink handle to be allocated by user
*
*/
struct nfnl_handle *nfnl_open(void)
{
struct nfnl_handle *nfnlh;
unsigned int addr_len;
int err;

nfnlh = malloc(sizeof(*nfnlh));
if (!nfnlh)
return NULL;

memset(nfnlh, 0, sizeof(*nfnlh));
nfnlh->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
if (nfnlh->fd < 0) {
syslog(LOG_DEBUG, "socket(netlink): %s\n", strerror(errno));
goto err_free;
}

nfnlh->local.nl_family = AF_NETLINK;
nfnlh->peer.nl_family = AF_NETLINK;

addr_len = sizeof(nfnlh->local);
err = getsockname(nfnlh->fd, (struct sockaddr *)&nfnlh->local,
&addr_len); //返回值定套接子的名称
if (addr_len != sizeof(nfnlh->local)) {
syslog(LOG_DEBUG, "Bad address length (%u != %zd)\n", addr_len,
sizeof(nfnlh->local));
goto err_close;
}
if (nfnlh->local.nl_family != AF_NETLINK) {
syslog(LOG_DEBUG, "Bad address family %d\n", nfnlh->local.nl_family);
goto err_close;
}
nfnlh->seq = time(NULL);

/* don't set pid here, only first socket of process has real pid !!!
* binding to pid '0' will default */

/* let us do the initial bind */
if (recalc_rebind_subscriptions(nfnlh) < 0)
goto err_close;

/* use getsockname to get the netlink pid that the kernel assigned us */
addr_len = sizeof(nfnlh->local);
err = getsockname(nfnlh->fd, (struct sockaddr *)&nfnlh->local,
&addr_len);
if (addr_len != sizeof(nfnlh->local)) {
syslog(LOG_DEBUG, "Bad address length (%u != %zd)\n", addr_len,
sizeof(nfnlh->local));
goto err_close;
}

return nfnlh;

err_close:
close(nfnlh->fd);
err_free:
free(nfnlh);
return NULL;
}

/**
* nfnl_subsys_open - open a netlink subsystem
*
* nfnlh: libnfnetlink handle
* subsys_id: which nfnetlink subsystem we are interested in
* cb_count: number of callbacks that are used maximum.
* subscriptions: netlink groups we want to be subscribed to
*/
struct nfnl_subsys_handle *nfnl_subsys_open(struct nfnl_handle *nfnlh, u_int8_t subsys_id,
u_int8_t cb_count, u_int32_t subscriptions)
{
struct nfnl_subsys_handle *ssh;

if (subsys_id > NFNL_MAX_SUBSYS) {

return NULL;
}

ssh = &nfnlh->subsys[subsys_id];
if (ssh->cb) {

return NULL;
}

ssh->cb = malloc(sizeof(*(ssh->cb)) * cb_count);
if (!ssh->cb) {

return NULL;
}

ssh->nfnlh = nfnlh;
ssh->cb_count = cb_count;
ssh->subscriptions = subscriptions;
ssh->subsys_id = subsys_id;

if (recalc_rebind_subscriptions(nfnlh) < 0) {
free(ssh->cb);
ssh->cb = NULL;
return NULL;
}

return ssh;
}


struct nfnl_subsys_handle *nfnl_subsys_open(struct nfnl_handle *nfnlh, u_int8_t subsys_id,
u_int8_t cb_count, u_int32_t subscriptions)
{
struct nfnl_subsys_handle *ssh;

if (subsys_id > NFNL_MAX_SUBSYS) {

return NULL;
}

ssh = &nfnlh->subsys[subsys_id];
if (ssh->cb) {

return NULL;
}

ssh->cb = malloc(sizeof(*(ssh->cb)) * cb_count);
if (!ssh->cb) {

return NULL;
}

ssh->nfnlh = nfnlh;
ssh->cb_count = cb_count;
ssh->subscriptions = subscriptions;
ssh->subsys_id = subsys_id;

if (recalc_rebind_subscriptions(nfnlh) < 0) {
free(ssh->cb);
ssh->cb = NULL;
return NULL;
}

return ssh;
}

我对nwtlink只有一个大致了解,现在不明白这段程序中nfnl_subsys_open()、recalc_rebind_subscriptions(nfnlh)这两个函数的用途和其中的一些语句。本人刚刚接触linux,希望有时间的大虾们给我一个仔细的分析过程。
邮箱:taijunmengnan@126.com
谢谢!
...全文
347 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

23,116

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧