xref: /freebsd/sbin/ipf/ipsend/ip.c (revision 41edb306f05651fcaf6c74f9e3557f59f80292e1)
1*41edb306SCy Schubert /*	$FreeBSD$	*/
2*41edb306SCy Schubert 
3*41edb306SCy Schubert /*
4*41edb306SCy Schubert  * ip.c (C) 1995-1998 Darren Reed
5*41edb306SCy Schubert  *
6*41edb306SCy Schubert  * See the IPFILTER.LICENCE file for details on licencing.
7*41edb306SCy Schubert  */
8*41edb306SCy Schubert #if !defined(lint)
9*41edb306SCy Schubert static const char sccsid[] = "%W% %G% (C)1995";
10*41edb306SCy Schubert static const char rcsid[] = "@(#)$Id$";
11*41edb306SCy Schubert #endif
12*41edb306SCy Schubert #include <sys/param.h>
13*41edb306SCy Schubert #include <sys/types.h>
14*41edb306SCy Schubert #include <netinet/in_systm.h>
15*41edb306SCy Schubert #include <sys/socket.h>
16*41edb306SCy Schubert #include <net/if.h>
17*41edb306SCy Schubert #include <netinet/in.h>
18*41edb306SCy Schubert #include <netinet/ip.h>
19*41edb306SCy Schubert #include <sys/param.h>
20*41edb306SCy Schubert # include <net/route.h>
21*41edb306SCy Schubert # include <netinet/if_ether.h>
22*41edb306SCy Schubert # include <netinet/ip_var.h>
23*41edb306SCy Schubert #include <errno.h>
24*41edb306SCy Schubert #include <stdio.h>
25*41edb306SCy Schubert #include <stdlib.h>
26*41edb306SCy Schubert #include <unistd.h>
27*41edb306SCy Schubert #include <string.h>
28*41edb306SCy Schubert #include "ipsend.h"
29*41edb306SCy Schubert 
30*41edb306SCy Schubert 
31*41edb306SCy Schubert static	char	*ipbuf = NULL, *ethbuf = NULL;
32*41edb306SCy Schubert 
33*41edb306SCy Schubert 
34*41edb306SCy Schubert u_short	chksum(buf,len)
35*41edb306SCy Schubert 	u_short	*buf;
36*41edb306SCy Schubert 	int	len;
37*41edb306SCy Schubert {
38*41edb306SCy Schubert 	u_long	sum = 0;
39*41edb306SCy Schubert 	int	nwords = len >> 1;
40*41edb306SCy Schubert 
41*41edb306SCy Schubert 	for(; nwords > 0; nwords--)
42*41edb306SCy Schubert 		sum += *buf++;
43*41edb306SCy Schubert 	sum = (sum>>16) + (sum & 0xffff);
44*41edb306SCy Schubert 	sum += (sum >>16);
45*41edb306SCy Schubert 	return (~sum);
46*41edb306SCy Schubert }
47*41edb306SCy Schubert 
48*41edb306SCy Schubert 
49*41edb306SCy Schubert int	send_ether(nfd, buf, len, gwip)
50*41edb306SCy Schubert 	int	nfd, len;
51*41edb306SCy Schubert 	char	*buf;
52*41edb306SCy Schubert 	struct	in_addr	gwip;
53*41edb306SCy Schubert {
54*41edb306SCy Schubert 	static	struct	in_addr	last_gw;
55*41edb306SCy Schubert 	static	char	last_arp[6] = { 0, 0, 0, 0, 0, 0};
56*41edb306SCy Schubert 	ether_header_t	*eh;
57*41edb306SCy Schubert 	char	*s;
58*41edb306SCy Schubert 	int	err;
59*41edb306SCy Schubert 
60*41edb306SCy Schubert 	if (!ethbuf)
61*41edb306SCy Schubert 		ethbuf = (char *)calloc(1, 65536+1024);
62*41edb306SCy Schubert 	s = ethbuf;
63*41edb306SCy Schubert 	eh = (ether_header_t *)s;
64*41edb306SCy Schubert 
65*41edb306SCy Schubert 	bcopy((char *)buf, s + sizeof(*eh), len);
66*41edb306SCy Schubert 	if (gwip.s_addr == last_gw.s_addr)
67*41edb306SCy Schubert 	    {
68*41edb306SCy Schubert 		bcopy(last_arp, (char *) &eh->ether_dhost, 6);
69*41edb306SCy Schubert 	    }
70*41edb306SCy Schubert 	else if (arp((char *)&gwip, (char *) &eh->ether_dhost) == -1)
71*41edb306SCy Schubert 	    {
72*41edb306SCy Schubert 		perror("arp");
73*41edb306SCy Schubert 		return -2;
74*41edb306SCy Schubert 	    }
75*41edb306SCy Schubert 	eh->ether_type = htons(ETHERTYPE_IP);
76*41edb306SCy Schubert 	last_gw.s_addr = gwip.s_addr;
77*41edb306SCy Schubert 	err = sendip(nfd, s, sizeof(*eh) + len);
78*41edb306SCy Schubert 	return err;
79*41edb306SCy Schubert }
80*41edb306SCy Schubert 
81*41edb306SCy Schubert 
82*41edb306SCy Schubert /*
83*41edb306SCy Schubert  */
84*41edb306SCy Schubert int	send_ip(nfd, mtu, ip, gwip, frag)
85*41edb306SCy Schubert 	int	nfd, mtu;
86*41edb306SCy Schubert 	ip_t	*ip;
87*41edb306SCy Schubert 	struct	in_addr	gwip;
88*41edb306SCy Schubert 	int	frag;
89*41edb306SCy Schubert {
90*41edb306SCy Schubert 	static	struct	in_addr	last_gw, local_ip;
91*41edb306SCy Schubert 	static	char	local_arp[6] = { 0, 0, 0, 0, 0, 0};
92*41edb306SCy Schubert 	static	char	last_arp[6] = { 0, 0, 0, 0, 0, 0};
93*41edb306SCy Schubert 	static	u_short	id = 0;
94*41edb306SCy Schubert 	ether_header_t	*eh;
95*41edb306SCy Schubert 	ip_t	ipsv;
96*41edb306SCy Schubert 	int	err, iplen;
97*41edb306SCy Schubert 
98*41edb306SCy Schubert 	if (!ipbuf)
99*41edb306SCy Schubert 	  {
100*41edb306SCy Schubert 		ipbuf = (char *)malloc(65536);
101*41edb306SCy Schubert 		if (!ipbuf)
102*41edb306SCy Schubert 		  {
103*41edb306SCy Schubert 			perror("malloc failed");
104*41edb306SCy Schubert 			return -2;
105*41edb306SCy Schubert 		  }
106*41edb306SCy Schubert 	  }
107*41edb306SCy Schubert 
108*41edb306SCy Schubert 	eh = (ether_header_t *)ipbuf;
109*41edb306SCy Schubert 
110*41edb306SCy Schubert 	bzero((char *) &eh->ether_shost, sizeof(eh->ether_shost));
111*41edb306SCy Schubert 	if (last_gw.s_addr && (gwip.s_addr == last_gw.s_addr))
112*41edb306SCy Schubert 	    {
113*41edb306SCy Schubert 		bcopy(last_arp, (char *) &eh->ether_dhost, 6);
114*41edb306SCy Schubert 	    }
115*41edb306SCy Schubert 	else if (arp((char *)&gwip, (char *) &eh->ether_dhost) == -1)
116*41edb306SCy Schubert 	    {
117*41edb306SCy Schubert 		perror("arp");
118*41edb306SCy Schubert 		return -2;
119*41edb306SCy Schubert 	    }
120*41edb306SCy Schubert 	bcopy((char *) &eh->ether_dhost, last_arp, sizeof(last_arp));
121*41edb306SCy Schubert 	eh->ether_type = htons(ETHERTYPE_IP);
122*41edb306SCy Schubert 
123*41edb306SCy Schubert 	bcopy((char *)ip, (char *)&ipsv, sizeof(*ip));
124*41edb306SCy Schubert 	last_gw.s_addr = gwip.s_addr;
125*41edb306SCy Schubert 	iplen = ip->ip_len;
126*41edb306SCy Schubert 	ip->ip_len = htons(iplen);
127*41edb306SCy Schubert 	if (!(frag & 2)) {
128*41edb306SCy Schubert 		if (!IP_V(ip))
129*41edb306SCy Schubert 			IP_V_A(ip, IPVERSION);
130*41edb306SCy Schubert 		if (!ip->ip_id)
131*41edb306SCy Schubert 			ip->ip_id  = htons(id++);
132*41edb306SCy Schubert 		if (!ip->ip_ttl)
133*41edb306SCy Schubert 			ip->ip_ttl = 60;
134*41edb306SCy Schubert 	}
135*41edb306SCy Schubert 
136*41edb306SCy Schubert 	if (ip->ip_src.s_addr != local_ip.s_addr) {
137*41edb306SCy Schubert 		(void) arp((char *)&ip->ip_src, (char *) &local_arp);
138*41edb306SCy Schubert 		bcopy(local_arp, (char *) &eh->ether_shost,sizeof(last_arp));
139*41edb306SCy Schubert 		local_ip = ip->ip_src;
140*41edb306SCy Schubert 	} else
141*41edb306SCy Schubert 		bcopy(local_arp, (char *) &eh->ether_shost, 6);
142*41edb306SCy Schubert 
143*41edb306SCy Schubert 	if (!frag || (sizeof(*eh) + iplen < mtu))
144*41edb306SCy Schubert 	    {
145*41edb306SCy Schubert 		ip->ip_sum = 0;
146*41edb306SCy Schubert 		ip->ip_sum = chksum((u_short *)ip, IP_HL(ip) << 2);
147*41edb306SCy Schubert 
148*41edb306SCy Schubert 		bcopy((char *)ip, ipbuf + sizeof(*eh), iplen);
149*41edb306SCy Schubert 		err =  sendip(nfd, ipbuf, sizeof(*eh) + iplen);
150*41edb306SCy Schubert 	    }
151*41edb306SCy Schubert 	else
152*41edb306SCy Schubert 	    {
153*41edb306SCy Schubert 		/*
154*41edb306SCy Schubert 		 * Actually, this is bogus because we're putting all IP
155*41edb306SCy Schubert 		 * options in every packet, which isn't always what should be
156*41edb306SCy Schubert 		 * done.  Will do for now.
157*41edb306SCy Schubert 		 */
158*41edb306SCy Schubert 		ether_header_t	eth;
159*41edb306SCy Schubert 		char	optcpy[48], ol;
160*41edb306SCy Schubert 		char	*s;
161*41edb306SCy Schubert 		int	i, sent = 0, ts, hlen, olen;
162*41edb306SCy Schubert 
163*41edb306SCy Schubert 		hlen = IP_HL(ip) << 2;
164*41edb306SCy Schubert 		if (mtu < (hlen + 8)) {
165*41edb306SCy Schubert 			fprintf(stderr, "mtu (%d) < ip header size (%d) + 8\n",
166*41edb306SCy Schubert 				mtu, hlen);
167*41edb306SCy Schubert 			fprintf(stderr, "can't fragment data\n");
168*41edb306SCy Schubert 			return -2;
169*41edb306SCy Schubert 		}
170*41edb306SCy Schubert 		ol = (IP_HL(ip) << 2) - sizeof(*ip);
171*41edb306SCy Schubert 		for (i = 0, s = (char*)(ip + 1); ol > 0; )
172*41edb306SCy Schubert 			if (*s == IPOPT_EOL) {
173*41edb306SCy Schubert 				optcpy[i++] = *s;
174*41edb306SCy Schubert 				break;
175*41edb306SCy Schubert 			} else if (*s == IPOPT_NOP) {
176*41edb306SCy Schubert 				s++;
177*41edb306SCy Schubert 				ol--;
178*41edb306SCy Schubert 			} else
179*41edb306SCy Schubert 			    {
180*41edb306SCy Schubert 				olen = (int)(*(u_char *)(s + 1));
181*41edb306SCy Schubert 				ol -= olen;
182*41edb306SCy Schubert 				if (IPOPT_COPIED(*s))
183*41edb306SCy Schubert 				    {
184*41edb306SCy Schubert 					bcopy(s, optcpy + i, olen);
185*41edb306SCy Schubert 					i += olen;
186*41edb306SCy Schubert 					s += olen;
187*41edb306SCy Schubert 				    }
188*41edb306SCy Schubert 			    }
189*41edb306SCy Schubert 		if (i)
190*41edb306SCy Schubert 		    {
191*41edb306SCy Schubert 			/*
192*41edb306SCy Schubert 			 * pad out
193*41edb306SCy Schubert 			 */
194*41edb306SCy Schubert 			while ((i & 3) && (i & 3) != 3)
195*41edb306SCy Schubert 				optcpy[i++] = IPOPT_NOP;
196*41edb306SCy Schubert 			if ((i & 3) == 3)
197*41edb306SCy Schubert 				optcpy[i++] = IPOPT_EOL;
198*41edb306SCy Schubert 		    }
199*41edb306SCy Schubert 
200*41edb306SCy Schubert 		bcopy((char *)eh, (char *)&eth, sizeof(eth));
201*41edb306SCy Schubert 		s = (char *)ip + hlen;
202*41edb306SCy Schubert 		iplen = ntohs(ip->ip_len) - hlen;
203*41edb306SCy Schubert 		ip->ip_off |= htons(IP_MF);
204*41edb306SCy Schubert 
205*41edb306SCy Schubert 		while (1)
206*41edb306SCy Schubert 		    {
207*41edb306SCy Schubert 			if ((sent + (mtu - hlen)) >= iplen)
208*41edb306SCy Schubert 			    {
209*41edb306SCy Schubert 				ip->ip_off ^= htons(IP_MF);
210*41edb306SCy Schubert 				ts = iplen - sent;
211*41edb306SCy Schubert 			    }
212*41edb306SCy Schubert 			else
213*41edb306SCy Schubert 				ts = (mtu - hlen);
214*41edb306SCy Schubert 			ip->ip_off &= htons(0xe000);
215*41edb306SCy Schubert 			ip->ip_off |= htons(sent >> 3);
216*41edb306SCy Schubert 			ts += hlen;
217*41edb306SCy Schubert 			ip->ip_len = htons(ts);
218*41edb306SCy Schubert 			ip->ip_sum = 0;
219*41edb306SCy Schubert 			ip->ip_sum = chksum((u_short *)ip, hlen);
220*41edb306SCy Schubert 			bcopy((char *)ip, ipbuf + sizeof(*eh), hlen);
221*41edb306SCy Schubert 			bcopy(s + sent, ipbuf + sizeof(*eh) + hlen, ts - hlen);
222*41edb306SCy Schubert 			err =  sendip(nfd, ipbuf, sizeof(*eh) + ts);
223*41edb306SCy Schubert 
224*41edb306SCy Schubert 			bcopy((char *)&eth, ipbuf, sizeof(eth));
225*41edb306SCy Schubert 			sent += (ts - hlen);
226*41edb306SCy Schubert 			if (!(ntohs(ip->ip_off) & IP_MF))
227*41edb306SCy Schubert 				break;
228*41edb306SCy Schubert 			else if (!(ip->ip_off & htons(0x1fff)))
229*41edb306SCy Schubert 			    {
230*41edb306SCy Schubert 				hlen = i + sizeof(*ip);
231*41edb306SCy Schubert 				IP_HL_A(ip, (sizeof(*ip) + i) >> 2);
232*41edb306SCy Schubert 				bcopy(optcpy, (char *)(ip + 1), i);
233*41edb306SCy Schubert 			    }
234*41edb306SCy Schubert 		    }
235*41edb306SCy Schubert 	    }
236*41edb306SCy Schubert 
237*41edb306SCy Schubert 	bcopy((char *)&ipsv, (char *)ip, sizeof(*ip));
238*41edb306SCy Schubert 	return err;
239*41edb306SCy Schubert }
240*41edb306SCy Schubert 
241*41edb306SCy Schubert 
242*41edb306SCy Schubert /*
243*41edb306SCy Schubert  * send a tcp packet.
244*41edb306SCy Schubert  */
245*41edb306SCy Schubert int	send_tcp(nfd, mtu, ip, gwip)
246*41edb306SCy Schubert 	int	nfd, mtu;
247*41edb306SCy Schubert 	ip_t	*ip;
248*41edb306SCy Schubert 	struct	in_addr	gwip;
249*41edb306SCy Schubert {
250*41edb306SCy Schubert 	static	tcp_seq	iss = 2;
251*41edb306SCy Schubert 	tcphdr_t *t, *t2;
252*41edb306SCy Schubert 	int	thlen, i, iplen, hlen;
253*41edb306SCy Schubert 	u_32_t	lbuf[20];
254*41edb306SCy Schubert 	ip_t	*ip2;
255*41edb306SCy Schubert 
256*41edb306SCy Schubert 	iplen = ip->ip_len;
257*41edb306SCy Schubert 	hlen = IP_HL(ip) << 2;
258*41edb306SCy Schubert 	t = (tcphdr_t *)((char *)ip + hlen);
259*41edb306SCy Schubert 	ip2 = (struct ip *)lbuf;
260*41edb306SCy Schubert 	t2 = (tcphdr_t *)((char *)ip2 + hlen);
261*41edb306SCy Schubert 	thlen = TCP_OFF(t) << 2;
262*41edb306SCy Schubert 	if (!thlen)
263*41edb306SCy Schubert 		thlen = sizeof(tcphdr_t);
264*41edb306SCy Schubert 	bzero((char *)ip2, sizeof(*ip2) + sizeof(*t2));
265*41edb306SCy Schubert 	ip->ip_p = IPPROTO_TCP;
266*41edb306SCy Schubert 	ip2->ip_p = ip->ip_p;
267*41edb306SCy Schubert 	ip2->ip_src = ip->ip_src;
268*41edb306SCy Schubert 	ip2->ip_dst = ip->ip_dst;
269*41edb306SCy Schubert 	bcopy((char *)ip + hlen, (char *)t2, thlen);
270*41edb306SCy Schubert 
271*41edb306SCy Schubert 	if (!t2->th_win)
272*41edb306SCy Schubert 		t2->th_win = htons(4096);
273*41edb306SCy Schubert 	iss += 63;
274*41edb306SCy Schubert 
275*41edb306SCy Schubert 	i = sizeof(struct tcpiphdr) / sizeof(long);
276*41edb306SCy Schubert 
277*41edb306SCy Schubert 	if ((t2->th_flags == TH_SYN) && !ntohs(ip->ip_off) &&
278*41edb306SCy Schubert 	    (lbuf[i] != htonl(0x020405b4))) {
279*41edb306SCy Schubert 		lbuf[i] = htonl(0x020405b4);
280*41edb306SCy Schubert 		bcopy((char *)ip + hlen + thlen, (char *)ip + hlen + thlen + 4,
281*41edb306SCy Schubert 		      iplen - thlen - hlen);
282*41edb306SCy Schubert 		thlen += 4;
283*41edb306SCy Schubert 	    }
284*41edb306SCy Schubert 	TCP_OFF_A(t2, thlen >> 2);
285*41edb306SCy Schubert 	ip2->ip_len = htons(thlen);
286*41edb306SCy Schubert 	ip->ip_len = hlen + thlen;
287*41edb306SCy Schubert 	t2->th_sum = 0;
288*41edb306SCy Schubert 	t2->th_sum = chksum((u_short *)ip2, thlen + sizeof(ip_t));
289*41edb306SCy Schubert 
290*41edb306SCy Schubert 	bcopy((char *)t2, (char *)ip + hlen, thlen);
291*41edb306SCy Schubert 	return send_ip(nfd, mtu, ip, gwip, 1);
292*41edb306SCy Schubert }
293*41edb306SCy Schubert 
294*41edb306SCy Schubert 
295*41edb306SCy Schubert /*
296*41edb306SCy Schubert  * send a udp packet.
297*41edb306SCy Schubert  */
298*41edb306SCy Schubert int	send_udp(nfd, mtu, ip, gwip)
299*41edb306SCy Schubert 	int	nfd, mtu;
300*41edb306SCy Schubert 	ip_t	*ip;
301*41edb306SCy Schubert 	struct	in_addr	gwip;
302*41edb306SCy Schubert {
303*41edb306SCy Schubert 	struct	tcpiphdr *ti;
304*41edb306SCy Schubert 	int	thlen;
305*41edb306SCy Schubert 	u_long	lbuf[20];
306*41edb306SCy Schubert 
307*41edb306SCy Schubert 	ti = (struct tcpiphdr *)lbuf;
308*41edb306SCy Schubert 	bzero((char *)ti, sizeof(*ti));
309*41edb306SCy Schubert 	thlen = sizeof(udphdr_t);
310*41edb306SCy Schubert 	ti->ti_pr = ip->ip_p;
311*41edb306SCy Schubert 	ti->ti_src = ip->ip_src;
312*41edb306SCy Schubert 	ti->ti_dst = ip->ip_dst;
313*41edb306SCy Schubert 	bcopy((char *)ip + (IP_HL(ip) << 2),
314*41edb306SCy Schubert 	      (char *)&ti->ti_sport, sizeof(udphdr_t));
315*41edb306SCy Schubert 
316*41edb306SCy Schubert 	ti->ti_len = htons(thlen);
317*41edb306SCy Schubert 	ip->ip_len = (IP_HL(ip) << 2) + thlen;
318*41edb306SCy Schubert 	ti->ti_sum = 0;
319*41edb306SCy Schubert 	ti->ti_sum = chksum((u_short *)ti, thlen + sizeof(ip_t));
320*41edb306SCy Schubert 
321*41edb306SCy Schubert 	bcopy((char *)&ti->ti_sport,
322*41edb306SCy Schubert 	      (char *)ip + (IP_HL(ip) << 2), sizeof(udphdr_t));
323*41edb306SCy Schubert 	return send_ip(nfd, mtu, ip, gwip, 1);
324*41edb306SCy Schubert }
325*41edb306SCy Schubert 
326*41edb306SCy Schubert 
327*41edb306SCy Schubert /*
328*41edb306SCy Schubert  * send an icmp packet.
329*41edb306SCy Schubert  */
330*41edb306SCy Schubert int	send_icmp(nfd, mtu, ip, gwip)
331*41edb306SCy Schubert 	int	nfd, mtu;
332*41edb306SCy Schubert 	ip_t	*ip;
333*41edb306SCy Schubert 	struct	in_addr	gwip;
334*41edb306SCy Schubert {
335*41edb306SCy Schubert 	struct	icmp	*ic;
336*41edb306SCy Schubert 
337*41edb306SCy Schubert 	ic = (struct icmp *)((char *)ip + (IP_HL(ip) << 2));
338*41edb306SCy Schubert 
339*41edb306SCy Schubert 	ic->icmp_cksum = 0;
340*41edb306SCy Schubert 	ic->icmp_cksum = chksum((u_short *)ic, sizeof(struct icmp));
341*41edb306SCy Schubert 
342*41edb306SCy Schubert 	return send_ip(nfd, mtu, ip, gwip, 1);
343*41edb306SCy Schubert }
344*41edb306SCy Schubert 
345*41edb306SCy Schubert 
346*41edb306SCy Schubert int	send_packet(nfd, mtu, ip, gwip)
347*41edb306SCy Schubert 	int	nfd, mtu;
348*41edb306SCy Schubert 	ip_t	*ip;
349*41edb306SCy Schubert 	struct	in_addr	gwip;
350*41edb306SCy Schubert {
351*41edb306SCy Schubert         switch (ip->ip_p)
352*41edb306SCy Schubert         {
353*41edb306SCy Schubert         case IPPROTO_TCP :
354*41edb306SCy Schubert                 return send_tcp(nfd, mtu, ip, gwip);
355*41edb306SCy Schubert         case IPPROTO_UDP :
356*41edb306SCy Schubert                 return send_udp(nfd, mtu, ip, gwip);
357*41edb306SCy Schubert         case IPPROTO_ICMP :
358*41edb306SCy Schubert                 return send_icmp(nfd, mtu, ip, gwip);
359*41edb306SCy Schubert         default :
360*41edb306SCy Schubert                 return send_ip(nfd, mtu, ip, gwip, 1);
361*41edb306SCy Schubert         }
362*41edb306SCy Schubert }
363