Messages in this thread | | | Subject | IP_HDRINCL and IP_PKTINFO on RAW sockets with sendmsg | From | Eng Se-Hsieng <> | Date | 20 May 2003 22:01:54 -0800 |
| |
Hello,
I am using IP_HDRINCL and IP_PKTINFO (to choose by which interface the packet leaves) on a RAW socket.
I'm using the udphdr structure with IPPROTO_RAW but I keep Malformed Packet in the Ethereal traces and the IP header can't even be read by Ethereal.
Is there something wrong with my approach? Please advise. Thank you.
Regards, Se-Hsieng
Attached: test_iphdr.c
#include <sys/socket.h> #include <sys/uio.h> #include <unistd.h> #include <resolv.h> #include <net/if.h> #include <netinet/udp.h> #include <netinet/ip.h>
#define BUFFER_SIZE 36000
int main(void) { char *buffer; int buffer_size = BUFFER_SIZE; int s = socket(PF_INET, SOCK_RAW, IPPROTO_RAW); struct sockaddr_in sin; struct msghdr msg; struct cmsghdr *cmsg; struct in_pktinfo *pktinfo; char outcmsg[CMSG_SPACE(sizeof(struct in_pktinfo))]; struct iovec io; int yes=1; int i, bytes; char *interface="eth0"; struct ip *iph; int iphdrSz; struct udphdr* udph; int if_index1=0; int if_index2=0;
bzero(&sin, sizeof(sin)); sin.sin_family=AF_INET; sin.sin_addr.s_addr=INADDR_ANY; sin.sin_port=htons(10000); if (bind(s, (struct sockaddr *)&sin, sizeof(sin))<0) { printf("bind: UH-OH.\n"); exit(1); }
bzero(&sin,sizeof(sin)); bzero(&msg,sizeof(msg));
sin.sin_family=AF_INET; sin.sin_port=htons(10000); sin.sin_addr.s_addr=inet_addr("137.132.165.146");
msg.msg_name=&sin; msg.msg_namelen=sizeof(sin); msg.msg_control= outcmsg; msg.msg_controllen=sizeof(outcmsg); msg.msg_flags=0;
buffer=(char*)malloc(buffer_size);
if (setsockopt(s,SOL_IP,IP_HDRINCL,&yes,sizeof(yes))==0) { printf("Construct IP header ok.\n"); }
/* Construct IP header */ iph=(struct ip*)buffer; iph->ip_hl=5; iph->ip_v=4; iphdrSz=sizeof(struct ip); iph->ip_len = htons(buffer_size+iphdrSz); iph->ip_id=0; iph->ip_off=0x40; iph->ip_p=132; iph->ip_sum=0; iph->ip_src.s_addr=0; iph->ip_dst.s_addr=0;
udph=(struct udphdr*) ((u_long)buffer+sizeof(struct ip)); udph->source=htons(10000); udph->dest=htons(10000); udph->len=htons(buffer_size); udph->check=0;
io.iov_base=buffer; io.iov_len=strlen(buffer);
if (setsockopt(s, SOL_IP, IP_PKTINFO,&yes,sizeof(yes))==0) { printf("sok opt OK\n"); }
cmsg=CMSG_FIRSTHDR(&msg); cmsg->cmsg_level=SOL_IP; cmsg->cmsg_type=IP_PKTINFO; cmsg->cmsg_len=CMSG_LEN(sizeof(struct in_pktinfo));
msg.msg_controllen=cmsg->cmsg_len; pktinfo=(struct in_pktinfo *)CMSG_DATA(cmsg); memset(pktinfo, 0x00, sizeof(struct in_pktinfo));
msg.msg_iov=&io; msg.msg_iovlen=1;
for (i=0;i<10;i++) {
if_index1 = if_nametoindex("eth0");
printf("eth0, %d\n", if_index1);
if (!if_index1) { printf("Interface %s unknown\n", interface); exit(1); }
pktinfo->ipi_ifindex=if_index1; //pktinfo->ipi_spec_dst.s_addr=inet_addr("137.132.53.46"); if ( (bytes=sendmsg(s,&msg,0))<0 ) printf("cannot send \n");
if_index2 = if_nametoindex("eth1");
printf("eth1, %d\n", if_index2); if (!if_index2) { printf("Interface %s unknown\n", interface); exit(1); }
pktinfo->ipi_ifindex=if_index2;
if ( (bytes=sendmsg(s,&msg,0))<0 ) printf("cannot send \n");
}
close (s); free(buffer);
}
| |