shill: Create and register a Cellular device for each ModemManager.Modem.

BUG=chromium-os:17818
TEST=unit tests

Change-Id: Ic35adf35c8021f4c9689e72ddd03776948d036c1
Reviewed-on: http://gerrit.chromium.org/gerrit/4711
Reviewed-by: Darin Petkov <petkov@chromium.org>
Tested-by: Darin Petkov <petkov@chromium.org>
diff --git a/rtnl_handler.cc b/rtnl_handler.cc
index 089180e..443d1cf 100644
--- a/rtnl_handler.cc
+++ b/rtnl_handler.cc
@@ -6,6 +6,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <string.h>
+#include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
 #include <netinet/ether.h>
@@ -14,7 +15,6 @@
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
 #include <fcntl.h>
-#include <string>
 
 #include <base/logging.h>
 
@@ -336,4 +336,30 @@
   return AddressRequest(interface_index, RTM_DELADDR, 0, ipconfig);
 }
 
+int RTNLHandler::GetInterfaceIndex(const string &interface_name) {
+  if (interface_name.empty()) {
+    LOG(ERROR) << "Empty interface name -- unable to obtain index.";
+    return -1;
+  }
+  struct ifreq ifr;
+  if (interface_name.size() >= sizeof(ifr.ifr_name)) {
+    LOG(ERROR) << "Interface name too long: " << interface_name.size() << " >= "
+               << sizeof(ifr.ifr_name);
+    return -1;
+  }
+  int socket = sockets_->Socket(PF_INET, SOCK_DGRAM, 0);
+  if (socket < 0) {
+    PLOG(ERROR) << "Unable to open INET socket";
+    return -1;
+  }
+  ScopedSocketCloser socket_closer(sockets_, socket);
+  memset(&ifr, 0, sizeof(ifr));
+  strncpy(ifr.ifr_name, interface_name.c_str(), sizeof(ifr.ifr_name));
+  if (sockets_->Ioctl(socket, SIOCGIFINDEX, &ifr) < 0) {
+    PLOG(ERROR) << "SIOCGIFINDEX error for " << interface_name;
+    return -1;
+  }
+  return ifr.ifr_ifindex;
+}
+
 }  // namespace shill