From 77e7c13b2ef95724c39395d92725b1a892ff84de Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 12 Nov 2010 07:14:01 -0500 Subject: [PATCH] macvtap: convert nl msg construction to use libnl In a first step I am converting the netlink message construction in macvtap code to use libnl. It's pretty much a 1:1 conversion except that now the message needs to be allocated and deallocated. --- src/util/macvtap.c | 321 +++++++++++++++++++-------------------------- 1 file changed, 137 insertions(+), 184 deletions(-) diff --git a/src/util/macvtap.c b/src/util/macvtap.c index 88c38c86f3..da9678f8e8 100644 --- a/src/util/macvtap.c +++ b/src/util/macvtap.c @@ -191,51 +191,6 @@ err_exit: } -static struct rtattr * -rtattrCreate(char *buffer, int bufsize, int type, - const void *data, int datalen) -{ - struct rtattr *r = (struct rtattr *)buffer; - r->rta_type = type; - r->rta_len = RTA_LENGTH(datalen); - if (r->rta_len > bufsize) - return NULL; - memcpy(RTA_DATA(r), data, datalen); - return r; -} - - -static void -nlInit(struct nlmsghdr *nlm, int flags, int type) -{ - nlm->nlmsg_len = NLMSG_LENGTH(0); - nlm->nlmsg_flags = flags; - nlm->nlmsg_type = type; -} - - -static void -nlAlign(struct nlmsghdr *nlm) -{ - nlm->nlmsg_len = NLMSG_ALIGN(nlm->nlmsg_len); -} - - -static void * -nlAppend(struct nlmsghdr *nlm, int totlen, const void *data, int datalen) -{ - char *pos; - nlAlign(nlm); - if (nlm->nlmsg_len + NLMSG_ALIGN(datalen) > totlen) - return NULL; - pos = (char *)nlm + nlm->nlmsg_len; - memcpy(pos, data, datalen); - nlm->nlmsg_len += datalen; - nlAlign(nlm); - return pos; -} - - # if WITH_MACVTAP static int @@ -247,74 +202,63 @@ link_add(const char *type, int *retry) { int rc = 0; - char nlmsgbuf[NLMSGBUF_SIZE]; - struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp; + struct nlmsghdr *resp; struct nlmsgerr *err; - char rtattbuf[RATTBUF_SIZE]; - struct rtattr *rta, *rta1, *li; struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; int ifindex; char *recvbuf = NULL; unsigned int recvbuflen; + struct nl_msg *nl_msg; + struct nlattr *linkinfo, *info_data; if (ifaceGetIndex(true, srcdev, &ifindex) != 0) return -1; *retry = 0; - memset(&nlmsgbuf, 0, sizeof(nlmsgbuf)); - - nlInit(nlm, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL, RTM_NEWLINK); + nl_msg = nlmsg_alloc_simple(RTM_NEWLINK, + NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); + if (!nl_msg) { + virReportOOMError(); + return -1; + } - if (!nlAppend(nlm, sizeof(nlmsgbuf), &ifinfo, sizeof(ifinfo))) + if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0) goto buffer_too_small; - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_LINK, - &ifindex, sizeof(ifindex)); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + if (nla_put_u32(nl_msg, IFLA_LINK, ifindex) < 0) goto buffer_too_small; - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_ADDRESS, - macaddress, macaddrsize); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + if (nla_put(nl_msg, IFLA_ADDRESS, macaddrsize, macaddress) < 0) goto buffer_too_small; - if (ifname) { - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME, - ifname, strlen(ifname) + 1); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) - goto buffer_too_small; - } + if (ifname && + nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) + goto buffer_too_small; - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_LINKINFO, NULL, 0); - if (!rta || - !(li = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))) + if (!(linkinfo = nla_nest_start(nl_msg, IFLA_LINKINFO))) goto buffer_too_small; - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_INFO_KIND, - type, strlen(type)); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + if (nla_put(nl_msg, IFLA_INFO_KIND, strlen(type), type) < 0) goto buffer_too_small; if (macvlan_mode > 0) { - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_INFO_DATA, - NULL, 0); - if (!rta || - !(rta1 = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))) + if (!(info_data = nla_nest_start(nl_msg, IFLA_INFO_DATA))) goto buffer_too_small; - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_MACVLAN_MODE, - &macvlan_mode, sizeof(macvlan_mode)); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + if (nla_put(nl_msg, IFLA_MACVLAN_MODE, sizeof(macvlan_mode), + &macvlan_mode) < 0) goto buffer_too_small; - rta1->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)rta1; + nla_nest_end(nl_msg, info_data); } - li->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)li; + nla_nest_end(nl_msg, linkinfo); - if (nlComm(nlm, &recvbuf, &recvbuflen, 0) < 0) - return -1; + if (nlComm(nlmsg_hdr(nl_msg), &recvbuf, &recvbuflen, 0) < 0) { + rc = -1; + goto err_exit; + } if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL) goto malformed_resp; @@ -352,50 +296,58 @@ link_add(const char *type, goto malformed_resp; } +err_exit: + nlmsg_free(nl_msg); + VIR_FREE(recvbuf); return rc; malformed_resp: + nlmsg_free(nl_msg); + macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed netlink response message")); VIR_FREE(recvbuf); return -1; buffer_too_small: + nlmsg_free(nl_msg); + macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", - _("internal buffer is too small")); + _("allocated netlink buffer is too small")); return -1; } static int -link_del(const char *name) +link_del(const char *ifname) { int rc = 0; - char nlmsgbuf[NLMSGBUF_SIZE]; - struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp; + struct nlmsghdr *resp; struct nlmsgerr *err; - char rtattbuf[RATTBUF_SIZE]; - struct rtattr *rta; struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; char *recvbuf = NULL; unsigned int recvbuflen; + struct nl_msg *nl_msg; - memset(&nlmsgbuf, 0, sizeof(nlmsgbuf)); - - nlInit(nlm, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL, RTM_DELLINK); + nl_msg = nlmsg_alloc_simple(RTM_DELLINK, + NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); + if (!nl_msg) { + virReportOOMError(); + return -1; + } - if (!nlAppend(nlm, sizeof(nlmsgbuf), &ifinfo, sizeof(ifinfo))) + if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0) goto buffer_too_small; - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME, - name, strlen(name)+1); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) goto buffer_too_small; - if (nlComm(nlm, &recvbuf, &recvbuflen, 0) < 0) - return -1; + if (nlComm(nlmsg_hdr(nl_msg), &recvbuf, &recvbuflen, 0) < 0) { + rc = -1; + goto err_exit; + } if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL) goto malformed_resp; @@ -411,7 +363,7 @@ link_del(const char *name) if (err->error) { virReportSystemError(-err->error, _("error destroying %s interface"), - name); + ifname); rc = -1; } break; @@ -423,19 +375,26 @@ link_del(const char *name) goto malformed_resp; } +err_exit: + nlmsg_free(nl_msg); + VIR_FREE(recvbuf); return rc; malformed_resp: + nlmsg_free(nl_msg); + macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed netlink response message")); VIR_FREE(recvbuf); return -1; buffer_too_small: + nlmsg_free(nl_msg); + macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", - _("internal buffer is too small")); + _("allocated netlink buffer is too small")); return -1; } @@ -783,40 +742,44 @@ link_dump(bool nltarget_kernel, const char *ifname, int ifindex, struct nlattr **tb, char **recvbuf) { int rc = 0; - char nlmsgbuf[NLMSGBUF_SIZE] = { 0, }; - struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp; + struct nlmsghdr *resp; struct nlmsgerr *err; - char rtattbuf[RATTBUF_SIZE]; - struct rtattr *rta; struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC, .ifi_index = ifindex }; unsigned int recvbuflen; uint32_t pid = 0; + struct nl_msg *nl_msg; *recvbuf = NULL; - nlInit(nlm, NLM_F_REQUEST, RTM_GETLINK); + nl_msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST); + if (!nl_msg) { + virReportOOMError(); + return -1; + } - if (!nlAppend(nlm, sizeof(nlmsgbuf), &ifinfo, sizeof(ifinfo))) + if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0) goto buffer_too_small; if (ifindex < 0 && ifname) { - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME, - ifname, strlen(ifname) + 1); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) goto buffer_too_small; } if (!nltarget_kernel) { pid = getLldpadPid(); - if (pid == 0) - return -1; + if (pid == 0) { + rc = -1; + goto err_exit; + } } - if (nlComm(nlm, recvbuf, &recvbuflen, pid) < 0) - return -1; + if (nlComm(nlmsg_hdr(nl_msg), recvbuf, &recvbuflen, pid) < 0) { + rc = -1; + goto err_exit; + } if (recvbuflen < NLMSG_LENGTH(0) || *recvbuf == NULL) goto malformed_resp; @@ -852,17 +815,24 @@ link_dump(bool nltarget_kernel, const char *ifname, int ifindex, if (rc != 0) VIR_FREE(*recvbuf); +err_exit: + nlmsg_free(nl_msg); + return rc; malformed_resp: + nlmsg_free(nl_msg); + macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed netlink response message")); VIR_FREE(*recvbuf); return -1; buffer_too_small: + nlmsg_free(nl_msg); + macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", - _("internal buffer is too small")); + _("allocated netlink buffer is too small")); return -1; } @@ -1046,11 +1016,8 @@ doPortProfileOpSetLink(bool nltarget_kernel, uint8_t op) { int rc = 0; - char nlmsgbuf[NLMSGBUF_SIZE]; - struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp; + struct nlmsghdr *resp; struct nlmsgerr *err; - char rtattbuf[RATTBUF_SIZE]; - struct rtattr *rta, *vfports = NULL, *vfport; struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC, .ifi_index = ifindex, @@ -1058,23 +1025,24 @@ doPortProfileOpSetLink(bool nltarget_kernel, char *recvbuf = NULL; unsigned int recvbuflen = 0; uint32_t pid = 0; + struct nl_msg *nl_msg; + struct nlattr *vfports = NULL, *vfport; - memset(&nlmsgbuf, 0, sizeof(nlmsgbuf)); - - nlInit(nlm, NLM_F_REQUEST, RTM_SETLINK); + nl_msg = nlmsg_alloc_simple(RTM_SETLINK, NLM_F_REQUEST); + if (!nl_msg) { + virReportOOMError(); + return -1; + } - if (!nlAppend(nlm, sizeof(nlmsgbuf), &ifinfo, sizeof(ifinfo))) + if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0) goto buffer_too_small; - if (ifname) { - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME, - ifname, strlen(ifname) + 1); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) - goto buffer_too_small; - } + if (ifname && + nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) + goto buffer_too_small; if (macaddr && vlanid >= 0) { - struct rtattr *vfinfolist, *vfinfo; + struct nlattr *vfinfolist, *vfinfo; struct ifla_vf_mac ifla_vf_mac = { .vf = vf, .mac = { 0, }, @@ -1087,110 +1055,88 @@ doPortProfileOpSetLink(bool nltarget_kernel, memcpy(ifla_vf_mac.mac, macaddr, 6); - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VFINFO_LIST, - NULL, 0); - if (!rta || - !(vfinfolist = nlAppend(nlm, sizeof(nlmsgbuf), - rtattbuf, rta->rta_len))) + if (!(vfinfolist = nla_nest_start(nl_msg, IFLA_VFINFO_LIST))) goto buffer_too_small; - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_INFO, - NULL, 0); - if (!rta || - !(vfinfo = nlAppend(nlm, sizeof(nlmsgbuf), - rtattbuf, rta->rta_len))) + if (!(vfinfo = nla_nest_start(nl_msg, IFLA_VF_INFO))) goto buffer_too_small; - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_MAC, - &ifla_vf_mac, sizeof(ifla_vf_mac)); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + if (!nla_put(nl_msg, IFLA_VF_MAC, sizeof(ifla_vf_mac), + &ifla_vf_mac) < 0) goto buffer_too_small; - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_VLAN, - &ifla_vf_vlan, sizeof(ifla_vf_vlan)); - - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + if (!nla_put(nl_msg, IFLA_VF_VLAN, sizeof(ifla_vf_vlan), + &ifla_vf_vlan) < 0) goto buffer_too_small; - vfinfo->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)vfinfo; - - vfinfolist->rta_len = (char *)nlm + nlm->nlmsg_len - - (char *)vfinfolist; + nla_nest_end(nl_msg, vfinfo); + nla_nest_end(nl_msg, vfinfolist); } if (vf == PORT_SELF_VF && nltarget_kernel) { - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_SELF, NULL, 0); + if (!(vfport = nla_nest_start(nl_msg, IFLA_PORT_SELF))) + goto buffer_too_small; } else { - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_PORTS, NULL, 0); - if (!rta || - !(vfports = nlAppend(nlm, sizeof(nlmsgbuf), - rtattbuf, rta->rta_len))) + if (!(vfports = nla_nest_start(nl_msg, IFLA_VF_PORTS))) goto buffer_too_small; /* begin nesting vfports */ - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_PORT, NULL, 0); + if (!(vfport = nla_nest_start(nl_msg, IFLA_VF_PORT))) + goto buffer_too_small; } - if (!rta || - !(vfport = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))) - goto buffer_too_small; - if (profileId) { - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_PROFILE, - profileId, strlen(profileId) + 1); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + if (nla_put(nl_msg, IFLA_PORT_PROFILE, strlen(profileId) + 1, + profileId) < 0) goto buffer_too_small; } if (portVsi) { - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_VSI_TYPE, - portVsi, sizeof(*portVsi)); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + if (nla_put(nl_msg, IFLA_PORT_VSI_TYPE, sizeof(*portVsi), + portVsi) < 0) goto buffer_too_small; } if (instanceId) { - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_INSTANCE_UUID, - instanceId, VIR_UUID_BUFLEN); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + if (nla_put(nl_msg, IFLA_PORT_INSTANCE_UUID, VIR_UUID_BUFLEN, + instanceId) < 0) goto buffer_too_small; } if (hostUUID) { - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_HOST_UUID, - hostUUID, VIR_UUID_BUFLEN); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + if (nla_put(nl_msg, IFLA_PORT_HOST_UUID, VIR_UUID_BUFLEN, + hostUUID) < 0) goto buffer_too_small; } if (vf != PORT_SELF_VF) { - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_VF, - &vf, sizeof(vf)); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + if (nla_put(nl_msg, IFLA_PORT_VF, sizeof(vf), &vf) < 0) goto buffer_too_small; } - rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_REQUEST, - &op, sizeof(op)); - if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + if (nla_put(nl_msg, IFLA_PORT_REQUEST, sizeof(op), &op) < 0) goto buffer_too_small; /* end nesting of vport */ - vfport->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)vfport; + nla_nest_end(nl_msg, vfport); if (vfports) { /* end nesting of vfports */ - vfports->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)vfports; + nla_nest_end(nl_msg, vfports); } if (!nltarget_kernel) { pid = getLldpadPid(); - if (pid == 0) - return -1; + if (pid == 0) { + rc = -1; + goto err_exit; + } } - if (nlComm(nlm, &recvbuf, &recvbuflen, pid) < 0) - return -1; + if (nlComm(nlmsg_hdr(nl_msg), &recvbuf, &recvbuflen, pid) < 0) { + rc = -1; + goto err_exit; + } if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL) goto malformed_resp; @@ -1218,19 +1164,26 @@ doPortProfileOpSetLink(bool nltarget_kernel, goto malformed_resp; } +err_exit: + nlmsg_free(nl_msg); + VIR_FREE(recvbuf); return rc; malformed_resp: + nlmsg_free(nl_msg); + macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed netlink response message")); VIR_FREE(recvbuf); return -1; buffer_too_small: + nlmsg_free(nl_msg); + macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", - _("internal buffer is too small")); + _("allocated netlink buffer is too small")); return -1; } -- GitLab