| 247 | |
| 248 | |
| 249 | Try<bool> setMAC(const string& link, const net::MAC& mac) |
| 250 | { |
| 251 | // TODO(jieyu): We use ioctl to set the MAC address because the |
| 252 | // interfaces in libnl have some issues with virtual devices. |
| 253 | struct ifreq ifr; |
| 254 | memset(&ifr, 0, sizeof(ifr)); |
| 255 | |
| 256 | strncpy(ifr.ifr_name, link.c_str(), IFNAMSIZ); |
| 257 | |
| 258 | int fd = ::socket(AF_INET, SOCK_STREAM, 0); |
| 259 | if (fd == -1) { |
| 260 | return ErrnoError(); |
| 261 | } |
| 262 | |
| 263 | // Since loopback interface has sa_family ARPHRD_LOOPBACK, we need |
| 264 | // to get the MAC address of the link first to decide what value the |
| 265 | // sa_family should be. |
| 266 | if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) { |
| 267 | if (errno == ENODEV) { |
| 268 | os::close(fd); |
| 269 | return false; |
| 270 | } else { |
| 271 | // Save the error string as os::close may overwrite errno. |
| 272 | const string message = os::strerror(errno); |
| 273 | os::close(fd); |
| 274 | return Error(message); |
| 275 | } |
| 276 | } |
| 277 | |
| 278 | ifr.ifr_hwaddr.sa_data[0] = mac[0]; |
| 279 | ifr.ifr_hwaddr.sa_data[1] = mac[1]; |
| 280 | ifr.ifr_hwaddr.sa_data[2] = mac[2]; |
| 281 | ifr.ifr_hwaddr.sa_data[3] = mac[3]; |
| 282 | ifr.ifr_hwaddr.sa_data[4] = mac[4]; |
| 283 | ifr.ifr_hwaddr.sa_data[5] = mac[5]; |
| 284 | |
| 285 | if (ioctl(fd, SIOCSIFHWADDR, &ifr) == -1) { |
| 286 | if (errno == ENODEV) { |
| 287 | os::close(fd); |
| 288 | return false; |
| 289 | } else { |
| 290 | // Save the error string as os::close may overwrite errno. |
| 291 | const string message = os::strerror(errno); |
| 292 | os::close(fd); |
| 293 | return Error(message); |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | os::close(fd); |
| 298 | return true; |
| 299 | } |
| 300 | |
| 301 | |
| 302 | Result<unsigned int> mtu(const string& _link) |