In older versions of Mac OS X, wildcard binding works like described here:
Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems?
Multicast Addresses
The meaning of SO_REUSEADDR changes for multicast addresses as it allows multiple sockets to be bound to exactly the same combination of source multicast address and port. In other words, for multicast addresses SO_REUSEADDR behaves exactly as SO_REUSEPORT for unicast addresses. Actually the code treats SO_REUSEADDR and SO_REUSEPORT identically for multicast addresses, that means you could say that SO_REUSEADDR implies SO_REUSEPORT for all multicast addresses and the other way round.
and
MacOS X
At its very core, MacOS X is simply a BSD-style UNIX, based on a rather late fork of the BSD code, which was even synchronized with FreeBSD 5 for the Mac OS 10.3 release. That's why MacOS X offers the same options as BSD and they also behave the same way as in BSD.
but in 10.10.5 I discovered a change when I was testing my networking library.
Two unbound (wildcard) UDP sockets can not share the same port anymore (errno=EADDRINUSE), even when SO_REUSEADDR is set.
SO_REUSEPORT has to be set on both two, which is a mystery to me.
It is reproducible with this simple test code:
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
int main() {
for(int p = 0; p < 4; ++p) {
printf("Flags set: ");
if(p&1) printf("SO_REUSEADDR ");
if(p&2) printf("SO_REUSEPORT");
printf("\n");
int handles[2];
bool success = true;
for(int i = 0; i < sizeof(handles)/sizeof(int); ++i) {
handles[i] = socket(AF_INET, SOCK_DGRAM, 0);
int flag = 1;
if((p&1) && setsockopt(handles[i], SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) == -1) {
printf("Setsockopt %d, SO_REUSEADDR failed with errno\n", i, errno);
success = false;
break;
}
if((p&2) && setsockopt(handles[i], SOL_SOCKET, SO_REUSEPORT, &flag, sizeof(flag)) == -1) {
printf("Setsockopt %d, SO_REUSEPORT failed with errno\n", i, errno);
success = false;
break;
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = 2000; // does not matter as long as it is currently free
addr.sin_addr.s_addr = 0; // wildcard address
if(bind(handles[i], (struct sockaddr*)&addr, sizeof(addr)) == -1) {
printf("Bind %d failed with errno %d\n", i, errno);
success = false;
break;
}
}
if(success)
printf("Alright\n");
for(int i = 0; i < sizeof(handles)/sizeof(int); ++i)
close(handles[i]);
printf("\n");
}
return 0;
}
Which outputs:
Flags set:
Bind 1 failed with errno 48
Flags set: SO_REUSEADDR
Bind 1 failed with errno 48
Flags set: SO_REUSEPORT
Alright
Flags set: SO_REUSEADDR SO_REUSEPORT
Alright
In older versions of Mac OS X, wildcard binding works like described
here:
Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do
they mean the same across all major operating systems?
Multicast Addresses
…
The description you quote is for Multicast Addresses. Your test code doesn't use a multicast address. Hence, a different description applies (from the same source):
SO_REUSEPORT
SO_REUSEPORT is what most people would expect SO_REUSEADDR to be.
Basically, SO_REUSEPORT allows you to bind an arbitrary number of
sockets to exactly the same source address and port as long as
all prior bound sockets also had SO_REUSEPORT set before they were bound. …
Your test code confirms exactly this.
What a hack! It just has bee incurred. Still the problem exists with using SO_REUSEADDR instead of SO_REUSEPORT. I think the latter works most of *nix based OSes. But once you get caught into the nest, shaking off the situation would not be easy, if you didn't read the answer before especially on Mac OS.
You know your port number of course, while using sockets. Open terminal, execute the following command.
lsof -i:<Port used by you>
then it brings you a line including PID.
Just kill it with -9, then change your code by SO_REUSEPORT. That's all!
Related
Getting address family can be done with getsockopt() with option SO_DOMAIN (see socket options) on linux.
(read Get address family from socket. Linux)
How do I do the same thing on OS X ?
When using the code that worked on linux on OS X I get
error: use of undeclared identifier 'SO_DOMAIN'
int err = getsockopt(sock, SOL_SOCKET, SO_DOMAIN, &addr_family, &len);
^
so not SO_DOMAIN ?
You can find this out by calling proc_pidfdinfo() on your own PID, and requesting PROC_PIDFDSOCKETINFO:
#include <libproc.h>
#include <stdbool.h>
#include <unistd.h>
bool socketDomainGet(int socket, int *domain) {
struct socket_fdinfo info;
int rc = proc_pidfdinfo(getpid(), socket, PROC_PIDFDSOCKETINFO, &info, sizeof info);
if (rc <= 0) return false;
*domain = info.psi.soi_family;
return true;
}
Unlike getsockname(), this works even if the socket hasn't been bound yet. Note as well as the domain (psi.soi_family), it also can tell you the type (psi.soi_type) and the protocol (psi.soi_protocol).
Keep in mind though this warning Apple gives in the libproc.h header:
/*
* This header file contains private interfaces to obtain process information.
* These interfaces are subject to change in future releases.
*/
They probably aren't going to break this, but the risk is higher than for more official APIs.
use SO_TYPE instead of SO_DOMAIN
in OS X man GETSOCKOPT(2) says
SO_TYPE get the type of the socket (get only)
I'm having trouble reading the Raspberry Pi 4 system timer.
My understanding is that the LO 32 bits should be at address 0x7e003004.
My reads always return -1.
Here's how I am trying:
int fd;
unsigned char* start;
uint32_t* t4lo;
fd = open("/dev/mem", O_RDONLY);
if (fd == -1)
{
perror("open /dev/mem");
exit(1);
}
start = (unsigned char*)mmap(0, getpagesize(), PROT_READ, MAP_SHARED,
fd, 0x7e003000);
t4lo = (unsigned int *)(start + 0x04);
...
uint32_t Rpi::readTimer(void)
{
return *t4lo;
}
I should be checking the value of start, but gdb tells me it's reasonable so I don't think that's the problem.
(gdb) p t4lo
$4 = (uint32_t *) 0xb6f3a004
and gdb won't let me access *t4lo. Any ideas?
Edit: clock_gettime() is fulfilling my needs, but I'm still curious.
A closer look at https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2711/rpi_DATA_2711_1p0.pdf
figure 1 on page 5 shows that addresses vary depending upon who's looking at things. If you start with 0x7c00_0000 on the left side and follow it over to the right, it's apparent that it shows up at 0xfc00_0000 to the processor. So changing the timer base address to 0xfe00_3000 fixed the problem.
The secret is hidden in section 1.2.4:
So a peripheral described in this document as being at legacy address 0x7Enn_nnnn
is available in the 35-bit address space at 0x4_7Enn_nnnn, and visible to the ARM
at 0x0_FEnn_nnnn if Low Peripheral mode is enabled.
The address of the BCM2711 ARM Peripherals is the bus address which is not the same as the physical address in most systems. The bus address is easily used by DMA(Direct Memory Access) controller. mmap creates a new mapping from physical address to virtual address not bus address. So you can't use mmap funtion with parameter 0x7e003000. The rich answer is right.
So changing the timer base address to 0xfe00_3000 fixed the problem.
In addtion, your program run in the User space, only virtual address can you directly use.
I'm writing a ping clone to practice socket programming. I'm able to send ICMP packets, but the destination address is 0.0.0.0 regardless of what I pass to sendto. Here is the most pertinent snip of code:
struct sockaddr_in dest;
memset(&dest, 0, sizeof(dest));
dest.sin_family = AF_INET;
if (0 == inet_aton(argv[1], &dest.sin_addr)) {
puts("could not parse address\n");
exit(EXIT_FAILURE);
}
ssize_t nbytes = sendto(sock, &hdr, ICMP_MINLEN, /*flags=*/0,
(struct sockaddr*)&dest, sizeof(dest));
The full program is on GitHub. I'm compiling on and for Mac OS X 10.6.8, and I'm using Wireshark 1.8.4 to verify the packets.
I have verified the value of dest.sin_addr.s_addr with a call to printf("%X"), and inet_aton is working as expected. I have even deliberately set it to 0x08080808 (Google's name server), and it still doesn't work.
What might I be doing wrong here?
There's one (copy-paste) bug in your full program on github:
struct sockaddr_in src;
memset(&dest, 0, sizeof(dest));
After declaring src, you memset dest again. This means that dest's sin_addr member is now 0 so you're requesting a destination address of 0.0.0.0.
As an aside, src's sin_port is left uninitialised so you may sometimes get other errors if you end up requesting a local port that is already in use.
I hope someone can help me with this issue. I made an application to read some data from a smartphone and display in an application. It worked fine at my house, so I took it to my friend's house to show him and it didn't work. So after the panic, I realized that the address had changed slightly due to being connected to a new PC not a problem there must be a simple solution on winapi.
\\?\usb#vid_045e&pid_0040#6&ff454f2&0&3#{a5dcbf10-6530-11d2-901f-00c04fb951ed}\
I have only found code for C++ and my app is in C so it's no use. I also found libusb on google, however this doesn't return the full paths like in my example above.
Is there a simple fix like search by GUID? Hope you can help.
BR
This was the LIBUSB I used
#include <stdio.h>
#include <sys/types.h>
#include <windows.h>
#include <libusb.h>
static void print_devs(libusb_device **devs)
{
libusb_device *dev;
int i = 0;
while ((dev = devs[i++]) != NULL) {
struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0) {
fprintf(stderr, "failed to get device descriptor");
return;
}
printf("%04x:%04x (bus %d, device %d)\n",
desc.idVendor, desc.idProduct,
libusb_get_bus_number(dev), libusb_get_device_address(dev));
}
}
int main(void)
{
libusb_device **devs;
int r;
ssize_t cnt;
r = libusb_init(NULL);
if (r < 0)
return r;
cnt = libusb_get_device_list(NULL, &devs);
if (cnt < 0)
return (int) cnt;
print_devs(devs);
libusb_free_device_list(devs, 1);
libusb_exit(NULL);
system("pause");
return 0;
}
This just returns for example
1033:0194 (bus 1, device 255)
Yes you can get a list of all the device identifiers on your computer, but it's not really all that simple, especially if you need to filter it for a particular kind of device.
You start with SetupDiGetClassDevs. After enumerating the matching devices, use SetupDiGetDeviceInstanceId to get the device path, like the one shown in your question.
I am trying to capture all of transferred packets on a computer. My code works fine in Windows XP but it only captures outgoing packets on Windows 7 and cannot see incoming packets.
Here is a version of the code which just calculate the size of received packets (it seems big but most of it is just definitions). This code works correctly on Windows XP but nothing happens on Windows 7 (it stuck at recvfrom) (the code is complete and you could give a try on Win7):
#include <Winsock2.h>
#include <Mstcpip.h>
#include <iostream>
#include <string>
using namespace std;
#pragma comment(lib,"Ws2_32.lib")
struct SIP4HEADER
{
u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits)
u_char tos; // Type of service
u_short tlen; // Total length
u_short ident; // Identification
u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits)
u_char ttl; // Time to live
u_char proto; // Protocol
u_short crc; // Header checksum
u_long saddr; // Source address
u_long daddr; // Destination address
u_int op_pad; // Option + Padding
};
// Error handling parts is removed for clarity
void main()
{
WSAData wsa={0};
WSAStartup(MAKEWORD(2,2),&wsa);
string strIPAddress;
cout << "Enter a local IP address to monitor: ";
cin >> strIPAddress;
SOCKET ListenSocket = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
sockaddr_in sa_in;
sa_in.sin_family = AF_INET;
sa_in.sin_addr.s_addr = inet_addr( strIPAddress.c_str() ); //My local IP address
sa_in.sin_port = htons(0);
bind(ListenSocket,(SOCKADDR *) &sa_in, sizeof(sa_in));
int rcv=RCVALL_IPLEVEL;
DWORD b=0;
WSAIoctl(ListenSocket,SIO_RCVALL,&rcv,sizeof(rcv),0,0,&b,0,0);
char buf[2000];
SIP4HEADER* ih = (SIP4HEADER*)buf;
DWORD ReceivedKBytes = 0;
DWORD t = 0;
while( recvfrom(ListenSocket,buf,_countof(buf),0,NULL,NULL)!=-1 )
{
if(sa_in.sin_addr.s_addr == ih->daddr)
t += ntohs(ih->tlen) ;
// update each 20KB
if(t > 20*1024)
{
t=0;
ReceivedKBytes += 20;
cout << "Received KBs: " << ReceivedKBytes << endl;
}
}
}
The only thing made me suspect was this article on MSDN who says:
A call to the bind function with a raw
socket for the IPPROTO_TCP protocol is
not allowed
but i am using IPPROTO_IP, and bind function documentation also says:
The bind function may also be used to
bind to a raw socket (the socket was
created by calling the socket function
with the type parameter set to
SOCK_RAW)
So it seems this is not the problem. Despite this, I don't get any error from calling bind and other functions in this code. I also omitted calling bind function which causes recvfrom make error 10022 Invalid argument. I also replaced IPPROTO_IP with IPPROTO_TCP but it doesn't help neither.
I am not sure whether I am doing it right or not, but this code works without any problem on Windows XP. Anyway, I am looking for a way to get received and sent packets related to a local IP address on Windows XP/7.
Also:
I am running this code on privileged (admin) mode in Windows 7.
The Winpcap or other third-party libraries is not an available option for me.
I had the same problem. Turned out it was Windows 7 Firewall that stopped the sniffer from seeing inbound data. Turned it off and finally, the code worked.
I run your code on my Win7 and it works. I do see following lines printed out:
Received KBs: 20
Received KBs: 40
Received KBs: 60
Received KBs: 80
Received KBs: 100
Probably check your firewall?