IBR-DTNSuite  0.8
ibrcommon/ibrcommon/net/lowpansocket.cpp
Go to the documentation of this file.
00001 /*
00002  * lowpansocket.cpp
00003  *
00004  *  Created on: 01.06.2010
00005  *      Author: stschmid
00006  */
00007 
00008 #include "ibrcommon/config.h"
00009 #include "ibrcommon/net/lowpansocket.h"
00010 #include <sys/socket.h>
00011 #include <errno.h>
00012 #include <sys/types.h>
00013 #include <netinet/in.h>
00014 #include <arpa/inet.h>
00015 #include <string.h>
00016 #include <stdlib.h>
00017 
00018 #if defined HAVE_LIBNL || HAVE_LIBNL3
00019 #include <netlink/route/link.h>
00020 #include <netlink/route/addr.h>
00021 #include <netlink/genl/genl.h>
00022 #include <netlink/genl/ctrl.h>
00023 #endif
00024 
00025 extern "C" {
00026 #include "ibrcommon/net/ieee802154.h"
00027 #include "ibrcommon/net/nl802154.h"
00028 extern struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1];
00029 };
00030 
00031 namespace ibrcommon
00032 {
00033         lowpansocket::lowpansocket(u_char proto) throw (SocketException)
00034         {
00035                 int sock = 0;
00036 
00037                 // Create socket for listening for client connection requests.
00038                 if ((sock = ::socket(PF_IEEE802154, SOCK_DGRAM, 0)) < 0) // Ignoring proto for now
00039                 {
00040                         throw SocketException("lowpansocket: cannot create listen socket");
00041                 }
00042 
00043                 bzero(&_sockaddr, sizeof(_sockaddr));
00044                 _sockaddr.family = AF_IEEE802154;
00045                 _sockaddr.addr.addr_type = IEEE802154_ADDR_SHORT;
00046 
00047                 // add the new fd to the virtual socket
00048                 _vsocket.add(sock);
00049         }
00050 
00051         lowpansocket::~lowpansocket()
00052         {
00053                 shutdown();
00054         }
00055 
00056         void lowpansocket::shutdown()
00057         {
00058                 _vsocket.close();
00059         }
00060 
00061         int lowpansocket::receive(char* data, size_t maxbuffer)
00062         {
00063                 struct sockaddr_ieee802154 clientAddress;
00064                 socklen_t clientAddressLength = sizeof(clientAddress);
00065 
00066                 std::list<int> fds;
00067                 _vsocket.select(fds, NULL);
00068                 int fd = fds.front();
00069 
00070                 int ret = recvfrom(fd, data, maxbuffer, MSG_WAITALL, (struct sockaddr *) &clientAddress, &clientAddressLength);
00071                 return ret;
00072         }
00073 
00074         lowpansocket::peer::peer(lowpansocket &socket, const struct sockaddr_ieee802154 &dest, const unsigned int panid)
00075          : _socket(socket)
00076         {
00077                 bzero(&_destaddress, sizeof(_destaddress));
00078                 _destaddress.family = AF_IEEE802154;
00079                 _destaddress.addr.addr_type = IEEE802154_ADDR_SHORT;
00080 
00081                 memcpy(&_destaddress.addr.short_addr, &dest.addr.short_addr, sizeof(_destaddress.addr.short_addr));
00082                 _destaddress.addr.pan_id = panid;
00083         }
00084 
00085         int lowpansocket::peer::send(const char *data, const size_t length)
00086         {
00087                 int stat = -1;
00088 
00089                 // iterate over all sockets
00090                 std::list<int> fds = _socket._vsocket.get();
00091 
00092                 for (std::list<int>::const_iterator iter = fds.begin(); iter != fds.end(); iter++)
00093                 {
00094                         ssize_t ret = 0;
00095 
00096                         ::connect(_socket._vsocket.fd(), (struct sockaddr *) &_destaddress, sizeof(_destaddress));
00097                         //printf("lowpan send() address %04x, PAN %04x\n", _destaddress.addr.short_addr, _destaddress.addr.pan_id);
00098                         //return ::sendto(_socket._socket, data, length, 0, (struct sockaddr *) &_destaddress, sizeof(_destaddress));
00099                         ret = ::send(*iter, data, length, 0);
00100 
00101                         // if the send was successful, set the correct return value
00102                         if (ret != -1) stat = ret;
00103                 }
00104 
00105                 return stat;
00106         }
00107 
00108         lowpansocket::peer lowpansocket::getPeer(unsigned int address, const unsigned int panid)
00109         {
00110                 struct sockaddr_ieee802154 destaddress;
00111 
00112                 destaddress.addr.short_addr = address;
00113                 return lowpansocket::peer(*this, destaddress, panid);
00114         }
00115 
00116         void lowpansocket::getAddress(struct ieee802154_addr *ret, const vinterface &iface)
00117         {
00118 #if defined HAVE_LIBNL || HAVE_LIBNL3
00119 #ifdef HAVE_LIBNL3
00120                 struct nl_sock *nl = nl_socket_alloc();
00121 #else
00122                 struct nl_handle *nl = nl_handle_alloc();
00123 #endif
00124                 unsigned char *buf = NULL;
00125                 struct sockaddr_nl nla;
00126                 struct nlattr *attrs[IEEE802154_ATTR_MAX+1];
00127                 struct genlmsghdr *ghdr;
00128                 struct nlmsghdr *nlh;
00129                 struct nl_msg *msg;
00130                 int family;
00131 
00132                 if (!nl)
00133                         return;
00134 
00135                 genl_connect(nl);
00136 
00137                 /* Build and send message */
00138                 msg = nlmsg_alloc();
00139                 family = genl_ctrl_resolve(nl, "802.15.4 MAC");
00140                 genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO, IEEE802154_LIST_IFACE, 1);
00141                 nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, iface.toString().c_str());
00142                 nl_send_auto_complete(nl, msg);
00143                 nlmsg_free(msg);
00144 
00145                 /* Receive and parse answer */
00146                 nl_recv(nl, &nla, &buf, NULL);
00147                 nlh = (struct nlmsghdr*)buf;
00148                 genlmsg_parse(nlh, 0, attrs, IEEE802154_ATTR_MAX, ieee802154_policy);
00149                 ghdr = (genlmsghdr*)nlmsg_data(nlh);
00150                 if (!attrs[IEEE802154_ATTR_SHORT_ADDR] || !attrs[IEEE802154_ATTR_SHORT_ADDR])
00151                         return;
00152 
00153                 // We only handle short addresses right now
00154                 ret->addr_type = IEEE802154_ADDR_SHORT;
00155                 ret->pan_id = nla_get_u16(attrs[IEEE802154_ATTR_PAN_ID]);
00156                 ret->short_addr = nla_get_u16(attrs[IEEE802154_ATTR_SHORT_ADDR]);
00157 
00158                 free(buf);
00159                 nl_close(nl);
00160 
00161 #ifdef HAVE_LIBNL3
00162                 nl_socket_free(nl);
00163 #else
00164                 nl_handle_destroy(nl);
00165 #endif
00166 #endif
00167         }
00168 }