99 100 /* 101 * Open the NAT device and lookup the mapping pair. 102 */ 103 fd = open(IPNAT_NAME, O_RDONLY); 104 if (ioctl(fd, SIOCGNATL, &obj) == -1) { 105 perror("ioctl(SIOCGNATL)"); 106 exit(-1); 107 } 108 109#define DO_NAT_OUT 110#ifdef DO_NAT_OUT 111 if (argc > 1) 112 do_nat_out(0, 1, fd, &natlook, argv[1]); 113#else 114 115 /* 116 * Log it 117 */ 118 syslog(LOG_DAEMON|LOG_INFO, "connect to %s,%d", 119 inet_ntoa(natlook.nl_realip), ntohs(natlook.nl_realport)); 120 printf("connect to %s,%d\n", 121 inet_ntoa(natlook.nl_realip), ntohs(natlook.nl_realport)); 122 123 /* 124 * Just echo data read in from stdin to stdout 125 */ 126 while ((n = read(0, buffer, sizeof(buffer))) > 0) 127 if (write(1, buffer, n) != n) 128 break; 129 close(0); 130#endif 131} 132 133 134#ifdef DO_NAT_OUT 135do_nat_out(in, out, fd, nlp, extif) 136int fd; 137natlookup_t *nlp; 138char *extif; 139{ 140 nat_save_t ns, *nsp = &ns; 141 struct sockaddr_in usin; 142 u_32_t sum1, sum2, sumd; 143 int onoff, ofd, slen; 144 ipfobj_t obj; 145 ipnat_t *ipn; 146 nat_t *nat; 147 148 bzero((char *)&ns, sizeof(ns)); 149 150 nat = &ns.ipn_nat; 151 nat->nat_p = IPPROTO_TCP; 152 nat->nat_dir = NAT_OUTBOUND; 153 if ((extif != NULL) && (*extif != '\0')) { 154 strncpy(nat->nat_ifnames[0], extif, 155 sizeof(nat->nat_ifnames[0])); 156 strncpy(nat->nat_ifnames[1], extif, 157 sizeof(nat->nat_ifnames[1])); 158 nat->nat_ifnames[0][sizeof(nat->nat_ifnames[0]) - 1] = '\0'; 159 nat->nat_ifnames[1][sizeof(nat->nat_ifnames[1]) - 1] = '\0'; 160 } 161 162 ofd = socket(AF_INET, SOCK_DGRAM, 0); 163 bzero((char *)&usin, sizeof(usin)); 164 usin.sin_family = AF_INET; 165 usin.sin_addr = nlp->nl_realip; 166 usin.sin_port = nlp->nl_realport; 167 (void) connect(ofd, (struct sockaddr *)&usin, sizeof(usin)); 168 slen = sizeof(usin); 169 (void) getsockname(ofd, (struct sockaddr *)&usin, &slen); 170 close(ofd); 171printf("local IP# to use: %s\n", inet_ntoa(usin.sin_addr)); 172 173 if ((ofd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 174 perror("socket"); 175 usin.sin_port = 0; 176 if (bind(ofd, (struct sockaddr *)&usin, sizeof(usin))) 177 perror("bind"); 178 slen = sizeof(usin); 179 if (getsockname(ofd, (struct sockaddr *)&usin, &slen)) 180 perror("getsockname"); 181printf("local port# to use: %d\n", ntohs(usin.sin_port)); 182 183 nat->nat_inip = usin.sin_addr; 184 nat->nat_outip = nlp->nl_outip; 185 nat->nat_oip = nlp->nl_realip; 186 187 sum1 = LONG_SUM(ntohl(usin.sin_addr.s_addr)) + ntohs(usin.sin_port); 188 sum2 = LONG_SUM(ntohl(nat->nat_outip.s_addr)) + ntohs(nlp->nl_outport); 189 CALC_SUMD(sum1, sum2, sumd); 190 nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16); 191 nat->nat_sumd[1] = nat->nat_sumd[0]; 192 193 sum1 = LONG_SUM(ntohl(usin.sin_addr.s_addr)); 194 sum2 = LONG_SUM(ntohl(nat->nat_outip.s_addr)); 195 CALC_SUMD(sum1, sum2, sumd); 196 nat->nat_ipsumd = (sumd & 0xffff) + (sumd >> 16); 197 198 nat->nat_inport = usin.sin_port; 199 nat->nat_outport = nlp->nl_outport; 200 nat->nat_oport = nlp->nl_realport; 201 202 nat->nat_flags = IPN_TCPUDP; 203 204 bzero((char *)&obj, sizeof(obj)); 205 obj.ipfo_rev = IPFILTER_VERSION; 206 obj.ipfo_size = sizeof(*nsp); 207 obj.ipfo_ptr = nsp; 208 obj.ipfo_type = IPFOBJ_NATSAVE; 209 210 onoff = 1; 211 if (ioctl(fd, SIOCSTLCK, &onoff) == 0) { 212 if (ioctl(fd, SIOCSTPUT, &obj) != 0) 213 perror("SIOCSTPUT"); 214 onoff = 0; 215 if (ioctl(fd, SIOCSTLCK, &onoff) != 0) 216 perror("SIOCSTLCK"); 217 } 218 219 usin.sin_addr = nlp->nl_realip; 220 usin.sin_port = nlp->nl_realport; 221printf("remote end for connection: %s,%d\n", inet_ntoa(usin.sin_addr), 222ntohs(usin.sin_port)); 223fflush(stdout); 224 if (connect(ofd, (struct sockaddr *)&usin, sizeof(usin))) 225 perror("connect"); 226 227 relay(in, out, ofd); 228} 229 230 231relay(in, out, net) 232int in, out, net; 233{ 234 char netbuf[1024], outbuf[1024]; 235 char *nwptr, *nrptr, *owptr, *orptr; 236 size_t nsz, osz; 237 fd_set rd, wr; 238 int i, n, maxfd; 239 240 n = 0; 241 maxfd = in; 242 if (out > maxfd) 243 maxfd = out; 244 if (net > maxfd) 245 maxfd = net; 246 247 nrptr = netbuf; 248 nwptr = netbuf; 249 nsz = sizeof(netbuf); 250 orptr = outbuf; 251 owptr = outbuf; 252 osz = sizeof(outbuf); 253 254 while (n >= 0) { 255 FD_ZERO(&rd); 256 FD_ZERO(&wr); 257 258 if (nrptr - netbuf < sizeof(netbuf)) 259 FD_SET(in, &rd); 260 if (orptr - outbuf < sizeof(outbuf)) 261 FD_SET(net, &rd); 262 263 if (nsz < sizeof(netbuf)) 264 FD_SET(net, &wr); 265 if (osz < sizeof(outbuf)) 266 FD_SET(out, &wr); 267 268 n = select(maxfd + 1, &rd, &wr, NULL, NULL); 269 270 if ((n > 0) && FD_ISSET(in, &rd)) { 271 i = read(in, nrptr, sizeof(netbuf) - (nrptr - netbuf)); 272 if (i <= 0) 273 break; 274 nsz -= i; 275 nrptr += i; 276 n--; 277 } 278 279 if ((n > 0) && FD_ISSET(net, &rd)) { 280 i = read(net, orptr, sizeof(outbuf) - (orptr - outbuf)); 281 if (i <= 0) 282 break; 283 osz -= i; 284 orptr += i; 285 n--; 286 } 287 288 if ((n > 0) && FD_ISSET(out, &wr)) { 289 i = write(out, owptr, orptr - owptr); 290 if (i <= 0) 291 break; 292 osz += i; 293 if (osz == sizeof(outbuf) || owptr == orptr) { 294 orptr = outbuf; 295 owptr = outbuf; 296 } else 297 owptr += i; 298 n--; 299 } 300 301 if ((n > 0) && FD_ISSET(net, &wr)) { 302 i = write(net, nwptr, nrptr - nwptr); 303 if (i <= 0) 304 break; 305 nsz += i; 306 if (nsz == sizeof(netbuf) || nwptr == nrptr) { 307 nrptr = netbuf; 308 nwptr = netbuf; 309 } else 310 nwptr += i; 311 } 312 } 313 314 close(net); 315 close(out); 316 close(in); 317} 318#endif
|