UDP server process can't accept packets from kernel - linux

I have a very simple UDP server program
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char**argv)
{
int sockfd,n;
struct sockaddr_in servaddr,cliaddr;
socklen_t len;
char mesg[1000];
sockfd=socket(AF_INET,SOCK_DGRAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(54000);
bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
for (;;)
{
len = sizeof(cliaddr);
n = recvfrom(sockfd,mesg,1000,0,(struct sockaddr *)&cliaddr,&len);
sendto(sockfd,mesg,n,0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));
printf("-------------------------------------------------------\n");
mesg[n] = 0;
printf("Received the following:\n");
printf("%s",mesg);
printf("-------------------------------------------------------\n");
}
}
I put it on several machines and let a udp client to send packets to it
it can accept incoming udp packets successfully
then I place it in a machine with fedora 18
I compile the program and run it
and then I let a udp client to send packets to it(the same as on the other machines)
but the program can't accept incoming UDP packets
I used tcpdump for capturing and I can see the incoming udp packets
why the server program doesn't accept the incoming UDP packet on this machine?
I checked the iptables rule iptables -L
and the results are in
https://docs.google.com/file/d/0B09y_TWqTtwlNHp1eTJkTFNuY0k/edit?usp=sharing
are there potential reasons for this?
thanks!

The code looks OK at first glance.
The most obvious explanation might simply be that the Fedora 18 machine has been installed with iptables firewalling configured by default...
Try running lsmod to look for loaded iptables modules, and/or iptables -L to list the current ruleset.

Related

How to kill a single TCP connection in Linux?

I have a process that opens several tcp connections to several browsers on separate ports.
Using netsat the output is something like this :
tcp 0 0 server1.something:myprog client1.something:49987 ESTABLISHED
tcp 0 0 server1.something:myprog client1.something:65987 ESTABLISHED
tcp 0 0 server1.something:myprog client1.something:89987 ESTABLISHED
Now i would like to kill exactly one of the connections? How do i do it? (Since killing the process will kill all connections)
On linux kernel >= 4.9 you can use the ss command from iproute2 with key -K
ss -K dst client1.something dport = 49987
the kernel have to be compiled with CONFIG_INET_DIAG_DESTROY option enabled.
Here are some options:
Attach with gdb and call close() on the fd. You can map from addr/port to inode number via /proc/net/tcp and from inode number to FD inside the process with ls -la /proc/$pid/fd.
Spoof a RST packet. You'll need to generate it locally and guess the SEQ number somehow.
Maybe setup an iptables rule to generate a RST on the next packet.
Write a kernel module.
There doesn't seem to be a well supported way to do this. It is likely that processes will crash if their FDs are unexpectedly closed anyway.
You can't kill a single connection of a process.
But you could block it with iptables. So the connection can't provide or receive data and the client will run in a timeout.
You can kill by destination port:
ss -K dport = 65987

Any small program to receive multicast packets on specified UDP port?

I'd like to debug some multicast issues, and I hope to have some small programs/utilities to display incoming multicast packets.
From the sending machine(A), I use Richard Stevens's sock program(provided with his TCP/IP Illustrated book Vol1) to send multicast packets(source port=dest port=7000), like this:
sock -u -b 7000 224.0.0.7 7000
On the receiving machine(B), I can capture the very sent packet with Wireshark, however, the same sock command running on B does not report receiving anything.
Then, what program should I use on B to see incoming multicast packets, aside from Wireshark which is overkill.
Linux and Windows programs are both welcome.
Here's a python script that will print the incoming data;
# Multicast client
# Adapted from: http://chaos.weblogs.us/archives/164
import socket
ANY = "0.0.0.0"
MCAST_ADDR = "224.0.0.7"
MCAST_PORT = 7000
# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
# Allow multiple sockets to use the same PORT number
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# Bind to the port that we know will receive multicast data
sock.bind((ANY,MCAST_PORT))
# Tell the kernel that we want to add ourselves to a multicast group
# The address for the multicast group is the third param
status = sock.setsockopt(socket.IPPROTO_IP,
socket.IP_ADD_MEMBERSHIP,
socket.inet_aton(MCAST_ADDR) + socket.inet_aton(ANY))
# setblocking(0) is equiv to settimeout(0.0) which means we poll the socket.
# But this will raise an error if recv() or send() can't immediately find or send data.
sock.setblocking(0)
while 1:
try:
data, addr = sock.recvfrom(1024)
except socket.error as e:
pass
else:
print "From: ", addr
print "Data: ", data
You can use netcat (nc) to do that:
netcat -vv -l -p 1234 -u
This means netcat is verbosely listening on port 1234 of the localhost in UDP mode.
I've written a multicast testing application back in the day.
You can check it out here: https://github.com/eranbetzalel/SimpleMulticastAnalyzer
This is the first hit when I searched for capturing multicast packets using netcat, and I found out that tcpdump does a job better. Just making a note for any one else hitting this post.
To install:
sudo apt install tcpdump
To run:
tcpdump -c 8 -n -i eth0 portrange 1234-1239
looks like there may be a Windows port too, but I didn't try it: https://www.winpcap.org/windump/

