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