along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <linux/rtnetlink.h>
#include <netinet/in.h>
#include <netinet/ether.h>
#include <stdbool.h>
#include <unistd.h>
+#include <linux/veth.h>
#include "util.h"
#include "refcnt.h"
+#include "missing.h"
#include "sd-rtnl.h"
#include "rtnl-util.h"
#include "rtnl-internal.h"
-#define GET_CONTAINER(m, i) (i < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
+#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
#define NEXT_RTA(m) ((struct rtattr*)((uint8_t*)(m)->hdr + (m)->next_rta_offset))
#define UPDATE_RTA(m, new) (m)->next_rta_offset = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
#define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
-int message_new(sd_rtnl_message **ret, size_t initial_size) {
+int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, size_t initial_size) {
sd_rtnl_message *m;
assert_return(ret, -EINVAL);
m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
m->sealed = false;
+ if (rtnl)
+ m->rtnl = sd_rtnl_ref(rtnl);
+
*ret = m;
return 0;
return 0;
}
-int sd_rtnl_message_new_route(uint16_t nlmsg_type, unsigned char rtm_family,
- sd_rtnl_message **ret) {
+int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
+ uint16_t nlmsg_type, unsigned char rtm_family) {
struct rtmsg *rtm;
int r;
assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
assert_return(ret, -EINVAL);
- r = message_new(ret, NLMSG_SPACE(sizeof(struct rtmsg)));
+ r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct rtmsg)));
if (r < 0)
return r;
assert_return(m, -EINVAL);
assert_return(m->hdr, -EINVAL);
assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
+ assert_return(change, -EINVAL);
ifi = NLMSG_DATA(m->hdr);
ifi->ifi_flags = flags;
- if (change)
- ifi->ifi_change = change;
- else
- ifi->ifi_change = 0xffffffff;
+ ifi->ifi_change = change;
return 0;
}
return 0;
}
-int sd_rtnl_message_new_link(uint16_t nlmsg_type, int index, sd_rtnl_message **ret) {
+int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
+ uint16_t nlmsg_type, int index) {
struct ifinfomsg *ifi;
int r;
assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
- assert_return(nlmsg_type == RTM_NEWLINK || index > 0, -EINVAL);
+ assert_return(nlmsg_type == RTM_NEWLINK ||
+ nlmsg_type == RTM_SETLINK || index > 0, -EINVAL);
assert_return(ret, -EINVAL);
- r = message_new(ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
+ r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
if (r < 0)
return r;
return 0;
}
-int sd_rtnl_message_new_addr(uint16_t nlmsg_type, int index, unsigned char family,
- sd_rtnl_message **ret) {
+int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
+ uint16_t nlmsg_type, int index,
+ unsigned char family) {
struct ifaddrmsg *ifa;
int r;
assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
assert_return(ret, -EINVAL);
- r = message_new(ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
+ r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
if (r < 0)
return r;
(*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
(*ret)->hdr->nlmsg_type = nlmsg_type;
+ if (nlmsg_type == RTM_GETADDR && family == AF_INET)
+ (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
ifa = NLMSG_DATA((*ret)->hdr);
sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
if (m && REFCNT_DEC(m->n_ref) <= 0) {
+ sd_rtnl_unref(m->rtnl);
free(m->hdr);
free(m);
}
break;
else
return -ENOTSUP;
- break;
+
default:
return -ENOTSUP;
}
sd_rtnl_message_get_type(m, &rtm_type);
if (rtnl_message_type_is_link(rtm_type)) {
+
if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
(type == IFLA_INFO_DATA && m->n_containers == 1 &&
GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
return add_rtattr(m, type, NULL, 0);
- else
- return -ENOTSUP;
- } else
- return -ENOTSUP;
+ else if (type == VETH_INFO_PEER && m->n_containers == 2 &&
+ GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
+ GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO)
+ return add_rtattr(m, type, NULL, sizeof(struct ifinfomsg));
+ }
- return 0;
+ return -ENOTSUP;
}
int sd_rtnl_message_close_container(sd_rtnl_message *m) {
if (r < 0)
return r;
- r = message_new(&m, need);
+ r = message_new(nl, &m, need);
if (r < 0)
return r;
if (k > 0)
switch (m->hdr->nlmsg_type) {
- struct ifinfomsg *ifi;
- struct ifaddrmsg *ifa;
- struct rtmsg *rtm;
-
/* check that the size matches the message type */
case NLMSG_ERROR:
if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
k = -EIO;
else {
+ struct ifinfomsg *ifi;
+
ifi = NLMSG_DATA(m->hdr);
UPDATE_RTA(m, IFLA_RTA(ifi));
}
if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
k = -EIO;
else {
+ struct ifaddrmsg *ifa;
+
ifa = NLMSG_DATA(m->hdr);
UPDATE_RTA(m, IFA_RTA(ifa));
}
if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
k = -EIO;
else {
+ struct rtmsg *rtm;
+
rtm = NLMSG_DATA(m->hdr);
UPDATE_RTA(m, RTM_RTA(rtm));
}