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>