IBR-DTNSuite 0.6

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 #ifdef HAVE_LIBNL
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                 // Create socket for listening for client connection requests.
00036                 if ((_socket = ::socket(PF_IEEE802154, SOCK_DGRAM, 0)) < 0) // Ignoring proto for now
00037                 {
00038                         throw SocketException("lowpansocket: cannot create listen socket");
00039                 }
00040 
00041                 bzero(&_sockaddr, sizeof(_sockaddr));
00042                 _sockaddr.family = AF_IEEE802154;
00043                 _sockaddr.addr.addr_type = IEEE802154_ADDR_SHORT;
00044         }
00045 
00046         lowpansocket::~lowpansocket()
00047         {
00048                 shutdown();
00049         }
00050 
00051         void lowpansocket::shutdown()
00052         {
00053                 if (_socket == -1) return;
00054                 ::close(_socket);
00055                 _socket = -1;
00056         }
00057 
00058         int lowpansocket::receive(char* data, size_t maxbuffer)
00059         {
00060                 struct sockaddr_ieee802154 clientAddress;
00061                 socklen_t clientAddressLength = sizeof(clientAddress);
00062 
00063                 int ret = recvfrom(_socket, data, maxbuffer, MSG_WAITALL, (struct sockaddr *) &clientAddress, &clientAddressLength);
00064                 return ret;
00065         }
00066 
00067         lowpansocket::peer::peer(lowpansocket &socket, const struct sockaddr_ieee802154 &dest, const unsigned int panid)
00068          : _socket(socket)
00069         {
00070                 bzero(&_destaddress, sizeof(_destaddress));
00071                 _destaddress.family = AF_IEEE802154;
00072                 _destaddress.addr.addr_type = IEEE802154_ADDR_SHORT;
00073 
00074                 memcpy(&_destaddress.addr.short_addr, &dest.addr.short_addr, sizeof(_destaddress.addr.short_addr));
00075                 _destaddress.addr.pan_id = panid;
00076         }
00077 
00078         int lowpansocket::peer::send(const char *data, const size_t length)
00079         {
00080                 ::connect(_socket._socket, (struct sockaddr *) &_destaddress, sizeof(_destaddress));
00081                 //printf("lowpan send() address %04x, PAN %04x\n", _destaddress.addr.short_addr, _destaddress.addr.pan_id);
00082                 //return ::sendto(_socket._socket, data, length, 0, (struct sockaddr *) &_destaddress, sizeof(_destaddress));
00083                 return ::send(_socket._socket, data, length, 0);
00084         }
00085 
00086         lowpansocket::peer lowpansocket::getPeer(const string address, const unsigned int panid)
00087         {
00088                 struct sockaddr_ieee802154 destaddress;
00089 
00090                 destaddress.addr.short_addr = atoi(address.c_str());
00091                 return lowpansocket::peer(*this, destaddress, panid);
00092         }
00093 
00094         void lowpansocket::getAddress(struct ieee802154_addr *ret, const vinterface &iface)
00095         {
00096 #ifdef HAVE_LIBNL
00097                 struct nl_handle *nl = nl_handle_alloc();
00098                 unsigned char *buf = NULL;
00099                 struct sockaddr_nl nla;
00100                 struct nlattr *attrs[IEEE802154_ATTR_MAX+1];
00101                 struct genlmsghdr *ghdr;
00102                 struct nlmsghdr *nlh;
00103                 struct nl_msg *msg;
00104                 int family;
00105 
00106                 if (!nl)
00107                         return;
00108 
00109                 genl_connect(nl);
00110 
00111                 /* Build and send message */
00112                 msg = nlmsg_alloc();
00113                 family = genl_ctrl_resolve(nl, "802.15.4 MAC");
00114                 genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO, IEEE802154_LIST_IFACE, 1);
00115                 nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, iface.toString().c_str());
00116                 nl_send_auto_complete(nl, msg);
00117                 nlmsg_free(msg);
00118 
00119                 /* Receive and parse answer */
00120                 nl_recv(nl, &nla, &buf, NULL);
00121                 nlh = (struct nlmsghdr*)buf;
00122                 genlmsg_parse(nlh, 0, attrs, IEEE802154_ATTR_MAX, ieee802154_policy);
00123                 ghdr = (genlmsghdr*)nlmsg_data(nlh);
00124                 if (!attrs[IEEE802154_ATTR_SHORT_ADDR] || !attrs[IEEE802154_ATTR_SHORT_ADDR])
00125                         return;
00126 
00127                 // We only handle short addresses right now
00128                 ret->addr_type = IEEE802154_ADDR_SHORT;
00129                 ret->pan_id = nla_get_u16(attrs[IEEE802154_ATTR_PAN_ID]);
00130                 ret->short_addr = nla_get_u16(attrs[IEEE802154_ATTR_SHORT_ADDR]);
00131 
00132                 free(buf);
00133                 nl_close(nl);
00134 #endif
00135         }
00136 }