Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 Apr 2006 14:44:02 +0200
From:      Stefan <stefan@sf-net.com>
To:        =?UTF-8?Q?JINMEI_Tatuya_/_=E7=A5=9E=E6=98=8E=E9=81=94=E5=93=89?= <jinmei@isl.rdc.toshiba.co.jp>
Cc:        freebsd-net@freebsd.org
Subject:   Re: raw ip paket sendto error
Message-ID:  <C34AC449-D9BA-4157-89B0-BBBCF576EB4C@sf-net.com>
In-Reply-To: <y7virpgjrhk.wl%jinmei@isl.rdc.toshiba.co.jp>
References:  <F8D644AB-76D0-49B6-A665-6B459A13F85D@sf-net.com> <y7vslokk17u.wl%jinmei@isl.rdc.toshiba.co.jp> <03F2063D-0333-482C-ADD5-914D162E92C0@sf-net.com> <y7virpgjrhk.wl%jinmei@isl.rdc.toshiba.co.jp>

next in thread | previous in thread | raw e-mail | index | archive | help
>
> 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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?C34AC449-D9BA-4157-89B0-BBBCF576EB4C>