Finding original MAC address from hardware itself

Is it possible to read the MAC address from the NIC directly? I have the code below but it just reads from the layer above but not the card itself.
I'm trying to figure out how to find the original MAC address of an Ethernet NIC on my Linux box. I understand how to find the current MAC address using ifconfig.
But the address can be changed, say by using
ifconfig eth0 hw ether uu:vv:ww:yy:xx:zz
or setting it "permanently" using /etc/sysconfig/network-scripts/ifcfg-eth0.
How do I find the original MAC address? There must be a way to find it, because it is still burned permanently into the card, but I can't find a tool to read the burned in address.
Is there any utility or command for that?
I suppose it should be possible to write C code for it, below code gives my current MAC but not the original MAC:
#include <stdio.h> /* Standard I/O */
#include <stdlib.h> /* Standard Library */
#include <errno.h> /* Error number and related */
#define ENUMS
#include <sys/socket.h>
#include <net/route.h>
#include <net/if.h>
#include <features.h> /* for the glibc version number */
#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1
#include <netpacket/packet.h>
#include <net/ethernet.h> /* the L2 protocols */
#else
#include <asm/types.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h> /* The L2 protocols */
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <netdb.h>
int main( int argc, char * argv[] ){
unsigned char mac[IFHWADDRLEN];
int i;
get_local_hwaddr( argv[1], mac );
for( i = 0; i < IFHWADDRLEN; i++ ){
printf( "%02X:", (unsigned int)(mac[i]) );
}
}
int get_local_hwaddr(const char *ifname, unsigned char *mac)
{
struct ifreq ifr;
int fd;
int rv; // return value - error value from df or ioctl call
/* determine the local MAC address */
strcpy(ifr.ifr_name, ifname);
fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (fd < 0)
rv = fd;
else {
rv = ioctl(fd, SIOCGIFHWADDR, &ifr);
if (rv >= 0) /* worked okay */
memcpy(mac, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
}
return rv;
}
OS: Red Hat Linux, 2.6.18.8-1
Certainly in ethtool you can just print the address:
-P --show-permaddr
Queries the specified network device for permanent hardware address.
e.g.
ethtool -P eth0
produces
Permanent address: 94:de:80:6a:21:25
Try cat /sys/class/net/eth0/address or cat /sys/class/net/em1/address if using Fedora. It should work.
The original answer is here: Notes of a Systems Admin
The only way to find the original MAC address is to use the same method the network card driver does - unfortunately, I don't believe there is a generic way to tell the driver to provide its MAC address "as provided by the hardware". Of course, there are cases where there isn't a hardware network card for that particular interface - virtual network drivers for virtualization and when using bridges and software switches for example.
And of course, the hardware may be such that you can't actually read the "original" MAC address when it has been overwritten by software, because there is only one set of registers for the MAC address itself.
I had a quick look at the pcnet32.c drivers (because it's one of the models of network card that I have a rough idea how it works and where the different registers are, etc, so I can see what it does). As far as I can see, it supports no method of actually asking "what is your PROM Ethernet address" - the MAC address is read out during the "probe1" section of the module initialization, and stored away. No further access to those hardware registers is made.
Well, the old ethernet address remains in the first bytes of the card eeprom (at least for some types of cards), so it is possible to extract it using ethtool
bash$ sudo ethtool -e eth1
Offset Values
------ ------
0x0000 tt uu ww xx yy zz 79 03
0x....
where tt:uu:ww:xx:yy:zz is old mac address
This may not be the programmatic way, but why not search dmesg. All of my machines' NICs spit out the MAC address at detection time.
Try something like this:
dmesg|grep eth0
Different NICs display the MAC address differently, but the log will always contain the kernel given name of the adapter (in most cases eth0 or wlan0).
In Ubuntu 18.4 LTS
First you need to find the network interface names on the computer by command
ls /sys/class/net
My output is
docker0 enp0s31f6 lo
Now you can use the command as discussed above, dont forget the sudo
sudo ethtool -P enp0s31f6
This command lists all the ethernet devices and original HW addresses.
dmesg | grep eth | grep IRQ | awk {'print "permanent address of " $5 " " $9'} |tr "," " "

Monitor transport,network and link layer buffers/queue (loaded, empty, full and drop) in Linux

As far as i know, these are buffer/queues for UDP in Linux (correct me if im wrong)
UDP Tx : [sendto] UDP socket buffer(getsockopt(SO_SNDBUF)) -> interface socket buf() -> driver ring buffer
UDP_Rx : driver ring buffer -> backlog queue -> [recvfrom] UDP socket buffer(getsockopt(SO_RCVBUF))
I know we can monitor drop/queue:
-socket buffer(UDP) at /proc/net/udp
-interface queue(IP) at /proc/net/dev
Where can i monitor the driver queue/buffer(MAC) for a drop in Linux?
p/s: i wanna see and PROVE what happen to the datagramme in those queues if we cut the connection during UDP transfer over WLAN.
use $tc -s -d qdisc ls dev eth0 for eth0 interface

Linux: Detect 64-bit kernel (long mode) from 32-bit user mode program

What's the best and most reliable way to detect if a 32-bit user mode program is running on a 64-bit kernel or not (i.e. if the system is in 'long mode')? I'd rather not call external programs if possible (or have to load any kernel modules).
Note: I want to detect whether a 64-bit kernel is being used (or really, whether the CPU is in long mode), not simply if a 64-bit capable processor is present (/proc/cpuinfo tells me that but not whether the 64-bit capability is being used).
The kernel fakes a 32-bit processor if uname is compiled 32-bit or if setarch i686 is used.
Call the uname() function and check the returned machine string, which will be x86_64 for a 64-bit Intel platform.
One way of reversing the effect of the use of setarch is to reset the personality:
#include <stdio.h>
#include <sys/utsname.h>
#include <sys/personality.h>
int main()
{
struct utsname u;
personality(PER_LINUX);
uname(&u);
puts(u.machine);
return 0;
}
This shows the right results when compiled in 32-bit mode and run on a 64-bit system:
$ gcc -m32 -o u u.c
$ ./u
x86_64
$ setarch i686 ./u
x86_64
EDIT: Fixed code to reverse effect of setarch.
Reference.
Assuming that uname() is cheating, there are still several mechanisms. One way is to check the width of the address of any of the kernel symbols.
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
char *inputline = malloc(1024);
char *oinputline = inputline;
int fd = open("/proc/kallsyms", O_RDONLY);
int numnibbles = 0;
if (fd == -1) {
perror("open");
free(inputline);
exit(1);
}
read(fd, inputline, 1024);
close(fd);
while(!isspace(*inputline)) {
numnibbles++;
inputline++;
}
printf("%dbit\n", numnibbles*4);
free(oinputline);
exit (0);
}
If the kernel is configured for it, you can read the kernel config from /proc/config.gz
zcat /proc/config.gz | grep CONFIG_64BIT
# CONFIG_64BIT is not set
I'm not sure how portable you need it to be- it doesn't seem like a super common config option.

Resources