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