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