1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "common/libs/net/netlink_client.h"
18 #include "common/libs/net/netlink_request.h"
19 #include "common/libs/net/network_interface.h"
20 #include "common/libs/net/network_interface_manager.h"
21 
22 #include <linux/rtnetlink.h>
23 #include <net/if.h>
24 #include <iostream>
25 #include <string>
26 
main(int argc,char * argv[])27 int main(int argc, char *argv[]) {
28   if (!((argc == 5 && std::string(argv[1]) == "vlan") ||
29         (argc == 4 && std::string(argv[1]) == "virt_wifi"))) {
30     std::cerr << "usages:\n";
31     std::cerr << "  " << argv[0] << " vlan [ethA] [ethB] [index]\n";
32     std::cerr << "  " << argv[0] << " virt_wifi [ethA] [ethB]\n";
33     return -1;
34   }
35   const char *const name = argv[2];
36   int32_t index = if_nametoindex(name);
37   if (index == 0) {
38     fprintf(stderr, "%s: invalid interface name '%s'\n", argv[2], name);
39     return -2;
40   }
41   const char *const new_name = argv[3];
42   auto factory = cuttlefish::NetlinkClientFactory::Default();
43   std::unique_ptr<cuttlefish::NetlinkClient> nl(factory->New(NETLINK_ROUTE));
44 
45   // http://maz-programmersdiary.blogspot.com/2011/09/netlink-sockets.html
46   cuttlefish::NetlinkRequest link_add_request(RTM_NEWLINK, NLM_F_REQUEST|NLM_F_ACK|0x600);
47   link_add_request.Append(ifinfomsg {
48     .ifi_change = 0xFFFFFFFF,
49   });
50   link_add_request.AddString(IFLA_IFNAME, std::string(new_name));
51   link_add_request.AddInt(IFLA_LINK, index);
52 
53   link_add_request.PushList(IFLA_LINKINFO);
54   link_add_request.AddString(IFLA_INFO_KIND, argv[1]);
55   link_add_request.PushList(IFLA_INFO_DATA);
56   if (std::string(argv[1]) == "vlan") {
57     uint16_t vlan_index = atoi(argv[4]);
58     link_add_request.AddInt(IFLA_VLAN_ID, vlan_index);
59   }
60   link_add_request.PopList();
61   link_add_request.PopList();
62 
63   nl->Send(link_add_request);
64 
65   cuttlefish::NetlinkRequest bring_up_backing_request(RTM_SETLINK, NLM_F_REQUEST|NLM_F_ACK|0x600);
66   bring_up_backing_request.Append(ifinfomsg {
67     .ifi_index = index,
68     .ifi_flags = IFF_UP,
69     .ifi_change = 0xFFFFFFFF,
70   });
71 
72   nl->Send(bring_up_backing_request);
73 
74   return 0;
75 }
76