summaryrefslogtreecommitdiffstats
path: root/contrib/ipfilter/ipsend/ipsend.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ipfilter/ipsend/ipsend.c')
-rw-r--r--contrib/ipfilter/ipsend/ipsend.c83
1 files changed, 67 insertions, 16 deletions
diff --git a/contrib/ipfilter/ipsend/ipsend.c b/contrib/ipfilter/ipsend/ipsend.c
index 8c9be57..80faef2 100644
--- a/contrib/ipfilter/ipsend/ipsend.c
+++ b/contrib/ipfilter/ipsend/ipsend.c
@@ -25,8 +25,10 @@
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
+#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
+#include <netinet/udp_var.h>
#include <netinet/ip_icmp.h>
#ifndef linux
#include <netinet/ip_var.h>
@@ -71,6 +73,7 @@ char default_device[] = "lan0";
static void usage __P((char *));
static void do_icmp __P((ip_t *, char *));
+void udpcksum(ip_t *, struct udphdr *, int);
int main __P((int, char **));
@@ -170,6 +173,37 @@ struct in_addr gwip;
return send_packet(wfd, mtu, ip, gwip);
}
+void
+udpcksum(ip_t *ip, struct udphdr *udp, int len)
+{
+ union pseudoh {
+ struct hdr {
+ u_short len;
+ u_char ttl;
+ u_char proto;
+ u_32_t src;
+ u_32_t dst;
+ } h;
+ u_short w[6];
+ } ph;
+ u_32_t temp32;
+ u_short cksum, *opts;
+
+ ph.h.len = htons(len);
+ ph.h.ttl = 0;
+ ph.h.proto = IPPROTO_UDP;
+ ph.h.src = ip->ip_src.s_addr;
+ ph.h.dst = ip->ip_dst.s_addr;
+ temp32 = 0;
+ opts = &ph.w[0];
+ temp32 += opts[0] + opts[1] + opts[2] + opts[3] + opts[4] + opts[5];
+ temp32 = (temp32 >> 16) + (temp32 & 65535);
+ temp32 += (temp32 >> 16);
+ udp->uh_sum = temp32 & 65535;
+ udp->uh_sum = chksum((u_short *)udp, len);
+ if (udp->uh_sum == 0)
+ udp->uh_sum = 0xffff;
+}
int main(argc, argv)
int argc;
@@ -177,8 +211,10 @@ char **argv;
{
FILE *langfile = NULL;
struct tcpiphdr *ti;
+ struct udpiphdr *ui;
struct in_addr gwip;
tcphdr_t *tcp;
+ udphdr_t *udp;
ip_t *ip;
char *name = argv[0], host[MAXHOSTNAMELEN + 1];
char *gateway = NULL, *dev = NULL;
@@ -190,7 +226,10 @@ char **argv;
*/
ip = (ip_t *)calloc(1, 65536);
ti = (struct tcpiphdr *)ip;
+ ui = (struct udpiphdr *)ip;
tcp = (tcphdr_t *)&ti->ti_sport;
+ udp = (udphdr_t *)&ui->ui_sport;
+ ui->ui_ulen = htons(sizeof(*udp));
ip->ip_len = sizeof(*ip);
ip->ip_hl = sizeof(*ip) >> 2;
@@ -344,27 +383,35 @@ char **argv;
exit(2);
}
+ if (ip->ip_p != IPPROTO_TCP && ip->ip_p != IPPROTO_UDP) {
+ fprintf(stderr,"Unsupported protocol %d\n", ip->ip_p);
+ exit(2);
+ }
+
if (olen)
{
- caddr_t ipo = (caddr_t)ip;
+ int hlen;
+ char *p;
printf("Options: %d\n", olen);
- ti = (struct tcpiphdr *)malloc(olen + ip->ip_len);
- if(!ti)
+ hlen = sizeof(*ip) + olen;
+ ip->ip_hl = hlen >> 2;
+ ip->ip_len += olen;
+ p = (char *)malloc(65536);
+ if(!p)
{
fprintf(stderr,"malloc failed\n");
exit(2);
}
-
- bcopy((char *)ip, (char *)ti, sizeof(*ip));
- ip = (ip_t *)ti;
- ip->ip_hl = (olen >> 2);
- bcopy(options, (char *)(ip + 1), olen);
- bcopy((char *)tcp, (char *)(ip + 1) + olen, sizeof(*tcp));
- ip->ip_len += olen;
- bcopy((char *)ip, (char *)ipo, ip->ip_len);
- ip = (ip_t *)ipo;
- tcp = (tcphdr_t *)((char *)(ip + 1) + olen);
+ bcopy(ip, p, sizeof(*ip));
+ bcopy(options, p + sizeof(*ip), olen);
+ bcopy(ip + 1, p + hlen, ip->ip_len - hlen);
+ ip = (ip_t *)p;
+ if (ip->ip_p == IPPROTO_TCP) {
+ tcp = (tcphdr_t *)((char *)ip + hlen);
+ } else {
+ udp = (udphdr_t *)((char *)ip + hlen);
+ }
}
if (ip->ip_p == IPPROTO_TCP)
@@ -401,9 +448,13 @@ char **argv;
printf("Flags: %#x\n", tcp->th_flags);
printf("mtu: %d\n", mtu);
+ if (ip->ip_p == IPPROTO_UDP) {
+ udp->uh_sum = 0;
+ udpcksum(ip, udp, (ip->ip_len) - (ip->ip_hl << 2));
+ }
#ifdef DOSOCKET
- if (tcp->th_dport)
- return do_socket(dev, mtu, ti, gwip);
+ if (ip->ip_p == IPPROTO_TCP && tcp->th_dport)
+ return do_socket(dev, mtu, (struct tcpiphdr *)ip, gwip);
#endif
- return send_packets(dev, mtu, (ip_t *)ti, gwip);
+ return send_packets(dev, mtu, ip, gwip);
}
OpenPOWER on IntegriCloud