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