I am creating a windows UDP tunnel using wintun driver. I have written a code to receive data from the server and send it to the windows tunnel using the function send_packet and allocatesendpacket. The error I get is that I can read data only as bytes from the UDP server but it causes a mismatch when I pass it to the send_packet function. The error is as follows:
mismatched types
expected struct `wintun::Packet`, found `&[u8]`
Code for send_packet and allocatesendpacket
https://github.com/nulldotblack/wintun/blob/main/src/session.rs
Code for packet struct data type
https://github.com/nulldotblack/wintun/blob/main/src/packet.rs
Link for other dependencies
https://github.com/nulldotblack/wintun
How do I convert the bytes (variable buffer below) to Packet struct data type?. The error of mismatch occurs when I declare the value of a variable packet with the value of the received buffer variable, so that packet variable can be sent to tunnel.
My code:
let socket = UdpSocket::bind("6.0.0.1:8000") //create client socket object with ip and port
.expect("Could not bind client socket");
socket.connect("6.0.0.10:8888") //SERVER IP /PORT
let writer_session = session.clone();
let writer =
std::thread::spawn(move || {
info!("Starting writer");
while RUNNING.load(Ordering::Relaxed) {
let mut buffer = [0u8; 20000];
socket.recv_from(&mut buffer) //get message from server
.expect("Could not read into buffer");
let leng1 = buffer.len();
let mut packet = writer_session.allocate_send_packet(leng1.try_into().unwrap()).unwrap();
packet = &buffer[0..leng1]; //ERROR occurs here
writer_session.send_packet(packet);
}
});
You have two errors the first caused by trying to assign a slice to packet directly which is solved by copying the buffer into packet instead:
packet.bytes_mut().copy_from_slice(&buffer);
The second is that you are not using the length returned by recv_from but instead using the length of the whole buffer which may lead to reading past the end of the read data although memory address is valid. You should do this instead:
let mut buffer = [0u8; 20000];
let (leng1, src_addr) = socket.recv_from(&mut buffer) //get message from server
.expect("Could not read into buffer");
let buffer = &mut buffer[..leng1];
To copy the contents of buffer into packet, you can use slice::copy_from_slice:
packet.bytes_mut().copy_from_slice(&buffer);
Related
I have a small program that looks like the following:
let sock = UdpSocket::bind("0.0.0.0:1024").unwrap();
let mut buf = [0; 10000];
loop {
let (len, src) = sock.recv_from(&mut buf).unwrap();
let buf = &mut buf[..len];
// do stuff
}
Let's say someone sends data to example.com:1024, is there any way to know they sent the data to example.com and not just the source IP address?
I'm testing to connect and send a simple message to a host and I've used this guide http://studyswift.blogspot.com/2016/01/connect-mac-iphone-to-simple-python.html.
So far I'm able to connect to the server and when I tried to write on the output stream .
let data : NSData = "hello".data(using: String.Encoding.utf8)! as NSData
outStream?.write(UnsafePointer<UInt8>(data.bytes), maxLength: data.length)
I got error on write(UnsafePointer(data.bytes), ...
Cannot convert value of type 'UnsafeRawPointer' to expected argument type 'RawPointer'
I'm playing around with Tokio and Rust and as an example, I am trying to write a simple UDP proxy that will just accept UDP packets on one socket and send it out to multiple other destinations. However, I stumble over the situation that I need to send the received packet to multiple addresses and am not sure how to do that in a idiomatic way.
Code I have this far:
extern crate bytes;
extern crate futures;
use std::net::SocketAddr;
use tokio::codec::BytesCodec;
use tokio::net::{UdpFramed, UdpSocket};
use tokio::prelude::*;
fn main() {
let listen_address = "127.0.0.1:4711".parse::<SocketAddr>().unwrap();
let forwarder = {
let socket = UdpSocket::bind(&listen_address).unwrap();
let peers = vec![
"192.168.1.136:4711".parse::<SocketAddr>().unwrap(),
"192.168.1.136:4712".parse::<SocketAddr>().unwrap(),
];
UdpFramed::new(UdpSocket::bind(&listen_address).unwrap(), BytesCodec::new()).for_each(
move |(bytes, _from)| {
// These are the problematic lines
for peer in peers.iter() {
socket.send_dgram(&bytes, &peer);
}
Ok(())
},
)
};
tokio::run({
forwarder
.map_err(|err| println!("Error: {}", err))
.map(|_| ())
});
}
The problematic lines are trying to send the received packet to multiple other addresses using a newly bound socket.
The existing examples all forward packets to single destinations, or internally use mpsc channels to communicate between internal tasks. I do not think that this is necessary and that it should be possible to do without having to spawn more than one task per listening socket.
Update: Thanks to #Ömer-erden I got this code that works.
extern crate bytes;
extern crate futures;
use std::net::SocketAddr;
use tokio::codec::BytesCodec;
use tokio::net::{UdpFramed, UdpSocket};
use tokio::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let listen_address = "0.0.0.0:4711".parse::<SocketAddr>()?;
let socket = UdpSocket::bind(&listen_address)?;
let peers: Vec<SocketAddr> = vec!["192.168.1.136:8080".parse()?, "192.168.1.136:8081".parse()?];
let (mut writer, reader) = UdpFramed::new(socket, BytesCodec::new()).split();
let forwarder = reader.for_each(move |(bytes, _from)| {
for peer in peers.iter() {
writer.start_send((bytes.clone().into(), peer.clone()))?;
}
writer.poll_complete()?;
Ok(())
});
tokio::run({
forwarder
.map_err(|err| println!("Error: {}", err))
.map(|_| ())
});
Ok(())
}
Note that:
It is not necessary to call poll_completion for each start_send: it just need to be called after all start_send has been dispatched.
For some reason, the content of the peer is gutted between calls (but there is no compiler error), generating an Error 22 (which is usually because a bad address is given to sendto(2)).
Looking in a debugger, it is quite clear that the second time, the peer address is pointing to invalid memory. I opted to clone the peer instead.
I removed the calls to unwrap() and propagate the Result upwards instead.
Your code has a logical mistake: you are trying to bind the same address twice, as sender and receiver respectively. Instead, you can use a stream and sink. UdpFramed has the functionality to provide that, please see Sink:
A Sink is a value into which other values can be sent, asynchronously.
let listen_address = "127.0.0.1:4711".parse::<SocketAddr>().unwrap();
let forwarder = {
let (mut socket_sink, socket_stream) =
UdpFramed::new(UdpSocket::bind(&listen_address).unwrap(), BytesCodec::new()).split();
let peers = vec![
"192.168.1.136:4711".parse::<SocketAddr>().unwrap(),
"192.168.1.136:4712".parse::<SocketAddr>().unwrap(),
];
socket_stream.for_each(move |(bytes, _from)| {
for peer in peers.iter() {
socket_sink.start_send((bytes.clone().into(), *peer));
socket_sink.poll_complete();
}
Ok(())
})
};
tokio::run({
forwarder
.map_err(|err| println!("Error: {}", err))
.map(|_| ())
});
I have a module where I have to discover by sending a packets to the 255 IP addresses.
eg. Connected IP : 192.188.2.1 then I have to send a packet changing the last value i.e.
var HOST = "192.188.2.1"
var arr = HOST.components(separatedBy: ".")
for i in 1 ..< 254
{
dispatchGroup.enter()
time += 0.005
DispatchQueue.main.asyncAfter(deadline: .now() + time) {
let obj = LPScanPacket()
arr[3] = "\(i)"
let str = arr.joined(separator: ".")
SenderWrapper.sendLPPacket(lpPacket: obj, HOST: str)
dispatchGroup.leave()
}
}
dispatchGroup.notify(queue: .main) {
print("Completed sending 👍")
}
But on sending this many packet it shows me error within udpSocketDidClose delegate method
Error Domain=NSPOSIXErrorDomain Code=65 "No route to host" UserInfo={NSLocalizedDescription=No route to host, NSLocalizedFailureReason=Error in send() function.}
Firstly why do I get this error, is there any alternative way I can achieve this result.
EDIT :
Try running this code, I am trying to get response from the device connected to the same router. To find the device IP I am using the above code. But the socket closes in between sometimes it works and sometime it doesn't I am not able to find the solution why it closes.
Thanks
A broadcast message is sent to all hosts on a network or subnetwork and is created by setting the node part of the IP address to all 1’s.
The error message you received is related to the fact, that broadcasts messages do not go through routers.
To be able to broadcast a datagram, the underlying socket must be in the broadcast mode. Run man setsockopt in your terminal for further reference.
I'm working on a solution to send commands to a point of sale receipt printer and having some issues getting the command format right. Ive got a socket open to the device and thats working, because incorrect commands are printed. What the SPEC calls for in this command is to send the following:
1B 07 or in decimal 27 7. Which in ASCII is ESC_KEY BEL. The only example the spec shows is for .NET:
MSComm1.Output = Chr$(&H1B) & Chr$(&H07)
What I've been trying:
// Socket is open previously using CFStreamCreatePairWithSocketToHost.
var cmd = "27 07"
if let dataString = "\(cmd)\r".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false), let oStream = self.outputStream {
self.outputData.append(dataString)
if oStream.hasSpaceAvailable {
oStream.write(UnsafePointer((self.outputData.first! as NSData).bytes), maxLength: self.outputData.first!length)
}
}
The data is getting there, but I think the format of the message is wrong. Any help would be appreciated.
Just create a byte (aka UInt8) array with the data that you want
to send, and pass that directly to the write() method of NSOutputStream:
let cmd: [UInt8] = [0x1B, 0x07]
oStream.write(cmd, maxLength: cmd.count)
Note that you send bytes to the output stream, not hex data.
It makes not difference at all if you create the array with hexadecimal
integer literals as above, or as
let cmd: [UInt8] = [27, 7]
the data is exactly the same.