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?
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've been struggling for the past few days to get the Elechouse PN532 V3 module working with an ESP32 over I2C. The PN532 module itself works fine with a Raspberry Pi.
This is the circuit (not actually using SparkFun ESP32 board, just for reference)
And this is the code I'm trying to run
#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>
PN532_I2C pn532i2c(Wire);
PN532 nfc(pn532i2c);
void setup(void) {
Serial.begin(115200);
Serial.println("Hello!");
Wire.begin(18, 19);
nfc.begin();
uint32_t versiondata = nfc.getFirmwareVersion();
if (! versiondata) {
Serial.print("Didn't find PN53x board");
while (1); // halt
}
// Got ok data, print it out!
Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
// Set the max number of retry attempts to read from a card
// This prevents us from waiting forever for a card, which is
// the default behaviour of the PN532.
nfc.setPassiveActivationRetries(0xFF);
// configure board to read RFID tags
nfc.SAMConfig();
Serial.println("Waiting for an ISO14443A card");
}
void loop(void) {
boolean success;
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
// Wait for an ISO14443A type cards (Mifare, etc.). When one is found
// 'uid' will be populated with the UID, and uidLength will indicate
// if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
if (success) {
Serial.println("Found a card!");
Serial.print("UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
Serial.print("UID Value: ");
for (uint8_t i=0; i < uidLength; i++)
{
Serial.print(" 0x");Serial.print(uid[i], HEX);
}
Serial.println("");
// Wait 1 second before continuing
delay(1000);
}
else
{
// PN532 probably timed out waiting for a card
Serial.println("Timed out waiting for a card");
}
}
And finally the serial output: Didn't find PN53X board
Any ideas what I'm doing wrong?
EDIT: libraries im using https://github.com/elechouse/PN532 and the ESP32 dev board is a Wemos Lolin32 Lite clone.
I don't have any of this hardware to verify this, but from 'PN532-PN532_HSU\NDEF\README.md'
For the Adafruit Shield using I2C
#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>
PN532_I2C pn532_i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532_i2c);
Try using the above in your code? I'd also suggest you review the PN532 I2C examples in more depth. The PN532 I2C library code defines a 'wakeup' function:
void PN532_I2C::wakeup()
{
delay(500); // wait for all ready to manipulate pn532
}
The comment makes me believe the device may require a significant delay (500ms) before it's ready to talk.
Best of luck.
sda and scl are 21 and 22
also make sure that you changed mode to I2C (those jumpers on PN532 module):
doc - page 3
I have this now working with an M5STACK grey core, the common issue was the I2C bus would lock up on a reset or re program. Use a spare I/O pin and connect to the PN532 reset pin, hold this low on boot, initialize I2C bus then drive reset high after 100mS problem solved no more bus conflicts.
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!
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 am writing a kernel module which registers a hook with netfilter. The handler is not being called if I ssh/telnet into the machine where the module is loaded.
struct nf_hook_ops my_hook_ops;
my_hook_ops.hook = hook_handler;
my_hook_ops.pf = PF_INET;
my_hook_ops.hooknum = NF_INET_PRE_ROUTING;
my_hook_ops.priority = NF_IP_PRI_FIRST;
nf_register_hook(&my_hook_ops);
The handler function:
unsigned int hook_handler(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
if(!skb)
return NF_ACCEPT;
struct iphdr* ip_header;
struct tcphdr* tcp_header;
union ip_address ipaddr;
printk(KERN_INFO "Entered handler\n");
if(skb->protocol == 8)
return NF_ACCEPT;
// Log the received packet
ip_header = ip_hdr(skb);
tcp_header = tcp_hdr(skb);
ipaddr.saddr = ip_header->saddr;
printk(KERN_INFO "Received packet:\nIP Address: %u.%u.%u.%u\nProtocol: %d\nSource port: %d\nDestination port: %d\n",
ipaddr.a[0],ipaddr.a[1],ipaddr.a[2],ipaddr.a[3],
skb->protocol,
tcp_header->source,
tcp_header->dest);
return NF_ACCEPT;
}
The hook is being called for protocol 8 (Exterior Gateway Protocol). The second printk never gets printed. Am I missing anything?
The protocol used here is different from the IP protocol number as assigned by IANA, for which 8 is for EGP and EGP has been outdated.
The protocol field for sk_buff is defined in , for which 8 is for ETH_P_IP. As your data is allways IP traffic,the first conditional check is always true. So the second part of code never get executed.
A couple of thoughts:
a hook handler takes a (struct skbuff **), not a (struct skbuff *)
following on from the above, skb->protocol doesn't exist. You want either (*skb)->protocol or you want the following idiom:
struct sk_buff *sock_buf = *skb;
if(sock_buff->protocol)
If the packet is an EGP packet, you should not be expecting output from the second printk, because you return before it.
You need to study how sk_buff works, the protocol field initialized by the function `eth_type_trans' which takes on ETH_P_* values. All ETH_P_* values are defined in if_ether. Here are some of these values.
#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */
#define ETH_P_PUP 0x0200 /* Xerox PUP packet */
#define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */
#define ETH_P_IP 0x0800 /* Internet Protocol packet */
You clearly see that 0x08 is defined for Internet Protocol packet. And your code clearly return in case of 8 (which is IP packet)
if(skb->protocol == 8)
return NF_ACCEPT;
Your ssh/telnet clearly IP packet(s) and rejected by above code. Please use proper protocol defined values defined in if_ethr