1 /* $NetBSD: ip.c,v 1.8 2007/04/14 20:34:22 martin Exp $ */
4 * ip.c (C) 1995-1998 Darren Reed
6 * See the IPFILTER.LICENCE file for details on licencing.
9 static const char sccsid
[] = "%W% %G% (C)1995";
10 static const char rcsid
[] = "@(#)Id: ip.c,v 2.8.2.2 2007/02/17 12:41:51 darrenr Exp";
12 #include <sys/param.h>
13 #include <sys/types.h>
14 #include <netinet/in_systm.h>
15 #include <sys/socket.h>
17 # include "radix_ipf_local.h"
20 #include <netinet/in.h>
21 #include <netinet/ip.h>
22 #include <sys/param.h>
24 # include <netinet/if_ether.h>
25 # include <netinet/ip_var.h>
26 # if __FreeBSD_version >= 300000
27 # include <net/if_var.h>
38 static char *ipbuf
= NULL
, *ethbuf
= NULL
;
41 u_short
chksum(buf
,len
)
46 int nwords
= len
>> 1;
48 for(; nwords
> 0; nwords
--)
50 sum
= (sum
>>16) + (sum
& 0xffff);
56 int send_ether(nfd
, buf
, len
, gwip
)
61 static struct in_addr last_gw
;
62 static char last_arp
[6] = { 0, 0, 0, 0, 0, 0};
68 ethbuf
= (char *)calloc(1, 65536+1024);
70 eh
= (ether_header_t
*)s
;
72 bcopy((char *)buf
, s
+ sizeof(*eh
), len
);
73 if (gwip
.s_addr
== last_gw
.s_addr
)
75 bcopy(last_arp
, (char *)A_A eh
->ether_dhost
, 6);
77 else if (arp((char *)&gwip
, (char *)A_A eh
->ether_dhost
) == -1)
82 eh
->ether_type
= htons(ETHERTYPE_IP
);
83 last_gw
.s_addr
= gwip
.s_addr
;
84 err
= sendip(nfd
, s
, sizeof(*eh
) + len
);
91 int send_ip(nfd
, mtu
, ip
, gwip
, frag
)
97 static struct in_addr last_gw
, local_ip
;
98 static char local_arp
[6] = { 0, 0, 0, 0, 0, 0};
99 static char last_arp
[6] = { 0, 0, 0, 0, 0, 0};
100 static u_short id
= 0;
107 ipbuf
= (char *)malloc(65536);
110 perror("malloc failed");
115 eh
= (ether_header_t
*)ipbuf
;
117 bzero((char *)A_A eh
->ether_shost
, sizeof(eh
->ether_shost
));
118 if (last_gw
.s_addr
&& (gwip
.s_addr
== last_gw
.s_addr
))
120 bcopy(last_arp
, (char *)A_A eh
->ether_dhost
, 6);
122 else if (arp((char *)&gwip
, (char *)A_A eh
->ether_dhost
) == -1)
127 bcopy((char *)A_A eh
->ether_dhost
, last_arp
, sizeof(last_arp
));
128 eh
->ether_type
= htons(ETHERTYPE_IP
);
130 bcopy((char *)ip
, (char *)&ipsv
, sizeof(*ip
));
131 last_gw
.s_addr
= gwip
.s_addr
;
133 ip
->ip_len
= htons(iplen
);
136 IP_V_A(ip
, IPVERSION
);
138 ip
->ip_id
= htons(id
++);
143 if (ip
->ip_src
.s_addr
!= local_ip
.s_addr
) {
144 (void) arp((char *)&ip
->ip_src
, (char *)A_A local_arp
);
145 bcopy(local_arp
, (char *)A_A eh
->ether_shost
,sizeof(last_arp
));
146 local_ip
= ip
->ip_src
;
148 bcopy(local_arp
, (char *)A_A eh
->ether_shost
, 6);
150 if (!frag
|| (sizeof(*eh
) + iplen
< mtu
))
153 ip
->ip_sum
= chksum((u_short
*)ip
, IP_HL(ip
) << 2);
155 bcopy((char *)ip
, ipbuf
+ sizeof(*eh
), iplen
);
156 err
= sendip(nfd
, ipbuf
, sizeof(*eh
) + iplen
);
161 * Actually, this is bogus because we're putting all IP
162 * options in every packet, which isn't always what should be
163 * done. Will do for now.
168 int i
, sent
= 0, ts
, hlen
, olen
;
170 hlen
= IP_HL(ip
) << 2;
171 if (mtu
< (hlen
+ 8)) {
172 fprintf(stderr
, "mtu (%d) < ip header size (%d) + 8\n",
174 fprintf(stderr
, "can't fragment data\n");
177 ol
= (IP_HL(ip
) << 2) - sizeof(*ip
);
178 for (i
= 0, s
= (char*)(ip
+ 1); ol
> 0; )
179 if (*s
== IPOPT_EOL
) {
182 } else if (*s
== IPOPT_NOP
) {
187 olen
= (int)(*(u_char
*)(s
+ 1));
189 if (IPOPT_COPIED(*s
))
191 bcopy(s
, optcpy
+ i
, olen
);
201 while ((i
& 3) && (i
& 3) != 3)
202 optcpy
[i
++] = IPOPT_NOP
;
204 optcpy
[i
++] = IPOPT_EOL
;
207 bcopy((char *)eh
, (char *)ð
, sizeof(eth
));
208 s
= (char *)ip
+ hlen
;
209 iplen
= ntohs(ip
->ip_len
) - hlen
;
210 ip
->ip_off
|= htons(IP_MF
);
214 if ((sent
+ (mtu
- hlen
)) >= iplen
)
216 ip
->ip_off
^= htons(IP_MF
);
221 ip
->ip_off
&= htons(0xe000);
222 ip
->ip_off
|= htons(sent
>> 3);
224 ip
->ip_len
= htons(ts
);
226 ip
->ip_sum
= chksum((u_short
*)ip
, hlen
);
227 bcopy((char *)ip
, ipbuf
+ sizeof(*eh
), hlen
);
228 bcopy(s
+ sent
, ipbuf
+ sizeof(*eh
) + hlen
, ts
- hlen
);
229 err
= sendip(nfd
, ipbuf
, sizeof(*eh
) + ts
);
231 bcopy((char *)ð
, ipbuf
, sizeof(eth
));
233 if (!(ntohs(ip
->ip_off
) & IP_MF
))
235 else if (!(ip
->ip_off
& htons(0x1fff)))
237 hlen
= i
+ sizeof(*ip
);
238 IP_HL_A(ip
, (sizeof(*ip
) + i
) >> 2);
239 bcopy(optcpy
, (char *)(ip
+ 1), i
);
244 bcopy((char *)&ipsv
, (char *)ip
, sizeof(*ip
));
252 int send_tcp(nfd
, mtu
, ip
, gwip
)
257 static tcp_seq iss
= 2;
259 int thlen
, i
, iplen
, hlen
;
264 hlen
= IP_HL(ip
) << 2;
265 t
= (tcphdr_t
*)((char *)ip
+ hlen
);
266 ip2
= (struct ip
*)lbuf
;
267 t2
= (tcphdr_t
*)((char *)ip2
+ sizeof(ip_t
));
268 thlen
= TCP_OFF(t
) << 2;
270 thlen
= sizeof(tcphdr_t
);
271 bzero((char *)ip2
, sizeof(*ip2
) + sizeof(*t2
));
272 ip
->ip_p
= IPPROTO_TCP
;
273 ip2
->ip_p
= ip
->ip_p
;
274 ip2
->ip_src
= ip
->ip_src
;
275 ip2
->ip_dst
= ip
->ip_dst
;
276 bcopy((char *)ip
+ hlen
, (char *)t2
, thlen
);
279 t2
->th_win
= htons(4096);
282 i
= sizeof(struct tcpiphdr
) / sizeof(long);
284 if ((t2
->th_flags
== TH_SYN
) && !ntohs(ip
->ip_off
) &&
285 (lbuf
[i
] != htonl(0x020405b4))) {
286 lbuf
[i
] = htonl(0x020405b4);
287 bcopy((char *)ip
+ hlen
+ thlen
, (char *)ip
+ hlen
+ thlen
+ 4,
288 iplen
- thlen
- hlen
);
291 TCP_OFF_A(t2
, thlen
>> 2);
292 ip2
->ip_len
= htons(thlen
);
293 ip
->ip_len
= hlen
+ thlen
;
295 t2
->th_sum
= chksum((u_short
*)ip2
, thlen
+ sizeof(ip_t
));
297 bcopy((char *)t2
, (char *)ip
+ hlen
, thlen
);
298 return send_ip(nfd
, mtu
, ip
, gwip
, 1);
305 int send_udp(nfd
, mtu
, ip
, gwip
)
314 ti
= (struct tcpiphdr
*)lbuf
;
315 bzero((char *)ti
, sizeof(*ti
));
316 thlen
= sizeof(udphdr_t
);
317 ti
->ti_pr
= ip
->ip_p
;
318 ti
->ti_src
= ip
->ip_src
;
319 ti
->ti_dst
= ip
->ip_dst
;
320 bcopy((char *)ip
+ (IP_HL(ip
) << 2),
321 (char *)&ti
->ti_sport
, sizeof(udphdr_t
));
323 ti
->ti_len
= htons(thlen
);
324 ip
->ip_len
= (IP_HL(ip
) << 2) + thlen
;
326 ti
->ti_sum
= chksum((u_short
*)ti
, thlen
+ sizeof(ip_t
));
328 bcopy((char *)&ti
->ti_sport
,
329 (char *)ip
+ (IP_HL(ip
) << 2), sizeof(udphdr_t
));
330 return send_ip(nfd
, mtu
, ip
, gwip
, 1);
335 * send an icmp packet.
337 int send_icmp(nfd
, mtu
, ip
, gwip
)
344 ic
= (struct icmp
*)((char *)ip
+ (IP_HL(ip
) << 2));
347 ic
->icmp_cksum
= chksum((u_short
*)ic
, sizeof(struct icmp
));
349 return send_ip(nfd
, mtu
, ip
, gwip
, 1);
353 int send_packet(nfd
, mtu
, ip
, gwip
)
361 return send_tcp(nfd
, mtu
, ip
, gwip
);
363 return send_udp(nfd
, mtu
, ip
, gwip
);
365 return send_icmp(nfd
, mtu
, ip
, gwip
);
367 return send_ip(nfd
, mtu
, ip
, gwip
, 1);