LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Wireshark UDP Packets Socket not set (https://www.linuxquestions.org/questions/programming-9/wireshark-udp-packets-socket-not-set-724165/)

robtard 05-06-2009 12:26 PM

Wireshark UDP Packets Socket not set
 
Hi,

I have something strange going on. I am sending UDP encapsulated packets
from one machine to another. On the outbound machine the packets show up in wireshark as "UDP Checksum Incorrect" - I've read somewhere that this may be because wireshark views the packet before the NIC computes the checksum and puts it in the packet.

Either way, on the other end (receiving end) the machine getting the packets receives them on a 3G Sprint interface (ppp0), they show up in wireshark (without the UDP checksum incorrect) message. The packets are being sent to 8080 on that machine, where I have a socket bound to ppp0:8080 using the "recvfrom()" function. Strangely, the socket filedescriptor is not being set. Here is my code:


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <net/if.h>

#include "monitorInterface.h"
#include "selectInterface.h"
#include "tunnelInterface.h"
//#include "capsulatePacket.h"

int handlePackets(int tunfd, struct tunnel *tun)
{
fd_set readSet;
int bufSize, maxfd, readfd, sockfd, rtn;
char *buffer = (char *)malloc(1600);
char buf[1600];

if( (readfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("read socket failed");
return -1;
}

struct sockaddr_in myAddr;
memset(&myAddr, 0, sizeof(struct sockaddr_in));
myAddr.sin_family = AF_INET;
myAddr.sin_port = htons((unsigned short)tun->localPort);
myAddr.sin_addr.s_addr = htonl(INADDR_ANY);

printf("Binding to local port: %d\n", ntohs(myAddr.sin_port) );

if( bind(readfd, (struct sockaddr *)&myAddr, sizeof(struct sockaddr_in)) < 0) {
perror("bind failed");
close(readfd);
return -1;
}


//TODO: this should be removed...shouldn't bind to device on read side if having multiple devices
char *bind_device = (char *)malloc(IFNAMSIZ);
strncpy(bind_device, "ppp0", IFNAMSIZ);
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));

if(setsockopt(readfd, SOL_SOCKET, SO_BINDTODEVICE, bind_device, IFNAMSIZ+1) < 0) {
perror("SO_BINDTODEVICE");
return -1;
}

//TODO: this duplicates code from interfaceBind() should remove from there
struct sockaddr_in destAddr;
memset(&destAddr, 0, sizeof(struct sockaddr_in));
destAddr.sin_family = AF_INET;
destAddr.sin_port = htons((unsigned short)tun->remotePort);
inet_pton(AF_INET, tun->remoteIP, &destAddr.sin_addr);

//struct sockaddr_in *test = tun->destAddr;
//printf("dest port: %d dest IP: %s\n", ntohs((unsigned short)(tun->destAddr).sin_port), (char *)inet_ntoa((tun->destAddr).sin_addr));
printf("stored port: %d stored IP: %s\n", (unsigned short)tun->remotePort, tun->remoteIP);


maxfd = (tunfd > readfd) ? tunfd : readfd;
sockfd = selectInterface(TEST);
printf("sockfd %d, readfd %d, tunfd %d maxfd %d\n", sockfd, readfd, tunfd, maxfd);

printf("output: ");

while(1)
{
//setup read descriptors
FD_ZERO(&readSet);
FD_SET(tunfd, &readSet);
FD_SET(readfd, &readSet);
//maxfd = (tunfd > readfd) ? tunfd : readfd;
//printf("maxfd %d\n", maxfd);
printf("$");

//TODO: how to know which fd is the max?
select((maxfd+1), &readSet, NULL, NULL, NULL);

if( FD_ISSET(tunfd, &readSet) ) {
printf("*");
//if( (bufSize = read(tunfd, buf, sizeof(buf))) < 0) {
if( (bufSize = read(tunfd, buffer, 1600)) < 0) {
perror("read packet error");
} else {
//select interface and send
if((sockfd = selectInterface(TEST)) < 0) {
printf("sockfd: %d\n", sockfd);
perror("selecting interface");
//return -1;
}
//TODO: this is a really big hack to overwrite the 2 bytes that come from ???
buffer += 2;
//if( (rtn = sendto(sockfd, buf, bufSize, 0, (struct sockaddr *)&destAddr, sizeof(struct sockaddr))) < 0) {
if( (rtn = sendto(sockfd, buffer, bufSize, 0, (struct sockaddr *)&destAddr, sizeof(struct sockaddr))) < 0) {
//perror("sendto failed");
printf("sendto failed: %s %d\n", (char *)strerror(errno), errno);
//printf("return value: %d, sockfd: %d\n", rtn, sockfd);
//return -1;
}
}
}

int fromlen = sizeof(struct sockaddr_in);
struct sockaddr_in * from = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));

