raw ip paket sendto error
Stefan
stefan at sf-net.com
Tue Apr 11 13:47:30 UTC 2006
>
> Sorry, but nope. But I guess if you can post a complete source code
Again your right ;-)
There are two functions udp_raw_send and ip4_udp_raw_send. The first
function which is called udp_raw_send has 6 arguments: source
address, destination address, source port, destination port, payload
and payload_length.
This function does nothing else than determinig which protocol the
address belongs to (IPv4 or IPv6) and call up the ip4_udp_raw_send
function with the arguments like udp_raw_send except that the source
and destination address are now in network byte order. The
ip4_udp_raw_send function then calculates the checksum etc and sends
then the udp packet out. Here are the two functions:
int udp_raw_send(const char *src_addr, const char *dst_addr,
const char *src_port, const char *dst_port,
const u_char *payload, const int payload_len) {
struct addrinfo hints, *src_ai, *dst_ai;
int result;
int getaddrinfoError;
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = 0;
hints.ai_protocol = 0;
hints.ai_addrlen = 0;
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
if((getaddrinfoError = getaddrinfo(src_addr, src_port, &hints,
&src_ai))
!= 0) {
fprintf(stderr, "Error getaddrinfo (src address): %s\n",
gai_strerror(getaddrinfoError));
exit(EXIT_FAILURE);
}
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = 0;
hints.ai_protocol = 0;
hints.ai_addrlen = 0;
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
if((getaddrinfoError = getaddrinfo(dst_addr, dst_port, &hints,
&dst_ai))
!= 0) {
fprintf(stderr, "Error getaddrinfo (dst address): %s\n",
gai_strerror(getaddrinfoError));
exit(EXIT_FAILURE);
}
/* check if source and destination address are from the same ip
family */
if(src_ai->ai_family != dst_ai->ai_family) {
fprintf(stderr, "Error: source and destination address
aren't from" \
" the same ip family. Maybe one is an IPv4
address" \
" and the other an IPv6 address\n");
exit(EXIT_FAILURE);
}
if(src_ai->ai_family == AF_INET) {
struct sockaddr_in *sin_src, *sin_dst;
sin_src = (struct sockaddr_in *)src_ai->ai_addr;
sin_dst = (struct sockaddr_in *)dst_ai->ai_addr;
result = ip4_udp_raw_send(sin_src->sin_addr.s_addr,
sin_dst->sin_addr.s_addr,
src_port, dst_port, payload,
payload_len);
} else if(src_ai->ai_family == AF_INET6) {
struct sockaddr_in6 *sin6_src, *sin6_dst;
sin6_src = (struct sockaddr_in6 *)src_ai->ai_addr;
sin6_dst = (struct sockaddr_in6 *)dst_ai->ai_addr;
result = ip6_udp_raw_send((char *)sin6_src->sin6_addr.s6_addr,
(char *)sin6_dst->sin6_addr.s6_addr,
src_port, dst_port, payload,
payload_len,
dst_ai);
/* result = ip6_udp_raw_send((char *)&(sin6_src->sin6_addr),
(char *)&(sin6_dst->sin6_addr),
src_port, dst_port, payload,
payload_len,
(struct sockaddr_in6 *)(dst_ai-
>ai_addr));*/
} else {
fprintf(stderr, "Error: please choose an address of" \
" AF_INET or AF_INET6\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(src_ai);
freeaddrinfo(dst_ai);
return(result);
}
int ip4_udp_raw_send(u_long src_addr, u_long dst_addr, const char
*src_port,
const char *dst_port, const u_char *payload,
int payload_len) {
struct sockaddr_in sin4;
struct ip *iphdr;
struct udphdr *udp;
struct pseudo_udphdr *pseudo_udp;
u_char *data;
unsigned char *packet = safe_zalloc(iphdr_len + udphdr_len +
payload_len);
int sockfd;
const int on = 1;
int result;
iphdr = (struct ip *)packet;
udp = (struct udphdr *)(packet + sizeof(struct ip));
pseudo_udp = (struct pseudo_udphdr *) ((char *)udp - 12);
data = (u_char *)(packet + sizeof(struct ip) + sizeof(struct
udphdr));
memcpy(data, payload, payload_len);
udp->uh_sport = htons(atoi(src_port));
udp->uh_dport = htons(atoi(dst_port));
udp->uh_ulen = htons(sizeof(struct udphdr) + payload_len);
udp->uh_sum = 0;
pseudo_udp->puh_src.s_addr = src_addr;
pseudo_udp->puh_dst.s_addr = dst_addr;
pseudo_udp->puh_p = IPPROTO_UDP;
pseudo_udp->puh_ulen = htons(sizeof(struct udphdr) + payload_len);
udp->uh_sum = in_cksum((unsigned short *)pseudo_udp,
sizeof(struct udphdr) + sizeof(struct
pseudo_udphdr)
+ payload_len);
/* "destroy" the pseudo udp header because the checksum is
calculated
* and the space is know needed for the ip header */
memset(pseudo_udp, '\0', sizeof(*pseudo_udp));
iphdr->ip_v = 4; /* header version */
iphdr->ip_hl = 0x5; /* header length */
iphdr->ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr)
+ payload_len); /* total length */
iphdr->ip_ttl = 245; /* time to live */
iphdr->ip_p = IPPROTO_UDP;
iphdr->ip_src.s_addr = src_addr;
iphdr->ip_dst.s_addr = dst_addr;
iphdr->ip_sum = 0;
iphdr->ip_sum = in_cksum((u_int16_t *)&packet, sizeof(struct ip));
sin4.sin_family = AF_INET;
sin4.sin_addr.s_addr = dst_addr;
sin4.sin_port = udp->uh_dport;
sockfd = Socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
Setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof
(on));
result = Sendto(sockfd, packet, (sizeof(struct ip) + sizeof
(struct udphdr)
+ payload_len), 0, (struct sockaddr *)&sin4,
(socklen_t)sizeof(struct sockaddr));
return(result);
}
While using this functions I get this error on a FreeBSD system
(RELENG_6_0):
sendto: Invalid argument
If you need the whole source code you can d/l here: http://
www.seekline.net/sile.tar.gz
After building via "make" you can execute the program like this:
./sile_send --src 192.168.0.1 --dst 192.168.0.2 --sport 53 --dport 53
--cmd echo
Then the error should occur.
Best regards, Stefan
More information about the freebsd-net
mailing list