Trying to broadcast message with LUA on raspberry - sockets

I am trying to broadcast a simple message from my raspberry to the entire network on port 6000 with the following simple code but it doesn't seem to allow the address 192.168.1.255 any other address will work.
local socket = require("socket")
local udp = assert(socket.udp())
udp:setoption('broadcast', true)
udp:settimeout(3)
assert(udp:sendto("Howdy\n", '192.168.1.255', 6000))
The IP on the PI is 192.168.1.127 for testing purposes but later on will be 192.168.1.1
Assert always gives me permission denied with the code above.

Related

UDP packets over NB-IoT

I'm trying to send UDP packets over the t-mobile NB-IoT network using AT-commands on a SIM7020E chip. I used the product wiki as reference. The starter version of the sim card I have doesn't support TCP, but I'm planning on using that later if I can succesfully communicate using UDP.
I created a UDP-socket on a Raspberry Pi using "nc -u -l 9999". I set an A-record on my hosting provider to refer dev.mydomain.com to the IP address of the Raspberry Pi. I verified the portforward and A-record settings by sending UDP packets from my laptop on another network using "nc -u dev.mydomain.com 9999" and typing some teststrings, so this all works.
On the 4G chip I use the following AT-commands:
// Check network
AT+CSQ
+CSQ: 21,0
AT+CGREG?
+CGREG: 0,5
AT+COPS?
+COPS: 0,2,"20416",9
AT+CGCONTRDP
+CGCONTRDP: 1,5,"iot.t-mobile.nl","x.x.x.x.255.255.255.0" <-- crossed out my ip
// Create UDP socket
AT+CSOC=1,2,1
+CSOC: 0
// Connect socket 0 to the listening port on the Raspberry Pi
AT+CSOCON=0,9999,"dev.mydomain.com"
OK
// Send "test"
AT+CSOSEND=0,0,"test"
At this point I expect to see "test" appear in the command line on the Raspberry Pi, but nothing happens. In the T-mobile portal it shows a PDP-context is successfully activated.
Also, setting the APN manually with AT*MCGDEFCONT="IP","iot.t-mobile.nl","username","password" doesn't work.
Did you work this out Hans? I was plodding along with a SIM7020E following https://www.waveshare.com/wiki/Pico-SIM7020E-NB-IoT code examples. Was successfully sending HTTP GETS to a server (without having to use micropython's wretched urequests lib) via the CHTTPCREATE/CHTTPCON/CHTTPSEND AT cmds, that seem to be be able to send packets over LTE to a server without specifying TCP/UDP etc or using a socket. Maybe give it a try?
Sadly I got the bright idea of trying an 'AT+POWD=1' cmd over the uart (was supposed to power the 7020E down) & now the module now does nothing but echo AT cmds (still auto connects to the LTE network & slow flashes the network led, just won't do anything else.) Real shame, nice little module otherwise.

porting Socket programming from Ubuntu to Windows

I have the following connection in Ubuntu
Linux PC -> Switch (PoE) -> DUT
with the following ip configurations:
Ethernet adaptor Statically assigned
BASE IP (ipv4): 10.0.0.1
subnet : 255.255.255.0
gateway : 10.0.0.0
eth0 network address : 10.0.0.3
This setup enables me to send and receive UDP packets.Works perfectly fine in Ubuntu.
Now in Windows, I have made relevant changes to the python code of the codebase, but the code gets stuck waiting for UDP packets from the Hardware. I have statically assigned the same values as in Ubuntu. I am very new to networking..
(1) I have ensured Firewall is allowing UDP packets
(2) I have made the same IP address,subnet,gateway settings configurations.
Where am I going wrong?
It's impossible to say exactly what goes wrong based on this information.
I'd suggest trying Wireshark from https://www.wireshark.org/.
With that running on your windows PC, you can see if your packets are being sent out or not, and you can also see if the device responds or not. That way you can determine if the problem is in sending or receiving the packets.

Finding out local IP address using a UDP socket on a system with no Internet access

I need to find out the local IP address on a very old platform which doesn't have getifaddrs(). Lots of people recommend to do this by creating a UDP socket, connect() it to a destination IP and then use getsockname() to find out the local IP address (see here)
Is there a way to make this work on systems that don't have Internet access? AFAIU, for UDP sockets connect() just sets the default destination address for the socket without actually establishing any connection. So can I just use some random destination IP with connect() because it doesn't connect immediately for UDP sockets anyway? I.e. can I just pass 8.8.8.8 as a dummy IP to connect() and getsockname() will still allow me to get the local IP address even if there is no Internet connection?

What does it mean to bind() a socket to any address other than localhost?

I don't understand what it means to bind a socket to any address other than 127.0.0.1 (or ::1, etc.).
Am I not -- by definition -- binding the socket to a port on my own machine.. which is localhost?
What sense does it make to bind or listen to another machine or IP address's port?
Conceptually, it just doesn't make sense to me!
(This has proven surprisingly hard to Google... possibly because I'm not Googling the right terms.)
Binding of a socket is done to address and port in order to receive data on this socket (most cases) or to use this address/port as the source of the data when sending data (for example used with data connections in FTP server).
Usually there are several interfaces on a specific machine, i.e. the pseudo-interface loopback where the machine can reach itself, ethernet, WLAN, VPN... . Each of these interfaces can have multiple IP addresses assigned. For example, loopback usually has 127.0.0.1 and with IPv6 also ::1, but you can assign others too. Ethernet or WLAN have the IP addresses on the local network, i.e. 172.16.0.34 or whatever.
If you bind a socket for receiving data to a specific address you can only receive data sent to this specific IP address. For example, if you bind to 127.0.0.1 you will be able to receive data from your own system but not from some other system on the local network, because they cannot send data to your 127.0.0.1: for one any data to 127.0.0.1 will be sent to their own 127.0.0.1 and second your 127.0.0.1 is an address on your internal loopback interface which is not reachable from outside.
You can also bind a socket to a catch-all address like 0.0.0.0 (Ipv4) and :: (Ipv6). In this case it is not bound to a specific IP address but will be able to receive data send to any IP address of the machine.

What does it mean to bind a multicast (UDP) socket?

I am using multicast UDP between hosts that have multiple network interfaces.
I am using boost::asio, and am confused by the 2 operations receivers have to make: bind, then join-group.
Why do you need to specify the local address of an interface, during bind, when you do that with every multicast group that you join?
The sister-question regards the multicast port: Since during sending, you send to a multicast address & port, why, during subscription to a multicast group, you only specify the address, not the port - the port being specified in the confusing call to bind.
Note: the "join-group" is a wrapper over setsockopt(IP_ADD_MEMBERSHIP), which as documented, may be called multiple times on the same socket to subscribe to different groups (over different networks?). It would therefore make perfect sense to ditch the bind call and specify the port every time I subscribe to a group.
From what I see, always binding to "0.0.0.0" and specifying the interface address when joining the group, works very well. Confused.
To bind a UDP socket when receiving multicast means to specify an address and port from which to receive data (NOT a local interface, as is the case for TCP acceptor bind). The address specified in this case has a filtering role, i.e. the socket will only receive datagrams sent to that multicast address & port, no matter what groups are subsequently joined by the socket. This explains why when binding to INADDR_ANY (0.0.0.0) I received datagrams sent to my multicast group, whereas when binding to any of the local interfaces I did not receive anything, even though the datagrams were being sent on the network to which that interface corresponded.
Quoting from UNIX® Network Programming Volume 1, Third Edition: The Sockets Networking API by W.R Stevens.
21.10. Sending and Receiving
[...] We want the receiving socket to bind the multicast group and
port, say 239.255.1.2 port 8888. (Recall that we could just bind the
wildcard IP address and port 8888, but binding the multicast address
prevents the socket from receiving any other datagrams that might
arrive destined for port 8888.) We then want the receiving socket to
join the multicast group. The sending socket will send datagrams to
this same multicast address and port, say 239.255.1.2 port 8888.
The "bind" operation is basically saying, "use this local UDP port for sending and receiving data. In other words, it allocates that UDP port for exclusive use for your application. (Same holds true for TCP sockets).
When you bind to "0.0.0.0" (INADDR_ANY), you are basically telling the TCP/IP layer to use all available adapters for listening and to choose the best adapter for sending. This is standard practice for most socket code. The only time you wouldn't specify 0 for the IP address is when you want to send/receive on a specific network adapter.
Similarly if you specify a port value of 0 during bind, the OS will assign a randomly available port number for that socket. So I would expect for UDP multicast, you bind to INADDR_ANY on a specific port number where multicast traffic is expected to be sent to.
The "join multicast group" operation (IP_ADD_MEMBERSHIP) is needed because it basically tells your network adapter to listen not only for ethernet frames where the destination MAC address is your own, it also tells the ethernet adapter (NIC) to listen for IP multicast traffic as well for the corresponding multicast ethernet address. Each multicast IP maps to a multicast ethernet address. When you use a socket to send to a specific multicast IP, the destination MAC address on the ethernet frame is set to the corresponding multicast MAC address for the multicast IP. When you join a multicast group, you are configuring the NIC to listen for traffic sent to that same MAC address (in addition to its own).
Without the hardware support, multicast wouldn't be any more efficient than plain broadcast IP messages. The join operation also tells your router/gateway to forward multicast traffic from other networks. (Anyone remember MBONE?)
If you join a multicast group, all the multicast traffic for all ports on that IP address will be received by the NIC. Only the traffic destined for your binded listening port will get passed up the TCP/IP stack to your app. In regards to why ports are specified during a multicast subscription - it's because multicast IP is just that - IP only. "ports" are a property of the upper protocols (UDP and TCP).
You can read more about how multicast IP addresses map to multicast ethernet addresses at various sites. The Wikipedia article is about as good as it gets:
The IANA owns the OUI MAC address 01:00:5e, therefore multicast
packets are delivered by using the Ethernet MAC address range
01:00:5e:00:00:00 - 01:00:5e:7f:ff:ff. This is 23 bits of available
address space. The first octet (01) includes the broadcast/multicast
bit. The lower 23 bits of the 28-bit multicast IP address are mapped
into the 23 bits of available Ethernet address space.
Correction for What does it mean to bind a multicast (udp) socket? as long as it partially true at the following quote:
The "bind" operation is basically saying, "use this local UDP port for sending and receiving data. In other words, it allocates that UDP port for exclusive use for your application
There is one exception. Multiple applications can share the same port for listening (usually it has practical value for multicast datagrams), if the SO_REUSEADDR option applied. For example
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // create UDP socket somehow
...
int set_option_on = 1;
// it is important to do "reuse address" before bind, not after
int res = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &set_option_on,
sizeof(set_option_on));
res = bind(sock, src_addr, len);
If several processes did such "reuse binding", then every UDP datagram received on that shared port will be delivered to each of the processes (providing natural joint with multicasts traffic).
Here are further details regarding what happens in a few cases:
attempt of any bind ("exclusive" or "reuse") to free port will be successful
attempt to "exclusive binding" will fail if the port is already "reuse-binded"
attempt to "reuse binding" will fail if some process keeps "exclusive binding"
It is also very important to distinguish a SENDING multicast socket from a RECEIVING multicast socket.
I agree with all the answers above regarding RECEIVING multicast sockets.
The OP noted that binding a RECEIVING socket to an interface did not help.
However, it is necessary to bind a multicast SENDING socket to an interface.
For a SENDING multicast socket on a multi-homed server, it is very important to create a separate socket for each interface you want to send to. A bound SENDING socket should be created for each interface.
// This is a fix for that bug that causes Servers to pop offline/online.
// Servers will intermittently pop offline/online for 10 seconds or so.
// The bug only happens if the machine had a DHCP gateway, and the gateway is no longer accessible.
// After several minutes, the route to the DHCP gateway may timeout, at which
// point the pingponging stops.
// You need 3 machines, Client machine, server A, and server B
// Client has both ethernets connected, and both ethernets receiving CITP pings (machine A pinging to en0, machine B pinging to en1)
// Now turn off the ping from machine B (en1), but leave the network connected.
// You will notice that the machine transmitting on the interface with
// the DHCP gateway will fail sendto() with errno 'No route to host'
if ( theErr == 0 )
{
// inspired by 'ping -b' option in man page:
// -b boundif
// Bind the socket to interface boundif for sending.
struct sockaddr_in bindInterfaceAddr;
bzero(&bindInterfaceAddr, sizeof(bindInterfaceAddr));
bindInterfaceAddr.sin_len = sizeof(bindInterfaceAddr);
bindInterfaceAddr.sin_family = AF_INET;
bindInterfaceAddr.sin_addr.s_addr = htonl(interfaceipaddr);
bindInterfaceAddr.sin_port = 0; // Allow the kernel to choose a random port number by passing in 0 for the port.
theErr = bind(mSendSocketID, (struct sockaddr *)&bindInterfaceAddr, sizeof(bindInterfaceAddr));
struct sockaddr_in serverAddress;
int namelen = sizeof(serverAddress);
if (getsockname(mSendSocketID, (struct sockaddr *)&serverAddress, (socklen_t *)&namelen) < 0) {
DLogErr(#"ERROR Publishing service... getsockname err");
}
else
{
DLog( #"socket %d bind, %# port %d", mSendSocketID, [NSString stringFromIPAddress:htonl(serverAddress.sin_addr.s_addr)], htons(serverAddress.sin_port) );
}
Without this fix, multicast sending will intermittently get sendto() errno 'No route to host'.
If anyone can shed light on why unplugging a DHCP gateway causes Mac OS X multicast SENDING sockets to get confused, I would love to hear it.