int add_link() { struct rtattr *nest; struct link_req req, ans; int rtnetlink_sk, ifindex; int ret; rtnetlink_sk = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); memset(&req, 0, sizeof(req)); req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.nh.nlmsg_flags = NLM_F_REQUEST; req.nh.nlmsg_type = RTM_NEWLINK; req.ifa.ifi_family = AF_UNSPEC; printf("nh:%ld, ifa:%ld, nlmsg_len:%d\n", sizeof(req.nh), sizeof(req.ifa), req.nh.nlmsg_len); nest = rta_begin_nested(&req, IFLA_LINKINFO); rta_put(&req, IFLA_INFO_KIND, "macvlan", strlen("macvlan")+1); rta_end_nested(&req, nest); printf("rta_len:%d, nlmsg_len:%d\n", nest->rta_len, req.nh.nlmsg_len); ifindex = if_nametoindex("eth0"); rta_put(&req, IFLA_LINK, &ifindex, sizeof(int)); printf("nlmsg_len:%d\n", req.nh.nlmsg_len); rta_put(&req, IFLA_IFNAME, "macvlan001", strlen("macvlan001")+1); printf("nlmsg_len:%d\n", req.nh.nlmsg_len); printf("send request for add macvlan001\n"); ret = send(rtnetlink_sk, &req, req.nh.nlmsg_len, 0); printf("send ret:%d\n", ret); ret = recv(rtnetlink_sk, &ans, NLMSG_LENGTH(sizeof(struct ifinfomsg) + 1024), 0); printf("recv ret:%d, nlmsg_type:%d\n", ret, ans.nh.nlmsg_type); if (ans.nh.nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(&ans); printf("error:%d\n", err->error); return err->error; } return 0; }
struct rtattr *rta_begin_nested(struct link_req *req, int attr) { struct rtattr *rtattr = NLMSG_TAIL(&req->nh); if (rta_put(req, attr, NULL, 0)) return NULL; return rtattr; }
hidden int rta_put_address(struct nlmsghdr *msg, int type, struct sockaddr *adr) { switch (adr->sa_family) { case AF_INET: { struct in_addr *i = rta_put(msg, type, 4); *i = ((struct sockaddr_in *)adr)->sin_addr; break; } case AF_INET6: { struct in6_addr *i6 = rta_put(msg, type, 16); *i6 = ((struct sockaddr_in6 *)adr)->sin6_addr; break; } default: return -1; } return 0; }