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