From 6c2f91af92a660f42b86afdcedc7ac14005e048f Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 25 Sep 2023 10:03:27 -0700 Subject: [PATCH 1/2] Fix incorrect usage of TX_INFO signalling acked frames Before this change every CMD_FRAME coming from the kernel would be ack'ed locally through the TX_INFO command. This tells the client that the frame was acked in all cases, regardless if the server dropped it. The kernel does expect a TX_INFO for each CMD_FRAME but the ACK flag should only be set if the peer received the frame. If the server drops it the ACK flag should be unset. To fix this TX_INFO messages can be sent over the "air" just as frames are. Then clients can choose to include the ACK flag or not. This did require the server still sends all frames regardless if they were dropped, but a new boolean was added to signal to clients if the frame should be dropped. If so the client won't forward the frame but will still send a TX_INFO (with the ACK flag set appropriately). --- src/ckernelwifi.cc | 110 +++++++++++++++++++++++++++----------------- src/ckernelwifi.h | 5 +- src/cwifi.cc | 13 +++++- src/cwifi.h | 4 +- src/cwificlient.h | 9 ++-- src/cwifiserver.cc | 22 +++++---- src/cwifiserver.h | 4 +- src/vwifi-server.cc | 3 +- 8 files changed, 108 insertions(+), 62 deletions(-) diff --git a/src/ckernelwifi.cc b/src/ckernelwifi.cc index 2a2d1df..02dc469 100644 --- a/src/ckernelwifi.cc +++ b/src/ckernelwifi.cc @@ -44,24 +44,19 @@ void CKernelWifi::cout_mac_address(struct ether_addr *src) std::cout << addr; } -int CKernelWifi::send_tx_info_frame_nl(struct ether_addr *src, unsigned int flags, int signal, struct hwsim_tx_rate *tx_attempts, unsigned long cookie) +struct nl_msg *CKernelWifi::build_tx_info(struct ether_addr *src, unsigned int flags, int signal, struct hwsim_tx_rate *tx_attempts, unsigned long cookie) { struct nl_msg *msg = nullptr; msg = nlmsg_alloc(); - if (!msg) { - - std::cerr << "Error allocating new message MSG !" << std::endl ; - nlmsg_free(msg); - return 0; - } + if (!msg) + return nullptr; if (m_family_id < 0){ - std::cerr << __func__ << "m_family_id < 0" << std::endl ; nlmsg_free(msg); - return 0; + return nullptr; } genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, m_family_id, 0, NLM_F_REQUEST, HWSIM_CMD_TX_INFO_FRAME, VERSION_NR); @@ -77,10 +72,21 @@ int CKernelWifi::send_tx_info_frame_nl(struct ether_addr *src, unsigned int flag { std::cerr << "Error filling payload" << std::endl; nlmsg_free(msg); - return 0; + return NULL; } - //nl_send_auto_complete(_netlink_socket, msg); //deprecated + return msg; +} + +int CKernelWifi::send_tx_info_frame_nl(struct ether_addr *src, unsigned int flags, int signal, struct hwsim_tx_rate *tx_attempts, unsigned long cookie) +{ + struct nl_msg *msg = build_tx_info(src, flags, signal, tx_attempts, cookie); + + if (!msg) { + std::cerr << "Error allocating new message MSG !" << std::endl ; + nlmsg_free(msg); + return 0; + } if (nl_send_auto(_netlink_socket, msg) < 0) { @@ -137,31 +143,6 @@ int CKernelWifi::process_messages(struct nl_msg *msg) struct ether_addr macsrchwsim; memcpy(&macsrchwsim,src,sizeof(macsrchwsim)); // backup the original mac src - /* Let's flag this frame as ACK'ed */ - /* whatever that means... */ - unsigned int flags = nla_get_u32(attrs[HWSIM_ATTR_FLAGS]); - flags |= HWSIM_TX_STAT_ACK; - - /* this is the signal sent to the sender, not the receiver */ - int signal = -10; - - /* We get the tx_rates struct */ - struct hwsim_tx_rate* tx_rates = (struct hwsim_tx_rate *)nla_data(attrs[HWSIM_ATTR_TX_INFO]); - - u64 cookie = nla_get_u64(attrs[HWSIM_ATTR_COOKIE]); - - /* this has to be an ack the driver expects */ - /* what does the driver do with these values? can i remove them? */ - send_tx_info_frame_nl(src, flags, signal, tx_rates, cookie); - - /* - * no need to send a tx info frame indicating failure with a - * signal of 0 - that was done in the tx code i took this from - * if i check for ack messages than i could add a failure message - */ - - /* we are now done with our code addition which sends the ack */ - /* we get the attributes*/ char* data = (char *)nla_data(attrs[HWSIM_ATTR_FRAME]); unsigned int data_len = nla_len(attrs[HWSIM_ATTR_FRAME]); @@ -454,6 +435,7 @@ int CKernelWifi::send_cloned_frame_msg(struct ether_addr *dst, char *data, int d } void CKernelWifi::recv_from_server(){ + uint8_t dropped; if ( ! is_connected_to_server()) return ; @@ -467,7 +449,7 @@ void CKernelWifi::recv_from_server(){ return ; TPower power; - if( _RecvSignal(&power, &Buffer) == SOCKET_ERROR ) + if( _RecvSignal(&power, &dropped, &Buffer) == SOCKET_ERROR ) manage_server_crash(); int signal = power ; @@ -478,6 +460,33 @@ void CKernelWifi::recv_from_server(){ /* generic netlink header */ struct genlmsghdr* gnlh = (struct genlmsghdr*)nlmsg_data(nlh); + /* we get the attributes*/ + struct nlattr *attrs[HWSIM_ATTR_MAX + 1]; + genlmsg_parse(nlh, 0, attrs, HWSIM_ATTR_MAX, NULL); + + struct hwsim_tx_rate* tx_rates = (struct hwsim_tx_rate *)nla_data(attrs[HWSIM_ATTR_TX_INFO]); + u64 cookie = nla_get_u64(attrs[HWSIM_ATTR_COOKIE]); + unsigned int flags = nla_get_u32(attrs[HWSIM_ATTR_FLAGS]); + if (gnlh->cmd == HWSIM_CMD_TX_INFO_FRAME) { + // TX_INFO receved from server, send to kernel + std::vector &inets = _list_winterfaces.list_devices(); + + for (auto & inet : inets) + { + struct ether_addr macdsthwsim = inet.getMachwsim(); + + send_tx_info_frame_nl(&macdsthwsim, + flags, + (int)signal, + tx_rates, + cookie); + } + + delete &inets; + + return; + } + /* exit if the message does not contain frame data */ if (gnlh->cmd != HWSIM_CMD_FRAME) { @@ -485,9 +494,7 @@ void CKernelWifi::recv_from_server(){ return ; } - /* we get the attributes*/ - struct nlattr *attrs[HWSIM_ATTR_MAX + 1]; - genlmsg_parse(nlh, 0, attrs, HWSIM_ATTR_MAX, NULL); + /* we get frequence */ TFrequency freq; @@ -526,8 +533,27 @@ void CKernelWifi::recv_from_server(){ #endif /* copy mac dst address from frame */ - struct ether_addr framedst; - memcpy(&framedst, data + 4, ETH_ALEN); + struct ether_addr framesrc; + memcpy(&framesrc, data + 10, ETH_ALEN); + + if (!dropped) + flags |= HWSIM_TX_STAT_ACK; + + struct nl_msg *tx_info = build_tx_info(&framesrc, flags, + (int)signal, + tx_rates, + cookie); + struct nlmsghdr *hdr = nlmsg_hdr(tx_info); + + // Send TX_Info back to server + int value=_SendSignal(&power, (char*)hdr, hdr->nlmsg_len); + + nlmsg_free(tx_info); + if( value == SOCKET_ERROR ) + manage_server_crash(); + + if (dropped) + return; #ifdef _DEBUG std::cout << "frame dst: "; cout_mac_address(&framedst);std::cout<Send(descriptor, (char*)power, sizeof(TPower)); if( val <= 0 ) return val; + val=socket->Send(descriptor, (char*)dropped, sizeof(uint8_t)); + if( val <= 0 ) + return val; + // std::cout<<"send big data of size : "<Send(descriptor, buffer, sizeOfBuffer); } -ssize_t CWifi::RecvSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, CDynBuffer* buffer) +ssize_t CWifi::RecvSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, uint8_t *dropped, CDynBuffer* buffer) { int valread; @@ -82,6 +86,11 @@ ssize_t CWifi::RecvSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPo if ( valread <= 0 ) return valread; + // read dropped + valread = socket->Read(descriptor, (char*)dropped, sizeof(uint8_t)); + if ( valread <= 0 ) + return valread; + // read the signal // "nlmsg_len" (type "uint32_t") is the first attribut of the "struct nlmsghdr" in "libnl3/netlink/netlink-kernel.h" ssize_t sizeRead = socket->ReadEqualSize(descriptor, buffer, 0, sizeof(struct nlmsghdr)); diff --git a/src/cwifi.h b/src/cwifi.h index b7517f9..02c9327 100644 --- a/src/cwifi.h +++ b/src/cwifi.h @@ -18,8 +18,8 @@ class CWifi bool PacketIsLost(TPower signalLevel); - ssize_t SendSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, const char* buffer, int sizeOfBuffer); - ssize_t RecvSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, CDynBuffer* buffer); + ssize_t SendSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, uint8_t *dropped, const char* buffer, int sizeOfBuffer); + ssize_t RecvSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, uint8_t *dropped, CDynBuffer* buffer); }; #endif diff --git a/src/cwificlient.h b/src/cwificlient.h index 80a99ff..dbc7325 100644 --- a/src/cwificlient.h +++ b/src/cwificlient.h @@ -22,10 +22,13 @@ class CWifiClient : public CKernelWifi, public CWifi, public TypeCSocketClient } ssize_t _SendSignal(TPower* power, const char* buffer, int sizeOfBuffer) override - { return SendSignalWithSocket(this, this->GetDescriptor(), power, buffer, sizeOfBuffer); } + { + uint8_t dropped = 0; + return SendSignalWithSocket(this, this->GetDescriptor(), power, &dropped, buffer, sizeOfBuffer); + } - ssize_t _RecvSignal(TPower* power, CDynBuffer* buffer) override - { return RecvSignalWithSocket(this, this->GetDescriptor(), power, buffer); } + ssize_t _RecvSignal(TPower* power, uint8_t *dropped, CDynBuffer* buffer) override + { return RecvSignalWithSocket(this, this->GetDescriptor(), power, dropped, buffer); } void _Close() override { TypeCSocketClient::Close(); }; }; diff --git a/src/cwifiserver.cc b/src/cwifiserver.cc index 3ec459d..58f02ad 100644 --- a/src/cwifiserver.cc +++ b/src/cwifiserver.cc @@ -180,14 +180,14 @@ void CWifiServer::CloseAllClient() CloseClient(0); // we can Close the 0 because we use the shift } -ssize_t CWifiServer::SendSignal(TDescriptor descriptor, TPower* power, const char* buffer, int sizeOfBuffer) +ssize_t CWifiServer::SendSignal(TDescriptor descriptor, TPower* power, uint8_t *dropped, const char* buffer, int sizeOfBuffer) { - return SendSignalWithSocket(this, descriptor, power, buffer, sizeOfBuffer); + return SendSignalWithSocket(this, descriptor, power, dropped, buffer, sizeOfBuffer); } -ssize_t CWifiServer::RecvSignal(TDescriptor descriptor, TPower* power, CDynBuffer* buffer) +ssize_t CWifiServer::RecvSignal(TDescriptor descriptor, TPower* power, uint8_t *dropped, CDynBuffer* buffer) { - return RecvSignalWithSocket(this, descriptor, power, buffer); + return RecvSignalWithSocket(this, descriptor, power, dropped, buffer); } void CWifiServer::SendAllOtherClients(TIndex index,TPower power, const char* data, ssize_t sizeOfData) @@ -202,30 +202,34 @@ void CWifiServer::SendAllOtherClients(TIndex index,TPower power, const char* dat { TFrequency frequency=GetFrequency((struct nlmsghdr*)data); TPower signalLevel=BoundedPower(power-Attenuation(coo.DistanceWith((*InfoWifis)[i]),frequency)); + uint8_t dropped = CanLostPackets && PacketIsLost(signalLevel); - if( ! CanLostPackets || ! PacketIsLost(signalLevel) ) - if( SendSignal((*InfoSockets)[i].GetDescriptor(), &signalLevel, data, sizeOfData) < 0 ) - (*InfoSockets)[i].DisableIt(); + if( SendSignal((*InfoSockets)[i].GetDescriptor(), &signalLevel, &dropped, data, sizeOfData) < 0 ) + (*InfoSockets)[i].DisableIt(); } } } void CWifiServer::SendAllOtherClientsWithoutLoss(TIndex index, TPower power, const char* data, ssize_t sizeOfData) { + uint8_t dropped = 0; + for (TIndex i = 0; i < GetNumberClient(); i++) { if( i != index ) if( IsEnable(i) ) - if( SendSignal((*InfoSockets)[i].GetDescriptor(), &power, data, sizeOfData) < 0 ) + if( SendSignal((*InfoSockets)[i].GetDescriptor(), &power, &dropped, data, sizeOfData) < 0 ) (*InfoSockets)[i].DisableIt(); } } void CWifiServer::SendAllClientsWithoutLoss(TPower power, const char* data, ssize_t sizeOfData) { + uint8_t dropped = 0; + for (TIndex i = 0; i < GetNumberClient(); i++) if( IsEnable(i) ) - if( SendSignal((*InfoSockets)[i].GetDescriptor(), &power, data, sizeOfData) < 0 ) + if( SendSignal((*InfoSockets)[i].GetDescriptor(), &power, &dropped, data, sizeOfData) < 0 ) (*InfoSockets)[i].DisableIt(); } diff --git a/src/cwifiserver.h b/src/cwifiserver.h index 40d45b1..d303237 100644 --- a/src/cwifiserver.h +++ b/src/cwifiserver.h @@ -44,9 +44,9 @@ class CWifiServer : public CSocketServer, public CWifi void CloseAllClient(); - ssize_t SendSignal(TDescriptor descriptor, TPower* power, const char* buffer, int sizeOfBuffer); + ssize_t SendSignal(TDescriptor descriptor, TPower* power, uint8_t *dropped, const char* buffer, int sizeOfBuffer); - ssize_t RecvSignal(TDescriptor descriptor, TPower* power, CDynBuffer* buffer); + ssize_t RecvSignal(TDescriptor descriptor, TPower* power, uint8_t *dropped, CDynBuffer* buffer); void SendAllOtherClients(TIndex index,TPower power, const char* data, ssize_t sizeOfData); diff --git a/src/vwifi-server.cc b/src/vwifi-server.cc index 242b089..67e1490 100644 --- a/src/vwifi-server.cc +++ b/src/vwifi-server.cc @@ -40,6 +40,7 @@ void ForwardData(bool srcIsSpy, CWifiServer* src, CWifiServer* otherDst) { int valread; TPower power; + uint8_t dropped; for ( TIndex i = 0 ; i < src->GetNumberClient() ; ) { @@ -57,7 +58,7 @@ void ForwardData(bool srcIsSpy, CWifiServer* src, CWifiServer* otherDst) //Check if it was for closing , and also read the //incoming message - valread=src->RecvSignal(socket,&power,&Buffer); + valread=src->RecvSignal(socket,&power,&dropped,&Buffer); if( valread <=0 ) { RemoveClient(src, srcIsSpy , i, socket); From 72463c2dd210cf83694929d311b077104b861384 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 2 Oct 2023 05:11:29 -0700 Subject: [PATCH 2/2] TESTING --- src/ckernelwifi.cc | 15 ++++++++++++--- src/csocket.cc | 4 +++- src/cwifi.cc | 18 +++++++++++++----- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/ckernelwifi.cc b/src/ckernelwifi.cc index 02dc469..cf83af3 100644 --- a/src/ckernelwifi.cc +++ b/src/ckernelwifi.cc @@ -179,8 +179,10 @@ int CKernelWifi::process_messages(struct nl_msg *msg) } int value=_SendSignal(&power, (char*)nlh, msg_len); - if( value == SOCKET_ERROR ) + if( value == SOCKET_ERROR ) { + printf("Error sending to server\n"); manage_server_crash(); + } // Send also on the others interfaces on the same VM : // -------------------> @@ -449,8 +451,10 @@ void CKernelWifi::recv_from_server(){ return ; TPower power; - if( _RecvSignal(&power, &dropped, &Buffer) == SOCKET_ERROR ) + if( _RecvSignal(&power, &dropped, &Buffer) == SOCKET_ERROR ) { + printf("Error receiving from server\n"); manage_server_crash(); + } int signal = power ; @@ -539,6 +543,7 @@ void CKernelWifi::recv_from_server(){ if (!dropped) flags |= HWSIM_TX_STAT_ACK; +#if 0 struct nl_msg *tx_info = build_tx_info(&framesrc, flags, (int)signal, tx_rates, @@ -549,8 +554,11 @@ void CKernelWifi::recv_from_server(){ int value=_SendSignal(&power, (char*)hdr, hdr->nlmsg_len); nlmsg_free(tx_info); - if( value == SOCKET_ERROR ) + if( value == SOCKET_ERROR ) { + printf("Error sending tx info to server\n"); manage_server_crash(); + } +#endif if (dropped) return; @@ -926,6 +934,7 @@ bool CKernelWifi::is_connected_to_server(){ void CKernelWifi::manage_server_crash(){ + printf("MANAGE SERVER CRASH"); connected_to_server(false) ; } diff --git a/src/csocket.cc b/src/csocket.cc index 423662c..b40fc58 100644 --- a/src/csocket.cc +++ b/src/csocket.cc @@ -53,8 +53,10 @@ ssize_t CSocket::SendBigData(TDescriptor descriptor, const char* data, TMinimalS ssize_t CSocket::Read(TDescriptor descriptor, char* data, ssize_t sizeOfData) { ssize_t ret = recv(descriptor , data, sizeOfData, 0); - if ( ret <= 0 ) + if ( ret <= 0 ) { + printf("Recv failed with %ld\n", errno); return SOCKET_ERROR ; + } return ret; } diff --git a/src/cwifi.cc b/src/cwifi.cc index 02775b7..bb2d780 100644 --- a/src/cwifi.cc +++ b/src/cwifi.cc @@ -15,7 +15,7 @@ const double ConstanteC=92.45; const TFrequency DEFAULT_FREQUENCY=2412; // Hz -const int MTU=1640; // Maximum Transmission Unit : 1640 is an experimental value +const int MTU=4096; // Maximum Transmission Unit : 1640 is an experimental value TFrequency CWifi::GetFrequency(struct nlmsghdr* nlh) { @@ -83,24 +83,32 @@ ssize_t CWifi::RecvSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPo // read the power valread = socket->Read(descriptor, (char*)power, sizeof(TPower)); - if ( valread <= 0 ) + if ( valread <= 0 ) { + printf("cannot read power %d\n", valread); return valread; + } // read dropped valread = socket->Read(descriptor, (char*)dropped, sizeof(uint8_t)); - if ( valread <= 0 ) + if ( valread <= 0 ) { + printf("cannot read dropped %d\n", valread); return valread; + } // read the signal // "nlmsg_len" (type "uint32_t") is the first attribut of the "struct nlmsghdr" in "libnl3/netlink/netlink-kernel.h" ssize_t sizeRead = socket->ReadEqualSize(descriptor, buffer, 0, sizeof(struct nlmsghdr)); - if( sizeRead == SOCKET_ERROR ) + if( sizeRead == SOCKET_ERROR ) { + printf("Cannot read nlmsg_len\n"); return SOCKET_ERROR; + } int sizeTotal=((struct nlmsghdr *)(buffer->GetBuffer()))->nlmsg_len; - if( sizeTotal > MTU ) // to avoid that a error packet overfulls the memory + if( sizeTotal > MTU ) { // to avoid that a error packet overfulls the memory + printf("Size greater than MTU %d\n", sizeTotal); return SOCKET_ERROR; + } return socket->ReadEqualSize(descriptor, buffer, sizeRead, sizeTotal); }