Commit dc990b1d by Shuai Zhang Committed by Stéphane Graber

audit: added capacity and reserve() to nlmsg

There are now two (permitted) ways to add data to netlink message: 1. put_xxx() 2. call nlmsg_reserve() to get a pointer to newly reserved room within the original netlink message, then write or memcpy data to that area. Both of them guarantee adding requested length data do not overflow the pre-allocated message buffer by checking against its cap field first. And there may be no need to access nlmsg_len outside nl module, because both put_xxx() and nlmsg_reserve() have alread did that for us. Signed-off-by: 's avatarShuai Zhang <zs.broccoli@gmail.com> Acked-by: 's avatarStéphane Graber <stgraber@ubuntu.com>
parent e5e0bc55
...@@ -87,26 +87,12 @@ ...@@ -87,26 +87,12 @@
# define IFLA_MACVLAN_MODE 1 # define IFLA_MACVLAN_MODE 1
#endif #endif
struct link_req {
struct nlmsg nlmsg;
struct ifinfomsg ifinfomsg;
};
struct ip_req {
struct nlmsg nlmsg;
struct ifaddrmsg ifa;
};
struct rt_req {
struct nlmsg nlmsg;
struct rtmsg rt;
};
int lxc_netdev_move_by_index(int ifindex, pid_t pid, const char* ifname) int lxc_netdev_move_by_index(int ifindex, pid_t pid, const char* ifname)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL; struct nlmsg *nlmsg = NULL;
struct link_req *link_req; struct ifinfomsg *ifi;
int err; int err;
err = netlink_open(&nlh, NETLINK_ROUTE); err = netlink_open(&nlh, NETLINK_ROUTE);
...@@ -118,12 +104,12 @@ int lxc_netdev_move_by_index(int ifindex, pid_t pid, const char* ifname) ...@@ -118,12 +104,12 @@ int lxc_netdev_move_by_index(int ifindex, pid_t pid, const char* ifname)
if (!nlmsg) if (!nlmsg)
goto out; goto out;
link_req = (struct link_req *)nlmsg; nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
link_req->ifinfomsg.ifi_family = AF_UNSPEC; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
link_req->ifinfomsg.ifi_index = ifindex;
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; ifi->ifi_family = AF_UNSPEC;
nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK; ifi->ifi_index = ifindex;
if (nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid)) if (nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid))
goto out; goto out;
...@@ -158,7 +144,7 @@ int lxc_netdev_delete_by_index(int ifindex) ...@@ -158,7 +144,7 @@ int lxc_netdev_delete_by_index(int ifindex)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct link_req *link_req; struct ifinfomsg *ifi;
int err; int err;
err = netlink_open(&nlh, NETLINK_ROUTE); err = netlink_open(&nlh, NETLINK_ROUTE);
...@@ -170,16 +156,16 @@ int lxc_netdev_delete_by_index(int ifindex) ...@@ -170,16 +156,16 @@ int lxc_netdev_delete_by_index(int ifindex)
if (!nlmsg) if (!nlmsg)
goto out; goto out;
answer = nlmsg_alloc(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; goto out;
link_req = (struct link_req *)nlmsg; nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
link_req->ifinfomsg.ifi_family = AF_UNSPEC; nlmsg->nlmsghdr->nlmsg_type = RTM_DELLINK;
link_req->ifinfomsg.ifi_index = ifindex;
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
nlmsg->nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST; ifi->ifi_family = AF_UNSPEC;
nlmsg->nlmsghdr.nlmsg_type = RTM_DELLINK; ifi->ifi_index = ifindex;
err = netlink_transaction(&nlh, nlmsg, answer); err = netlink_transaction(&nlh, nlmsg, answer);
out: out:
...@@ -204,7 +190,7 @@ int lxc_netdev_rename_by_index(int ifindex, const char *newname) ...@@ -204,7 +190,7 @@ int lxc_netdev_rename_by_index(int ifindex, const char *newname)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct link_req *link_req; struct ifinfomsg *ifi;
int len, err; int len, err;
err = netlink_open(&nlh, NETLINK_ROUTE); err = netlink_open(&nlh, NETLINK_ROUTE);
...@@ -220,16 +206,16 @@ int lxc_netdev_rename_by_index(int ifindex, const char *newname) ...@@ -220,16 +206,16 @@ int lxc_netdev_rename_by_index(int ifindex, const char *newname)
if (!nlmsg) if (!nlmsg)
goto out; goto out;
answer = nlmsg_alloc(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; goto out;
link_req = (struct link_req *)nlmsg; nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
link_req->ifinfomsg.ifi_family = AF_UNSPEC; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
link_req->ifinfomsg.ifi_index = ifindex;
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
nlmsg->nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST; ifi->ifi_family = AF_UNSPEC;
nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK; ifi->ifi_index = ifindex;
if (nla_put_string(nlmsg, IFLA_IFNAME, newname)) if (nla_put_string(nlmsg, IFLA_IFNAME, newname))
goto out; goto out;
...@@ -261,7 +247,7 @@ int netdev_set_flag(const char *name, int flag) ...@@ -261,7 +247,7 @@ int netdev_set_flag(const char *name, int flag)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct link_req *link_req; struct ifinfomsg *ifi;
int index, len, err; int index, len, err;
err = netlink_open(&nlh, NETLINK_ROUTE); err = netlink_open(&nlh, NETLINK_ROUTE);
...@@ -278,7 +264,7 @@ int netdev_set_flag(const char *name, int flag) ...@@ -278,7 +264,7 @@ int netdev_set_flag(const char *name, int flag)
if (!nlmsg) if (!nlmsg)
goto out; goto out;
answer = nlmsg_alloc(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; goto out;
...@@ -287,14 +273,14 @@ int netdev_set_flag(const char *name, int flag) ...@@ -287,14 +273,14 @@ int netdev_set_flag(const char *name, int flag)
if (!index) if (!index)
goto out; goto out;
link_req = (struct link_req *)nlmsg; nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
link_req->ifinfomsg.ifi_family = AF_UNSPEC; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
link_req->ifinfomsg.ifi_index = index;
link_req->ifinfomsg.ifi_change |= IFF_UP; ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
link_req->ifinfomsg.ifi_flags |= flag; ifi->ifi_family = AF_UNSPEC;
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); ifi->ifi_index = index;
nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; ifi->ifi_change |= IFF_UP;
nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK; ifi->ifi_flags |= flag;
err = netlink_transaction(&nlh, nlmsg, answer); err = netlink_transaction(&nlh, nlmsg, answer);
out: out:
...@@ -308,9 +294,8 @@ int netdev_get_flag(const char* name, int *flag) ...@@ -308,9 +294,8 @@ int netdev_get_flag(const char* name, int *flag)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct link_req *link_req;
int index, len, err;
struct ifinfomsg *ifi; struct ifinfomsg *ifi;
int index, len, err;
if (!name) if (!name)
return -EINVAL; return -EINVAL;
...@@ -329,7 +314,7 @@ int netdev_get_flag(const char* name, int *flag) ...@@ -329,7 +314,7 @@ int netdev_get_flag(const char* name, int *flag)
if (!nlmsg) if (!nlmsg)
goto out; goto out;
answer = nlmsg_alloc(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; goto out;
...@@ -338,18 +323,18 @@ int netdev_get_flag(const char* name, int *flag) ...@@ -338,18 +323,18 @@ int netdev_get_flag(const char* name, int *flag)
if (!index) if (!index)
goto out; goto out;
link_req = (struct link_req *)nlmsg; nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST;
link_req->ifinfomsg.ifi_family = AF_UNSPEC; nlmsg->nlmsghdr->nlmsg_type = RTM_GETLINK;
link_req->ifinfomsg.ifi_index = index;
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST; ifi->ifi_family = AF_UNSPEC;
nlmsg->nlmsghdr.nlmsg_type = RTM_GETLINK; ifi->ifi_index = index;
err = netlink_transaction(&nlh, nlmsg, answer); err = netlink_transaction(&nlh, nlmsg, answer);
if (err) if (err)
goto out; goto out;
ifi = NLMSG_DATA(answer); ifi = NLMSG_DATA(answer->nlmsghdr);
*flag = ifi->ifi_flags; *flag = ifi->ifi_flags;
out: out:
...@@ -388,7 +373,7 @@ int netdev_get_mtu(int ifindex) ...@@ -388,7 +373,7 @@ int netdev_get_mtu(int ifindex)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct ip_req *ip_req; struct ifinfomsg *ifi;
struct nlmsghdr *msg; struct nlmsghdr *msg;
int err, res; int err, res;
int recv_len = 0, answer_len; int recv_len = 0, answer_len;
...@@ -403,21 +388,20 @@ int netdev_get_mtu(int ifindex) ...@@ -403,21 +388,20 @@ int netdev_get_mtu(int ifindex)
if (!nlmsg) if (!nlmsg)
goto out; goto out;
answer = nlmsg_alloc(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; goto out;
/* Save the answer buffer length, since it will be overwritten /* Save the answer buffer length, since it will be overwritten
* on the first receive (and we might need to receive more than * on the first receive (and we might need to receive more than
* once. */ * once. */
answer_len = answer->nlmsghdr.nlmsg_len; answer_len = answer->nlmsghdr->nlmsg_len;
ip_req = (struct ip_req *)nlmsg; nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
ip_req->nlmsg.nlmsghdr.nlmsg_len = nlmsg->nlmsghdr->nlmsg_type = RTM_GETLINK;
NLMSG_LENGTH(sizeof(struct ifaddrmsg));
ip_req->nlmsg.nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP; ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_GETLINK; ifi->ifi_family = AF_UNSPEC;
ip_req->ifa.ifa_family = AF_UNSPEC;
/* Send the request for addresses, which returns all addresses /* Send the request for addresses, which returns all addresses
* on all interfaces. */ * on all interfaces. */
...@@ -428,7 +412,7 @@ int netdev_get_mtu(int ifindex) ...@@ -428,7 +412,7 @@ int netdev_get_mtu(int ifindex)
do { do {
/* Restore the answer buffer length, it might have been /* Restore the answer buffer length, it might have been
* overwritten by a previous receive. */ * overwritten by a previous receive. */
answer->nlmsghdr.nlmsg_len = answer_len; answer->nlmsghdr->nlmsg_len = answer_len;
/* Get the (next) batch of reply messages */ /* Get the (next) batch of reply messages */
err = netlink_rcv(&nlh, answer); err = netlink_rcv(&nlh, answer);
...@@ -439,7 +423,7 @@ int netdev_get_mtu(int ifindex) ...@@ -439,7 +423,7 @@ int netdev_get_mtu(int ifindex)
err = 0; err = 0;
/* Satisfy the typing for the netlink macros */ /* Satisfy the typing for the netlink macros */
msg = &answer->nlmsghdr; msg = answer->nlmsghdr;
while (NLMSG_OK(msg, recv_len)) { while (NLMSG_OK(msg, recv_len)) {
...@@ -456,7 +440,7 @@ int netdev_get_mtu(int ifindex) ...@@ -456,7 +440,7 @@ int netdev_get_mtu(int ifindex)
break; break;
} }
struct ifinfomsg *ifi = NLMSG_DATA(msg); ifi = NLMSG_DATA(msg);
if (ifi->ifi_index == ifindex) { if (ifi->ifi_index == ifindex) {
struct rtattr *rta = IFLA_RTA(ifi); struct rtattr *rta = IFLA_RTA(ifi);
int attr_len = msg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)); int attr_len = msg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
...@@ -498,7 +482,7 @@ int lxc_netdev_set_mtu(const char *name, int mtu) ...@@ -498,7 +482,7 @@ int lxc_netdev_set_mtu(const char *name, int mtu)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct link_req *link_req; struct ifinfomsg *ifi;
int index, len, err; int index, len, err;
err = netlink_open(&nlh, NETLINK_ROUTE); err = netlink_open(&nlh, NETLINK_ROUTE);
...@@ -515,7 +499,7 @@ int lxc_netdev_set_mtu(const char *name, int mtu) ...@@ -515,7 +499,7 @@ int lxc_netdev_set_mtu(const char *name, int mtu)
if (!nlmsg) if (!nlmsg)
goto out; goto out;
answer = nlmsg_alloc(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; goto out;
...@@ -524,12 +508,12 @@ int lxc_netdev_set_mtu(const char *name, int mtu) ...@@ -524,12 +508,12 @@ int lxc_netdev_set_mtu(const char *name, int mtu)
if (!index) if (!index)
goto out; goto out;
link_req = (struct link_req *)nlmsg; nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
link_req->ifinfomsg.ifi_family = AF_UNSPEC; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
link_req->ifinfomsg.ifi_index = index;
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; ifi->ifi_family = AF_UNSPEC;
nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK; ifi->ifi_index = index;
if (nla_put_u32(nlmsg, IFLA_MTU, mtu)) if (nla_put_u32(nlmsg, IFLA_MTU, mtu))
goto out; goto out;
...@@ -556,7 +540,7 @@ int lxc_veth_create(const char *name1, const char *name2) ...@@ -556,7 +540,7 @@ int lxc_veth_create(const char *name1, const char *name2)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct link_req *link_req; struct ifinfomsg *ifi;
struct rtattr *nest1, *nest2, *nest3; struct rtattr *nest1, *nest2, *nest3;
int len, err; int len, err;
...@@ -578,16 +562,16 @@ int lxc_veth_create(const char *name1, const char *name2) ...@@ -578,16 +562,16 @@ int lxc_veth_create(const char *name1, const char *name2)
if (!nlmsg) if (!nlmsg)
goto out; goto out;
answer = nlmsg_alloc(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; goto out;
link_req = (struct link_req *)nlmsg; nlmsg->nlmsghdr->nlmsg_flags =
link_req->ifinfomsg.ifi_family = AF_UNSPEC;
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
nlmsg->nlmsghdr.nlmsg_flags =
NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK; NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
ifi->ifi_family = AF_UNSPEC;
err = -EINVAL; err = -EINVAL;
nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO); nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO);
...@@ -605,7 +589,9 @@ int lxc_veth_create(const char *name1, const char *name2) ...@@ -605,7 +589,9 @@ int lxc_veth_create(const char *name1, const char *name2)
if (!nest3) if (!nest3)
goto out; goto out;
nlmsg->nlmsghdr.nlmsg_len += sizeof(struct ifinfomsg); ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
if (!ifi)
goto out;
if (nla_put_string(nlmsg, IFLA_IFNAME, name2)) if (nla_put_string(nlmsg, IFLA_IFNAME, name2))
goto out; goto out;
...@@ -632,7 +618,7 @@ int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid) ...@@ -632,7 +618,7 @@ int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct link_req *link_req; struct ifinfomsg *ifi;
struct rtattr *nest, *nest2; struct rtattr *nest, *nest2;
int lindex, len, err; int lindex, len, err;
...@@ -654,7 +640,7 @@ int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid) ...@@ -654,7 +640,7 @@ int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid)
if (!nlmsg) if (!nlmsg)
goto err3; goto err3;
answer = nlmsg_alloc(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto err2; goto err2;
...@@ -663,12 +649,12 @@ int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid) ...@@ -663,12 +649,12 @@ int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid)
if (!lindex) if (!lindex)
goto err1; goto err1;
link_req = (struct link_req *)nlmsg; nlmsg->nlmsghdr->nlmsg_flags =
link_req->ifinfomsg.ifi_family = AF_UNSPEC;
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
nlmsg->nlmsghdr.nlmsg_flags =
NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK; NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
ifi->ifi_family = AF_UNSPEC;
nest = nla_begin_nested(nlmsg, IFLA_LINKINFO); nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
if (!nest) if (!nest)
...@@ -708,7 +694,7 @@ int lxc_macvlan_create(const char *master, const char *name, int mode) ...@@ -708,7 +694,7 @@ int lxc_macvlan_create(const char *master, const char *name, int mode)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct link_req *link_req; struct ifinfomsg *ifi;
struct rtattr *nest, *nest2; struct rtattr *nest, *nest2;
int index, len, err; int index, len, err;
...@@ -730,7 +716,7 @@ int lxc_macvlan_create(const char *master, const char *name, int mode) ...@@ -730,7 +716,7 @@ int lxc_macvlan_create(const char *master, const char *name, int mode)
if (!nlmsg) if (!nlmsg)
goto out; goto out;
answer = nlmsg_alloc(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; goto out;
...@@ -739,12 +725,12 @@ int lxc_macvlan_create(const char *master, const char *name, int mode) ...@@ -739,12 +725,12 @@ int lxc_macvlan_create(const char *master, const char *name, int mode)
if (!index) if (!index)
goto out; goto out;
link_req = (struct link_req *)nlmsg; nlmsg->nlmsghdr->nlmsg_flags =
link_req->ifinfomsg.ifi_family = AF_UNSPEC;
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
nlmsg->nlmsghdr.nlmsg_flags =
NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK; NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
ifi->ifi_family = AF_UNSPEC;
nest = nla_begin_nested(nlmsg, IFLA_LINKINFO); nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
if (!nest) if (!nest)
...@@ -900,7 +886,7 @@ static int ip_addr_add(int family, int ifindex, ...@@ -900,7 +886,7 @@ static int ip_addr_add(int family, int ifindex,
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct ip_req *ip_req; struct ifaddrmsg *ifa;
int addrlen; int addrlen;
int err; int err;
...@@ -916,20 +902,19 @@ static int ip_addr_add(int family, int ifindex, ...@@ -916,20 +902,19 @@ static int ip_addr_add(int family, int ifindex,
if (!nlmsg) if (!nlmsg)
goto out; goto out;
answer = nlmsg_alloc(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; goto out;
ip_req = (struct ip_req *)nlmsg; nlmsg->nlmsghdr->nlmsg_flags =
ip_req->nlmsg.nlmsghdr.nlmsg_len =
NLMSG_LENGTH(sizeof(struct ifaddrmsg));
ip_req->nlmsg.nlmsghdr.nlmsg_flags =
NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL; NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWADDR; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWADDR;
ip_req->ifa.ifa_prefixlen = prefix;
ip_req->ifa.ifa_index = ifindex; ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg));
ip_req->ifa.ifa_family = family; ifa->ifa_prefixlen = prefix;
ip_req->ifa.ifa_scope = 0; ifa->ifa_index = ifindex;
ifa->ifa_family = family;
ifa->ifa_scope = 0;
err = -EINVAL; err = -EINVAL;
if (nla_put_buffer(nlmsg, IFA_LOCAL, addr, addrlen)) if (nla_put_buffer(nlmsg, IFA_LOCAL, addr, addrlen))
...@@ -974,12 +959,13 @@ int lxc_ipv4_addr_add(int ifindex, struct in_addr *addr, ...@@ -974,12 +959,13 @@ int lxc_ipv4_addr_add(int ifindex, struct in_addr *addr,
* address and stores that pointer in *res (so res should be an * address and stores that pointer in *res (so res should be an
* in_addr** or in6_addr**). * in_addr** or in6_addr**).
*/ */
static int ifa_get_local_ip(int family, struct ip_req *ip_info, void** res) { static int ifa_get_local_ip(int family, struct nlmsghdr *msg, void** res) {
struct rtattr *rta = IFA_RTA(&ip_info->ifa); struct ifaddrmsg *ifa = NLMSG_DATA(msg);
int attr_len = IFA_PAYLOAD(&ip_info->nlmsg.nlmsghdr); struct rtattr *rta = IFA_RTA(ifa);
int attr_len = NLMSG_PAYLOAD(msg, sizeof(struct ifaddrmsg));
int addrlen; int addrlen;
if (ip_info->ifa.ifa_family != family) if (ifa->ifa_family != family)
return 0; return 0;
addrlen = family == AF_INET ? sizeof(struct in_addr) : addrlen = family == AF_INET ? sizeof(struct in_addr) :
...@@ -1018,7 +1004,7 @@ static int ip_addr_get(int family, int ifindex, void **res) ...@@ -1018,7 +1004,7 @@ static int ip_addr_get(int family, int ifindex, void **res)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct ip_req *ip_req, *ip_info; struct ifaddrmsg *ifa;
struct nlmsghdr *msg; struct nlmsghdr *msg;
int err; int err;
int recv_len = 0, answer_len; int recv_len = 0, answer_len;
...@@ -1033,21 +1019,20 @@ static int ip_addr_get(int family, int ifindex, void **res) ...@@ -1033,21 +1019,20 @@ static int ip_addr_get(int family, int ifindex, void **res)
if (!nlmsg) if (!nlmsg)
goto out; goto out;
answer = nlmsg_alloc(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; goto out;
/* Save the answer buffer length, since it will be overwritten /* Save the answer buffer length, since it will be overwritten
* on the first receive (and we might need to receive more than * on the first receive (and we might need to receive more than
* once. */ * once. */
answer_len = answer->nlmsghdr.nlmsg_len; answer_len = answer->nlmsghdr->nlmsg_len;
nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_ROOT;
nlmsg->nlmsghdr->nlmsg_type = RTM_GETADDR;
ip_req = (struct ip_req *)nlmsg; ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg));
ip_req->nlmsg.nlmsghdr.nlmsg_len = ifa->ifa_family = family;
NLMSG_LENGTH(sizeof(struct ifaddrmsg));
ip_req->nlmsg.nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ROOT;
ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_GETADDR;
ip_req->ifa.ifa_family = family;
/* Send the request for addresses, which returns all addresses /* Send the request for addresses, which returns all addresses
* on all interfaces. */ * on all interfaces. */
...@@ -1058,7 +1043,7 @@ static int ip_addr_get(int family, int ifindex, void **res) ...@@ -1058,7 +1043,7 @@ static int ip_addr_get(int family, int ifindex, void **res)
do { do {
/* Restore the answer buffer length, it might have been /* Restore the answer buffer length, it might have been
* overwritten by a previous receive. */ * overwritten by a previous receive. */
answer->nlmsghdr.nlmsg_len = answer_len; answer->nlmsghdr->nlmsg_len = answer_len;
/* Get the (next) batch of reply messages */ /* Get the (next) batch of reply messages */
err = netlink_rcv(&nlh, answer); err = netlink_rcv(&nlh, answer);
...@@ -1069,7 +1054,7 @@ static int ip_addr_get(int family, int ifindex, void **res) ...@@ -1069,7 +1054,7 @@ static int ip_addr_get(int family, int ifindex, void **res)
err = 0; err = 0;
/* Satisfy the typing for the netlink macros */ /* Satisfy the typing for the netlink macros */
msg = &answer->nlmsghdr; msg = answer->nlmsghdr;
while (NLMSG_OK(msg, recv_len)) { while (NLMSG_OK(msg, recv_len)) {
/* Stop reading if we see an error message */ /* Stop reading if we see an error message */
...@@ -1090,9 +1075,9 @@ static int ip_addr_get(int family, int ifindex, void **res) ...@@ -1090,9 +1075,9 @@ static int ip_addr_get(int family, int ifindex, void **res)
goto out; goto out;
} }
ip_info = (struct ip_req *)msg; ifa = (struct ifaddrmsg *)NLMSG_DATA(msg);
if (ip_info->ifa.ifa_index == ifindex) { if (ifa->ifa_index == ifindex) {
if (ifa_get_local_ip(family, ip_info, res) < 0) { if (ifa_get_local_ip(family, msg, res) < 0) {
err = -1; err = -1;
goto out; goto out;
} }
...@@ -1136,7 +1121,7 @@ static int ip_gateway_add(int family, int ifindex, void *gw) ...@@ -1136,7 +1121,7 @@ static int ip_gateway_add(int family, int ifindex, void *gw)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct rt_req *rt_req; struct rtmsg *rt;
int addrlen; int addrlen;
int err; int err;
...@@ -1152,23 +1137,22 @@ static int ip_gateway_add(int family, int ifindex, void *gw) ...@@ -1152,23 +1137,22 @@ static int ip_gateway_add(int family, int ifindex, void *gw)
if (!nlmsg) if (!nlmsg)
goto out; goto out;
answer = nlmsg_alloc(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; goto out;
rt_req = (struct rt_req *)nlmsg; nlmsg->nlmsghdr->nlmsg_flags =
rt_req->nlmsg.nlmsghdr.nlmsg_len =
NLMSG_LENGTH(sizeof(struct rtmsg));
rt_req->nlmsg.nlmsghdr.nlmsg_flags =
NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL; NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
rt_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWROUTE; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWROUTE;
rt_req->rt.rtm_family = family;
rt_req->rt.rtm_table = RT_TABLE_MAIN; rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg));
rt_req->rt.rtm_scope = RT_SCOPE_UNIVERSE; rt->rtm_family = family;
rt_req->rt.rtm_protocol = RTPROT_BOOT; rt->rtm_table = RT_TABLE_MAIN;
rt_req->rt.rtm_type = RTN_UNICAST; rt->rtm_scope = RT_SCOPE_UNIVERSE;
rt->rtm_protocol = RTPROT_BOOT;
rt->rtm_type = RTN_UNICAST;
/* "default" destination */ /* "default" destination */
rt_req->rt.rtm_dst_len = 0; rt->rtm_dst_len = 0;
err = -EINVAL; err = -EINVAL;
if (nla_put_buffer(nlmsg, RTA_GATEWAY, gw, addrlen)) if (nla_put_buffer(nlmsg, RTA_GATEWAY, gw, addrlen))
...@@ -1201,7 +1185,7 @@ static int ip_route_dest_add(int family, int ifindex, void *dest) ...@@ -1201,7 +1185,7 @@ static int ip_route_dest_add(int family, int ifindex, void *dest)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct rt_req *rt_req; struct rtmsg *rt;
int addrlen; int addrlen;
int err; int err;
...@@ -1217,22 +1201,21 @@ static int ip_route_dest_add(int family, int ifindex, void *dest) ...@@ -1217,22 +1201,21 @@ static int ip_route_dest_add(int family, int ifindex, void *dest)
if (!nlmsg) if (!nlmsg)
goto out; goto out;
answer = nlmsg_alloc(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; goto out;
rt_req = (struct rt_req *)nlmsg; nlmsg->nlmsghdr->nlmsg_flags =
rt_req->nlmsg.nlmsghdr.nlmsg_len =
NLMSG_LENGTH(sizeof(struct rtmsg));
rt_req->nlmsg.nlmsghdr.nlmsg_flags =
NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL; NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
rt_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWROUTE; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWROUTE;
rt_req->rt.rtm_family = family;
rt_req->rt.rtm_table = RT_TABLE_MAIN; rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg));
rt_req->rt.rtm_scope = RT_SCOPE_LINK; rt->rtm_family = family;
rt_req->rt.rtm_protocol = RTPROT_BOOT; rt->rtm_table = RT_TABLE_MAIN;
rt_req->rt.rtm_type = RTN_UNICAST; rt->rtm_scope = RT_SCOPE_LINK;
rt_req->rt.rtm_dst_len = addrlen*8; rt->rtm_protocol = RTPROT_BOOT;
rt->rtm_type = RTN_UNICAST;
rt->rtm_dst_len = addrlen*8;
err = -EINVAL; err = -EINVAL;
if (nla_put_buffer(nlmsg, RTA_DST, dest, addrlen)) if (nla_put_buffer(nlmsg, RTA_DST, dest, addrlen))
......
...@@ -37,12 +37,12 @@ ...@@ -37,12 +37,12 @@
extern size_t nlmsg_len(const struct nlmsg *nlmsg) extern size_t nlmsg_len(const struct nlmsg *nlmsg)
{ {
return nlmsg->nlmsghdr.nlmsg_len - NLMSG_HDRLEN; return nlmsg->nlmsghdr->nlmsg_len - NLMSG_HDRLEN;
} }
extern void *nlmsg_data(struct nlmsg *nlmsg) extern void *nlmsg_data(struct nlmsg *nlmsg)
{ {
char *data = ((char *)nlmsg) + NLMSG_ALIGN(sizeof(struct nlmsghdr)); char *data = ((char *)nlmsg) + NLMSG_HDRLEN;
if (!nlmsg_len(nlmsg)) if (!nlmsg_len(nlmsg))
return NULL; return NULL;
return data; return data;
...@@ -53,13 +53,16 @@ static int nla_put(struct nlmsg *nlmsg, int attr, ...@@ -53,13 +53,16 @@ static int nla_put(struct nlmsg *nlmsg, int attr,
{ {
struct rtattr *rta; struct rtattr *rta;
size_t rtalen = RTA_LENGTH(len); size_t rtalen = RTA_LENGTH(len);
size_t tlen = NLMSG_ALIGN(nlmsg->nlmsghdr->nlmsg_len) + RTA_ALIGN(rtalen);
rta = NLMSG_TAIL(&nlmsg->nlmsghdr); if (tlen > nlmsg->cap)
rta->rta_type = attr; return -ENOMEM;
rta->rta_len = rtalen;
memcpy(RTA_DATA(rta), data, len); rta = NLMSG_TAIL(nlmsg->nlmsghdr);
nlmsg->nlmsghdr.nlmsg_len = rta->rta_type = attr;
NLMSG_ALIGN(nlmsg->nlmsghdr.nlmsg_len) + RTA_ALIGN(rtalen); rta->rta_len = rtalen;
memcpy(RTA_DATA(rta), data, len);
nlmsg->nlmsghdr->nlmsg_len = tlen;
return 0; return 0;
} }
...@@ -91,7 +94,7 @@ extern int nla_put_attr(struct nlmsg *nlmsg, int attr) ...@@ -91,7 +94,7 @@ extern int nla_put_attr(struct nlmsg *nlmsg, int attr)
struct rtattr *nla_begin_nested(struct nlmsg *nlmsg, int attr) struct rtattr *nla_begin_nested(struct nlmsg *nlmsg, int attr)
{ {
struct rtattr *rtattr = NLMSG_TAIL(&nlmsg->nlmsghdr); struct rtattr *rtattr = NLMSG_TAIL(nlmsg->nlmsghdr);
if (nla_put_attr(nlmsg, attr)) if (nla_put_attr(nlmsg, attr))
return NULL; return NULL;
...@@ -101,7 +104,7 @@ struct rtattr *nla_begin_nested(struct nlmsg *nlmsg, int attr) ...@@ -101,7 +104,7 @@ struct rtattr *nla_begin_nested(struct nlmsg *nlmsg, int attr)
void nla_end_nested(struct nlmsg *nlmsg, struct rtattr *attr) void nla_end_nested(struct nlmsg *nlmsg, struct rtattr *attr)
{ {
attr->rta_len = (void *)NLMSG_TAIL(&nlmsg->nlmsghdr) - (void *)attr; attr->rta_len = (void *)NLMSG_TAIL(nlmsg->nlmsghdr) - (void *)attr;
} }
extern struct nlmsg *nlmsg_alloc(size_t size) extern struct nlmsg *nlmsg_alloc(size_t size)
...@@ -109,18 +112,61 @@ extern struct nlmsg *nlmsg_alloc(size_t size) ...@@ -109,18 +112,61 @@ extern struct nlmsg *nlmsg_alloc(size_t size)
struct nlmsg *nlmsg; struct nlmsg *nlmsg;
size_t len = NLMSG_HDRLEN + NLMSG_ALIGN(size); size_t len = NLMSG_HDRLEN + NLMSG_ALIGN(size);
nlmsg = (struct nlmsg *)malloc(len); nlmsg = (struct nlmsg *)malloc(sizeof(struct nlmsg));
if (!nlmsg) if (!nlmsg)
return NULL; return NULL;
memset(nlmsg, 0, len); nlmsg->nlmsghdr = (struct nlmsghdr *)malloc(len);
nlmsg->nlmsghdr.nlmsg_len = NLMSG_HDRLEN; if (!nlmsg->nlmsghdr)
goto errout;
memset(nlmsg->nlmsghdr, 0, len);
nlmsg->cap = len;
nlmsg->nlmsghdr->nlmsg_len = NLMSG_HDRLEN;
return nlmsg; return nlmsg;
errout:
free(nlmsg);
return NULL;
}
extern void *nlmsg_reserve(struct nlmsg *nlmsg, size_t len)
{
void *buf;
size_t nlmsg_len = nlmsg->nlmsghdr->nlmsg_len;
size_t tlen = NLMSG_ALIGN(len);
if (nlmsg_len + tlen > nlmsg->cap)
return NULL;
buf = ((char *)(nlmsg->nlmsghdr)) + nlmsg_len;
nlmsg->nlmsghdr->nlmsg_len += tlen;
if (tlen > len)
memset(buf + len, 0, tlen - len);
return buf;
}
extern struct nlmsg *nlmsg_alloc_reserve(size_t size)
{
struct nlmsg *nlmsg;
nlmsg = nlmsg_alloc(size);
if (!nlmsg)
return NULL;
// just set message length to cap directly
nlmsg->nlmsghdr->nlmsg_len = nlmsg->cap;
return nlmsg;
} }
extern void nlmsg_free(struct nlmsg *nlmsg) extern void nlmsg_free(struct nlmsg *nlmsg)
{ {
if (!nlmsg)
return;
free(nlmsg->nlmsghdr);
free(nlmsg); free(nlmsg);
} }
...@@ -129,8 +175,8 @@ extern int netlink_rcv(struct nl_handler *handler, struct nlmsg *answer) ...@@ -129,8 +175,8 @@ extern int netlink_rcv(struct nl_handler *handler, struct nlmsg *answer)
int ret; int ret;
struct sockaddr_nl nladdr; struct sockaddr_nl nladdr;
struct iovec iov = { struct iovec iov = {
.iov_base = answer, .iov_base = answer->nlmsghdr,
.iov_len = answer->nlmsghdr.nlmsg_len, .iov_len = answer->nlmsghdr->nlmsg_len,
}; };
struct msghdr msg = { struct msghdr msg = {
...@@ -157,7 +203,7 @@ again: ...@@ -157,7 +203,7 @@ again:
return 0; return 0;
if (msg.msg_flags & MSG_TRUNC && if (msg.msg_flags & MSG_TRUNC &&
ret == answer->nlmsghdr.nlmsg_len) ret == answer->nlmsghdr->nlmsg_len)
return -EMSGSIZE; return -EMSGSIZE;
return ret; return ret;
...@@ -167,8 +213,8 @@ extern int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg) ...@@ -167,8 +213,8 @@ extern int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg)
{ {
struct sockaddr_nl nladdr; struct sockaddr_nl nladdr;
struct iovec iov = { struct iovec iov = {
.iov_base = (void*)nlmsg, .iov_base = nlmsg->nlmsghdr,
.iov_len = nlmsg->nlmsghdr.nlmsg_len, .iov_len = nlmsg->nlmsghdr->nlmsg_len,
}; };
struct msghdr msg = { struct msghdr msg = {
.msg_name = &nladdr, .msg_name = &nladdr,
...@@ -206,8 +252,8 @@ extern int netlink_transaction(struct nl_handler *handler, ...@@ -206,8 +252,8 @@ extern int netlink_transaction(struct nl_handler *handler,
if (ret < 0) if (ret < 0)
return ret; return ret;
if (answer->nlmsghdr.nlmsg_type == NLMSG_ERROR) { if (answer->nlmsghdr->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(answer); struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(answer->nlmsghdr);
return err->error; return err->error;
} }
......
...@@ -53,14 +53,16 @@ struct nl_handler { ...@@ -53,14 +53,16 @@ struct nl_handler {
}; };
/* /*
* struct nlmsg : the netlink message structure, it consists just * struct nlmsg : the netlink message structure. This message is to be used to
* on a definition for a nlmsghdr. This message is to be used to
* be allocated with netlink_alloc. * be allocated with netlink_alloc.
* @nlmsghdr : a pointer to a netlink message header, this field *
* _must_ be always the first field of this structure * @nlmsghdr: a pointer to a netlink message header
* @cap: capacity of the netlink message, this is the initially allocated size
* and later operations (e.g. reserve and put) can not exceed this limit.
*/ */
struct nlmsg { struct nlmsg {
struct nlmsghdr nlmsghdr; struct nlmsghdr *nlmsghdr;
ssize_t cap;
}; };
/* /*
...@@ -210,16 +212,35 @@ void nla_end_nested(struct nlmsg *nlmsg, struct rtattr *attr); ...@@ -210,16 +212,35 @@ void nla_end_nested(struct nlmsg *nlmsg, struct rtattr *attr);
* is sizeof(header) + sizeof(padding) + payloadsize + sizeof(padding), * is sizeof(header) + sizeof(padding) + payloadsize + sizeof(padding),
* in other words, the function will allocate more than specified. When * in other words, the function will allocate more than specified. When
* the buffer is allocated, the content is zeroed. * the buffer is allocated, the content is zeroed.
* The function will also fill the field nlmsg_len with computed size. * The function will also fill the field nlmsg_len with NLMSG_HDRLEN.
* If the allocation must be for the specified size, just use malloc. * If the allocation must be for the specified size, just use malloc.
* *
* @size: the size of the payload to be allocated * @size: the capacity of the payload to be allocated
* *
* Returns a pointer to the newly allocated netlink message, NULL otherwise * Returns a pointer to the newly allocated netlink message, NULL otherwise
*/ */
struct nlmsg *nlmsg_alloc(size_t size); struct nlmsg *nlmsg_alloc(size_t size);
/* /*
* nlmsg_alloc_reserve: like nlmsg_alloc(), but reserve the whole payload
* after allocated, that is, the field nlmsg_len be set to the capacity
* of nlmsg. Often used to allocate a message for the reply.
*
* @size: the capacity of the payload to be allocated.
*/
struct nlmsg *nlmsg_alloc_reserve(size_t size);
/*
* Reserve room for additional data at the tail of a netlink message
*
* @nlmsg: the netlink message
* @len: length of additional data to reserve room for
*
* Returns a pointer to newly reserved room or NULL
*/
void *nlmsg_reserve(struct nlmsg *nlmsg, size_t len);
/*
* nlmsg_free : free a previously allocate message * nlmsg_free : free a previously allocate message
* *
* @nlmsg: the netlink message to be freed * @nlmsg: the netlink message to be freed
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment