Apache Mesos
internal.hpp
Go to the documentation of this file.
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #ifndef __LINUX_ROUTING_LINK_INTERNAL_HPP__
18 #define __LINUX_ROUTING_LINK_INTERNAL_HPP__
19 
20 #include <errno.h>
21 #include <string.h>
22 
23 #include <sys/ioctl.h>
24 #include <sys/socket.h>
25 
26 #include <linux/if.h> // Must be included after sys/socket.h.
27 
28 #include <netlink/cache.h>
29 #include <netlink/errno.h>
30 #include <netlink/socket.h>
31 
32 #include <netlink/route/link.h>
33 
34 #include <string>
35 
36 #include <stout/error.hpp>
37 #include <stout/none.hpp>
38 #include <stout/os.hpp>
39 #include <stout/result.hpp>
40 #include <stout/try.hpp>
41 
43 
44 namespace routing {
45 
46 template <>
47 inline void cleanup(struct rtnl_link* link)
48 {
49  rtnl_link_put(link);
50 }
51 
52 namespace link {
53 namespace internal {
54 
55 // Returns the netlink link object associated with a given link by its
56 // name. Returns None if the link is not found.
57 inline Result<Netlink<struct rtnl_link>> get(const std::string& link)
58 {
60  if (socket.isError()) {
61  return Error(socket.error());
62  }
63 
64  // Dump all the netlink link objects from kernel. Note that the flag
65  // AF_UNSPEC means all available families.
66  struct nl_cache* c = nullptr;
67  int error = rtnl_link_alloc_cache(socket->get(), AF_UNSPEC, &c);
68  if (error != 0) {
69  return Error(nl_geterror(error));
70  }
71 
72  Netlink<struct nl_cache> cache(c);
73  struct rtnl_link* l = rtnl_link_get_by_name(cache.get(), link.c_str());
74  if (l == nullptr) {
75  return None();
76  }
77 
78  return Netlink<struct rtnl_link>(l);
79 }
80 
81 
82 // Returns the netlink link object associated with a given link by its
83 // interface index. Returns None if the link is not found.
85 {
87  if (socket.isError()) {
88  return Error(socket.error());
89  }
90 
91  // Dump all the netlink link objects from kernel. Note that the flag
92  // AF_UNSPEC means all available families.
93  struct nl_cache* c = nullptr;
94  int error = rtnl_link_alloc_cache(socket->get(), AF_UNSPEC, &c);
95  if (error != 0) {
96  return Error(nl_geterror(error));
97  }
98 
99  Netlink<struct nl_cache> cache(c);
100  struct rtnl_link* l = rtnl_link_get(cache.get(), index);
101  if (l == nullptr) {
102  return None();
103  }
104 
105  return Netlink<struct rtnl_link>(l);
106 }
107 
108 
109 // Tests if the flags are set on the link. Returns None if the link is
110 // not found.
111 inline Result<bool> test(const std::string& _link, unsigned int flags)
112 {
113  Result<Netlink<struct rtnl_link>> link = get(_link);
114  if (link.isError()) {
115  return Error(link.error());
116  } else if (link.isNone()) {
117  return None();
118  }
119 
120  return flags == (rtnl_link_get_flags(link->get()) & flags);
121 }
122 
123 
124 // Sets the flags on the link. Returns false if the link is not found.
125 inline Try<bool> set(const std::string& _link, unsigned int flags)
126 {
127  Result<Netlink<struct rtnl_link>> link = get(_link);
128  if (link.isError()) {
129  return Error(link.error());
130  } else if (link.isNone()) {
131  return false;
132  }
133 
134  // TODO(jieyu): We use ioctl to set the flags because the interfaces
135  // in libnl have some issues with virtual devices.
136  struct ifreq ifr;
137  memset(&ifr, 0, sizeof(ifr));
138 
139  // Get the existing flags and take a bit-wise OR.
140  ifr.ifr_flags = (rtnl_link_get_flags(link->get()) | flags);
141 
142  strncpy(ifr.ifr_name, _link.c_str(), IFNAMSIZ);
143 
144  int fd = ::socket(AF_INET, SOCK_STREAM, 0);
145  if (fd == -1) {
146  return ErrnoError();
147  }
148 
149  if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) {
150  if (errno == ENODEV) {
151  os::close(fd);
152  return false;
153  } else {
154  // Save the error string as os::close may overwrite errno.
155  const std::string message = os::strerror(errno);
156  os::close(fd);
157  return Error(message);
158  }
159  }
160 
161  os::close(fd);
162  return true;
163 }
164 
165 } // namespace internal {
166 } // namespace link {
167 } // namespace routing {
168 
169 #endif // __LINUX_ROUTING_LINK_INTERNAL_HPP__
std::string strerror(int errno_)
A thread-safe version of strerror.
Definition: strerror.hpp:30
bool isNone() const
Definition: result.hpp:113
Definition: errorbase.hpp:36
T & get()&
Definition: try.hpp:80
Definition: check.hpp:33
static Result< T > error(const std::string &message)
Definition: result.hpp:54
Definition: errorbase.hpp:50
Definition: check.hpp:30
Try< Nothing > close(int fd)
Definition: close.hpp:24
static Try error(const E &e)
Definition: try.hpp:43
#define flags
Definition: decoder.hpp:18
Definition: none.hpp:27
Definition: attributes.hpp:24
bool isError() const
Definition: try.hpp:78
std::string error(const std::string &msg, uint32_t code)
T & get()&
Definition: result.hpp:116
Definition: diagnosis.hpp:30
bool isError() const
Definition: result.hpp:114
void cleanup(struct rtnl_cls *cls)
Definition: internal.hpp:64
Try< Netlink< struct nl_sock > > socket(int protocol=NETLINK_ROUTE)
Definition: internal.hpp:91
Definition: parse.hpp:33