//if packets returning from proxy
if( FD_ISSET(readfd, &readSet) ) {
printf("readfd set\n");
if( (bufSize = recvfrom(readfd, &buf[2], (sizeof(buf)-2), 0, (struct sockaddr *)from, &fromlen)) < 0) {
perror("recv failed");
} else {
//printf("sent to tunnet for denat\n");
buf[0] = 0x45;
buf[1] = 0x00;
if(write(tunfd, buf, (bufSize)) < 0) {
perror("writting to tunnel");
}
}
}

fflush(stdout);
}

return 1;
}


int main(int agrc, char *argv[])
{
struct tunnel *myTun = (struct tunnel *)malloc(sizeof(struct tunnel));

//scan interfaces
//char inbound_if[IFNAMSIZ] = "eth0";
interfaceScan(myTun);
interfacePrint(int_last);

//tunnel interface
int tunfd = tunnelInit(myTun);

//process packets
handlePackets(tunfd, myTun);

//clean up
interfaceCleanup(int_list, int_last);
return 1;
}

amysaraantony 05-07-2009 06:42 AM

Wow ... That's some scary code !
Sadly, I aint any good with network and sockets ... Sorry I couldnt be much help here ...
:(

Debian

asangau 08-07-2010 03:41 PM

Hello,

I too had a similar problem. I have an application that needs to send UDP over multiple network interfaces (ppp0, wlan0). But, the same, as described above was happening, i.e. wireshark was seeing the packet destined to the interface address, but not the select()/recvfrom() in the application which is bound to that interface. The outgoing packets from the application were going over the right interfaces.

I was using IPROUTE2 and iptables to forward outgoing packets generated from the approprite socket bound to the approprite interface at the network level. i.e.,
- iptables used to mark packets based on the approprite source address
- "ip rule" to forward marked packets to the approprite routing table
- "ip route" to create the different routing tables with entries to forward packets through the approprite interface

After trying many different things, including using Ubuntu 9.10 and 10.4, I found that, by removing the dependance on iptables and solely using IPROUTE2 for the network level routing for outgoing packets, the incomming packets became visible to the select()/recvfrom() of my application.

Unfortunately, I did not have time to investigate further. I had to move on to other issues.

Asanga Udugama

Chief Sleepy Bear 10-27-2010 06:45 PM

Bad checksum's on outbound packets are normal
 
Don't mess with your system because you see checksum errors on outbound packets using wireshark. This is normal, and should be ignored.

When your code sends packets, you do not calculate the checksum. Also, the socket library does not calculate the checksum when it creates the udp packet header. This is because your network card or driver will compute the checksum for you. Network cards have gotten smarter, so some work is offloaded to the card.

If you really want to see what packets look like leaving your computer, then you can do what I do. I have a tiny micro ATX linux computer that has three gigabit network interfaces. (nothing special, just a normal computer with linux installed) I make a network bridge out of two interfaces. The third interface has the IP address configured like usual for a workstation. The bridge has no ip address, and is invisible to the network. I can use the bridge to observer packets, capture streams, and block network streams.

You have to get the cabling right. It seems easy to me, but I noticed people at work have trouble figuring out how to connect the parts.


All times are GMT -5. The time now is 11:49 AM.