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