Date: Sun, 30 Nov 2003 14:26:31 +0200 From: "Ivo Vachkov" <ivo@bsdmail.org> To: freebsd-ipfw@freebsd.org Cc: freebsd-net@freebsd.org Message-ID: <20031130122631.7868.qmail@bsdmail.com>
next in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
Hi all,
I've been trying to write some code using divert(4) sockets, but i meet the following difficulties:
- when i get diverted packet it has both source and destination IP addresses the same. The attached code shows:
192.168.0.2 -> 192.168.0.2
getting 84 bytes, real: 84
and the way I run it is (on 192.168.0.2):
ipfw add 100 divert 8670 ip from any to 192.168.0.1
burstd
then on 192.168.0.2 I issue "ping 192.168.0.1"
- the manual says this happens with recvfrom()/sendto(), but recv() is mentioned to be same as recvfrom() and read()/write() sometimes fail.
After digging some kernel code I've found that around line 167 in ip_divert.c we have:
/*
* Record receive interface address, if any.
* But only for incoming packets.
*/
divsrc.sin_addr.s_addr = 0;
if (incoming) {
struct ifaddr *ifa;
/* Sanity check */
KASSERT((m->m_flags & M_PKTHDR), ("%s: !PKTHDR", __FUNCTION__));
/* Find IP address for receive interface */
TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrhead, ifa_link) {
if (ifa->ifa_addr == NULL)
continue;
if (ifa->ifa_addr->sa_family != AF_INET)
continue;
divsrc.sin_addr =
((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;
break;
}
}
which (as I think) changes the address of diverted packet. What is the reason for that and are there any workarounds to get real source and destination IP addresses from a diverted packet. I need both because I try to make connection tracking based on src<->dst .
Any help with that is appretiated. Any divert code welcome. I've looked through natd.c and it was helpfull.
Ivo Vachkov
P.S. Excuse my:
- English
- long pastes
- (sometimes) lack of kernel code understanding
--
_______________________________________________
Get your free email from http://mymail.bsdmail.com
Powered by Outblaze
[-- Attachment #2 --]
CC = cc
CFLAGS = -g -Wall -Wpointer-arith
LIBS =
SRC = burstd.c
OBJ =
PROG = burstd
all:$(SRC)
$(CC) $(CFLAGS) -c *.c
$(CC) $(CFLAGS) -o $(PROG) $(SRC) $(OBJ) $(LIBS)
clean:
rm -f $(PROG) *.core *.o etc/*
[-- Attachment #3 --]
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <machine/in_cksum.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/route.h>
#include <arpa/inet.h>
#include <alias.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
// #include "queue.h"
#define CONF "burstd.conf"
/* Connection type; bursting */
typedef struct _flow
{
struct in_addr src_addr;
struct in_addr dst_addr;
long long bytes;
long long last;
int alive;
int used;
}CONNECTION;
typedef struct _node
{
struct _node *next;
struct _flow *data;
}CONN_LIST;
long long limit, rate;
/* Some functions */
/* signal.c */
void sig_alrm_hnd(int sig);
/* init.c */
void set_rate_limit();
/* parent.c */
int search_conn(CONNECTION cons[], struct in_addr saddr, struct in_addr daddr);
int add_conn(CONNECTION cons[], CONNECTION s_conn);
[-- Attachment #4 --]
#include "burstd.h"
int main(int argc, char **argv)
{
int divIO;
fd_set readmask;
struct sockaddr_in sa;
int bytes, oldbytes, addrSize;
struct ip* ip;
void* buff;
buff = (void *)malloc(IP_MAXPACKET);
memset((void *)buff, 0, IP_MAXPACKET);
if((divIO = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT)) == -1)
{
perror("socket");
exit(-1);
}
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = INADDR_ANY;
sa.sin_port = htons(8670);
if(bind(divIO, (struct sockaddr*)&sa, sizeof(struct sockaddr)) == -1)
{
perror("bind");
exit(-1);
}
FD_ZERO(&readmask);
FD_SET(divIO, &readmask);
while(1)
{
if(select(getdtablesize() + 1, &readmask, NULL, NULL, NULL) == -1)
{
perror("select");
exit(-1);
}
if(FD_ISSET(divIO, &readmask))
{
addrSize = sizeof(sa);
if((oldbytes = recvfrom(divIO, buff, IP_MAXPACKET, 0, (struct sockaddr*) &sa, &addrSize)) == -1)
{
perror("recvfrom");
exit(-1);
}
ip = (struct ip*) buff;
printf("%s -> %s\n", inet_ntoa(ip->ip_src), inet_ntoa(ip->ip_dst));
printf("getting %d bytes, real: %d\n", oldbytes, ntohs(ip->ip_len));
printf("sa.sin_addr.s_addr = %s\n", inet_ntoa(sa.sin_addr));
if((bytes = sendto(divIO, buff, oldbytes, 0, (struct sockaddr*) &sa, addrSize)) != oldbytes)
{
printf("Different recieved/sent values: %d <-> %d\n", oldbytes, bytes);
perror("sendto");
exit(-1);
}
}
}
return 0;
}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20031130122631.7868.qmail>
