|
IBR-DTNSuite 0.6
|
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 }