ns_ifmove.c revision 0eb8985098758972c8e3fc2291b2f080be3b9f54
1/* Copyright (c) 2015 Red Hat, Inc. 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of version 2 the GNU General Public License as 5 * published by the Free Software Foundation. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * 15 * Written by Matus Marhefka <mmarhefk@redhat.com> 16 * 17 *********************************************************************** 18 * Moves a network interface to the namespace of a process specified by a PID. 19 * 20 */ 21 22#define _GNU_SOURCE 23#include <stdlib.h> 24#include <string.h> 25#include <errno.h> 26#include <unistd.h> 27#include <asm/types.h> 28#include <sys/socket.h> 29#include <linux/rtnetlink.h> 30#include <sys/ioctl.h> 31#include <linux/if.h> 32#include <net/ethernet.h> 33#include <arpa/inet.h> 34#include "test.h" 35 36#include "config.h" 37 38char *TCID = "ns_ifmove"; 39 40#if HAVE_DECL_IFLA_NET_NS_PID 41 42struct { 43 struct nlmsghdr nh; 44 struct ifinfomsg ifi; 45 char attrbuf[512]; 46} req; 47 48 49int get_intf_index_from_name(const char *intf_name) 50{ 51 struct ifreq ifr; 52 int sock_fd; 53 54 memset(&ifr, 0, sizeof(ifr)); 55 strncpy(ifr.ifr_name, intf_name, sizeof(ifr.ifr_name) - 1); 56 ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0'; 57 58 sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 59 if (sock_fd == -1) { 60 tst_resm(TINFO | TERRNO, "socket"); 61 return -1; 62 } 63 64 /* gets interface index */ 65 if (ioctl(sock_fd, SIOCGIFINDEX, &ifr) == -1) { 66 tst_resm(TINFO | TERRNO, "ioctl"); 67 close(sock_fd); 68 return -1; 69 } 70 71 close(sock_fd); 72 return ifr.ifr_ifindex; 73} 74 75/* 76 * ./ns_ifmove <INTERFACE_NAME> <NAMESPACE_PID> 77 */ 78int main(int argc, char **argv) 79{ 80 struct rtattr *rta; 81 int intf_index, pid, rtnetlink_socket; 82 83 if (argc != 3) { 84 tst_resm(TINFO, "%s <INTERFACE_NAME> <NAMESPACE_PID>\n", 85 argv[0]); 86 return 1; 87 } 88 89 intf_index = get_intf_index_from_name(argv[1]); 90 if (intf_index == -1) { 91 tst_resm(TINFO , "unable to get interface index"); 92 return 1; 93 } 94 95 pid = atoi(argv[2]); 96 97 rtnetlink_socket = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); 98 if (rtnetlink_socket == -1) { 99 tst_resm(TINFO | TERRNO, "socket"); 100 return 1; 101 } 102 103 memset(&req, 0, sizeof(req)); 104 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); 105 req.nh.nlmsg_flags = NLM_F_REQUEST; 106 req.nh.nlmsg_type = RTM_NEWLINK; 107 req.ifi.ifi_family = AF_UNSPEC; 108 req.ifi.ifi_index = intf_index; 109 req.ifi.ifi_change = 0xffffffff; 110 rta = (struct rtattr *)(((char *) &req) + 111 NLMSG_ALIGN(req.nh.nlmsg_len)); 112 rta->rta_type = IFLA_NET_NS_PID; 113 rta->rta_len = RTA_LENGTH(sizeof(int)); 114 req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) + 115 RTA_LENGTH(sizeof(pid)); 116 memcpy(RTA_DATA(rta), &pid, sizeof(pid)); 117 118 if (send(rtnetlink_socket, &req, req.nh.nlmsg_len, 0) == -1) { 119 tst_resm(TINFO | TERRNO, "send"); 120 return 1; 121 } 122 123 close(rtnetlink_socket); 124 return 0; 125} 126 127#else 128 129int main(void) 130{ 131 tst_brkm(TCONF, NULL, "IFLA_NET_NS_PID not defined in linux/if_link.h"); 132} 133 134#endif 135