1/* $NetBSD: sock.c,v 1.20 2012/02/15 17:55:05 riz Exp $ */ 2 3/* 4 * sock.c (C) 1995-1998 Darren Reed 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 * 8 */ 9#if !defined(lint) 10static const char sccsid[] = "@(#)sock.c 1.2 1/11/96 (C)1995 Darren Reed"; 11static const char rcsid[] = "@(#)Id: sock.c,v 2.8.4.9 2009/12/27 06:53:15 darrenr Exp"; 12#endif 13#include <sys/param.h> 14#include <sys/types.h> 15#include <sys/time.h> 16#include <sys/stat.h> 17#include <stdbool.h> 18#if defined(__NetBSD__) && defined(__vax__) 19/* 20 * XXX need to declare boolean_t for _KERNEL <sys/files.h> 21 * which ends up including <sys/device.h> for vax. See PR#32907 22 * for further details. 23 */ 24typedef int boolean_t; 25#endif 26#ifndef ultrix 27#include <fcntl.h> 28#endif 29#if (__FreeBSD_version >= 300000) 30# include <sys/dirent.h> 31#else 32# include <sys/dir.h> 33#endif 34#if !defined(__osf__) 35# ifdef __NetBSD__ 36# include <machine/lock.h> 37# include <sys/mutex.h> 38# endif 39# define _KERNEL 40# define KERNEL 41# ifdef ultrix 42# undef LOCORE 43# include <sys/smp_lock.h> 44# endif 45# include <sys/file.h> 46# undef _KERNEL 47# undef KERNEL 48#endif 49#include <nlist.h> 50#include <sys/user.h> 51#include <sys/socket.h> 52#include <sys/socketvar.h> 53#include <sys/proc.h> 54#if !defined(ultrix) && !defined(hpux) && !defined(__osf__) 55# include <kvm.h> 56#endif 57#ifdef sun 58#include <sys/systm.h> 59#include <sys/session.h> 60#endif 61#if BSD >= 199103 62#include <sys/sysctl.h> 63#include <sys/filedesc.h> 64#include <paths.h> 65#endif 66#include <math.h> 67#include <netinet/in.h> 68#include <netinet/in_systm.h> 69#include <netinet/ip.h> 70#include <netinet/tcp.h> 71#include <net/if.h> 72#if defined(__FreeBSD__) 73# include "radix_ipf.h" 74#endif 75#ifndef __osf__ 76# include <net/route.h> 77#endif 78#include <netinet/ip_var.h> 79#include <netinet/in_pcb.h> 80#include <netinet/tcp_timer.h> 81#include <netinet/tcp_var.h> 82#include <stdio.h> 83#include <unistd.h> 84#include <string.h> 85#include <stdlib.h> 86#include <stddef.h> 87#include <pwd.h> 88#include "ipsend.h" 89 90 91int nproc; 92struct proc *proc; 93 94#ifndef KMEM 95# ifdef _PATH_KMEM 96# define KMEM _PATH_KMEM 97# endif 98#endif 99#ifndef KERNEL 100# ifdef _PATH_UNIX 101# define KERNEL _PATH_UNIX 102# endif 103#endif 104#ifndef KMEM 105# define KMEM "/dev/kmem" 106#endif 107#ifndef KERNEL 108# define KERNEL "/vmunix" 109#endif 110 111 112#if BSD < 199103 113static struct proc *getproc __P((void)); 114#else 115static struct kinfo_proc *getproc __P((void)); 116#endif 117 118 119int kmemcpy(buf, pos, n) 120char *buf; 121void *pos; 122int n; 123{ 124 static int kfd = -1; 125 off_t offset = (u_long)pos; 126 127 if (kfd == -1) 128 kfd = open(KMEM, O_RDONLY); 129 130 if (lseek(kfd, offset, SEEK_SET) == -1) 131 { 132 perror("lseek"); 133 return -1; 134 } 135 if (read(kfd, buf, n) == -1) 136 { 137 perror("read"); 138 return -1; 139 } 140 return n; 141} 142 143struct nlist names[4] = { 144 { "_proc" }, 145 { "_nproc" }, 146#ifdef ultrix 147 { "_u" }, 148#else 149 { NULL }, 150#endif 151 { NULL } 152 }; 153 154#if BSD < 199103 155static struct proc *getproc() 156{ 157 struct proc *p; 158 pid_t pid = getpid(); 159 int siz, n; 160 161 n = nlist(KERNEL, names); 162 if (n != 0) 163 { 164 fprintf(stderr, "nlist(%#x) == %d\n", names, n); 165 return NULL; 166 } 167 if (KMCPY(&nproc, names[1].n_value, sizeof(nproc)) == -1) 168 { 169 fprintf(stderr, "read nproc (%#x)\n", names[1].n_value); 170 return NULL; 171 } 172 siz = nproc * sizeof(struct proc); 173 if (KMCPY(&p, names[0].n_value, sizeof(p)) == -1) 174 { 175 fprintf(stderr, "read(%#x,%#x,%d) proc\n", 176 names[0].n_value, &p, sizeof(p)); 177 return NULL; 178 } 179 proc = (struct proc *)malloc(siz); 180 if (KMCPY(proc, p, siz) == -1) 181 { 182 fprintf(stderr, "read(%#x,%#x,%d) proc\n", 183 p, proc, siz); 184 return NULL; 185 } 186 187 p = proc; 188 189 for (n = nproc; n; n--, p++) 190 if (p->p_pid == pid) 191 break; 192 if (!n) 193 return NULL; 194 195 return p; 196} 197 198 199struct tcpcb *find_tcp(fd, ti) 200int fd; 201struct tcpiphdr *ti; 202{ 203 struct tcpcb *t; 204 struct inpcb *i; 205 struct socket *s; 206 struct user *up; 207 struct proc *p; 208 struct file *f, **o; 209 210 if (!(p = getproc())) 211 return NULL; 212 up = (struct user *)malloc(sizeof(*up)); 213#ifndef ultrix 214 if (KMCPY(up, p->p_uarea, sizeof(*up)) == -1) 215 { 216 fprintf(stderr, "read(%#x,%#x) failed\n", p, p->p_uarea); 217 return NULL; 218 } 219#else 220 if (KMCPY(up, names[2].n_value, sizeof(*up)) == -1) 221 { 222 fprintf(stderr, "read(%#x,%#x) failed\n", p, names[2].n_value); 223 return NULL; 224 } 225#endif 226 227 o = (struct file **)calloc(1, sizeof(*o) * (up->u_lastfile + 1)); 228 if (KMCPY(o, up->u_ofile, (up->u_lastfile + 1) * sizeof(*o)) == -1) 229 { 230 fprintf(stderr, "read(%#x,%#x,%d) - u_ofile - failed\n", 231 up->u_ofile, o, sizeof(*o)); 232 return NULL; 233 } 234 f = (struct file *)calloc(1, sizeof(*f)); 235 if (KMCPY(f, o[fd], sizeof(*f)) == -1) 236 { 237 fprintf(stderr, "read(%#x,%#x,%d) - o[fd] - failed\n", 238 up->u_ofile[fd], f, sizeof(*f)); 239 return NULL; 240 } 241 242 s = (struct socket *)calloc(1, sizeof(*s)); 243 if (KMCPY(s, f->f_data, sizeof(*s)) == -1) 244 { 245 fprintf(stderr, "read(%#x,%#x,%d) - f_data - failed\n", 246 o[fd], s, sizeof(*s)); 247 return NULL; 248 } 249 250 i = (struct inpcb *)calloc(1, sizeof(*i)); 251 if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1) 252 { 253 fprintf(stderr, "kvm_read(%#x,%#x,%d) - so_pcb - failed\n", 254 s->so_pcb, i, sizeof(*i)); 255 return NULL; 256 } 257 258 t = (struct tcpcb *)calloc(1, sizeof(*t)); 259 if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1) 260 { 261 fprintf(stderr, "read(%#x,%#x,%d) - inp_ppcb - failed\n", 262 i->inp_ppcb, t, sizeof(*t)); 263 return NULL; 264 } 265 return (struct tcpcb *)i->inp_ppcb; 266} 267#else 268static struct kinfo_proc *getproc() 269{ 270 static struct kinfo_proc kp; 271 pid_t pid = getpid(); 272 int mib[4]; 273 size_t n; 274 275 mib[0] = CTL_KERN; 276 mib[1] = KERN_PROC; 277 mib[2] = KERN_PROC_PID; 278 mib[3] = pid; 279 280 n = sizeof(kp); 281 if (sysctl(mib, 4, &kp, &n, NULL, 0) == -1) 282 { 283 perror("sysctl"); 284 return NULL; 285 } 286 return &kp; 287} 288 289 290struct tcpcb *find_tcp(tfd, ti) 291int tfd; 292struct tcpiphdr *ti; 293{ 294 struct tcpcb *t; 295 struct inpcb *i; 296 struct socket *s; 297 struct filedesc *fd; 298 struct kinfo_proc *p; 299 struct file *f, **o; 300 301 if (!(p = getproc())) 302 return NULL; 303 304 fd = (struct filedesc *)malloc(sizeof(*fd)); 305 if (fd == NULL) 306 return NULL; 307#if defined( __FreeBSD_version) && __FreeBSD_version >= 500013 308 if (KMCPY(fd, p->ki_fd, sizeof(*fd)) == -1) 309 { 310 fprintf(stderr, "read(%#lx,%#lx) failed\n", 311 (u_long)p, (u_long)p->ki_fd); 312 free(fd); 313 return NULL; 314 } 315#else 316 if (KMCPY(fd, p->kp_proc.p_fd, sizeof(*fd)) == -1) 317 { 318 fprintf(stderr, "read(%#lx,%#lx) failed\n", 319 (u_long)p, (u_long)p->kp_proc.p_fd); 320 free(fd); 321 return NULL; 322 } 323#endif 324 325 o = NULL; 326 f = NULL; 327 s = NULL; 328 i = NULL; 329 t = NULL; 330 331 o = (struct file **)calloc(1, sizeof(*o) * (fd->fd_lastfile + 1)); 332#if defined(__NetBSD_Version__) && __NetBSD_Version__ < 599001200 333 if (KMCPY(o, fd->fd_ofiles, (fd->fd_lastfile + 1) * sizeof(*o)) == -1) 334 { 335 fprintf(stderr, "read(%#lx,%#lx,%lu) - u_ofile - failed\n", 336 (u_long)fd->fd_ofiles, (u_long)o, (u_long)sizeof(*o)); 337 goto finderror; 338 } 339#else 340 if (KMCPY(o, &fd->fd_dt->dt_ff, (fd->fd_lastfile + 1) * sizeof(*o)) == -1) 341 { 342 fprintf(stderr, "read(%#lx,%#lx,%lu) - u_ofile - failed\n", 343 (u_long)fd->fd_dt->dt_ff, (u_long)o, (u_long)sizeof(*o)); 344 goto finderror; 345 } 346#endif 347 f = (struct file *)calloc(1, sizeof(*f)); 348 if (KMCPY(f, o[tfd], sizeof(*f)) == -1) 349 { 350 fprintf(stderr, "read(%#lx,%#lx,%lu) - o[tfd] - failed\n", 351 (u_long)o[tfd], (u_long)f, (u_long)sizeof(*f)); 352 goto finderror; 353 } 354 355 s = (struct socket *)calloc(1, sizeof(*s)); 356 if (KMCPY(s, f->f_data, sizeof(*s)) == -1) 357 { 358 fprintf(stderr, "read(%#lx,%#lx,%lu) - f_data - failed\n", 359 (u_long)f->f_data, (u_long)s, (u_long)sizeof(*s)); 360 goto finderror; 361 } 362 363 i = (struct inpcb *)calloc(1, sizeof(*i)); 364 if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1) 365 { 366 fprintf(stderr, "kvm_read(%#lx,%#lx,%lu) - so_pcb - failed\n", 367 (u_long)s->so_pcb, (u_long)i, (u_long)sizeof(*i)); 368 goto finderror; 369 } 370 371 t = (struct tcpcb *)calloc(1, sizeof(*t)); 372 if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1) 373 { 374 fprintf(stderr, "read(%#lx,%#lx,%lu) - inp_ppcb - failed\n", 375 (u_long)i->inp_ppcb, (u_long)t, (u_long)sizeof(*t)); 376 goto finderror; 377 } 378 return (struct tcpcb *)i->inp_ppcb; 379 380finderror: 381 if (o != NULL) 382 free(o); 383 if (f != NULL) 384 free(f); 385 if (s != NULL) 386 free(s); 387 if (i != NULL) 388 free(i); 389 if (t != NULL) 390 free(t); 391 return NULL; 392} 393#endif /* BSD < 199301 */ 394 395int do_socket(dev, mtu, ti, gwip) 396char *dev; 397int mtu; 398struct tcpiphdr *ti; 399struct in_addr gwip; 400{ 401 struct sockaddr_in rsin, lsin; 402 struct tcpcb *t, tcb; 403 int fd, nfd; 404 socklen_t len; 405 406 printf("Dest. Port: %d\n", ti->ti_dport); 407 408 fd = socket(AF_INET, SOCK_STREAM, 0); 409 if (fd == -1) 410 { 411 perror("socket"); 412 return -1; 413 } 414 415 if (fcntl(fd, F_SETFL, FNDELAY) == -1) 416 { 417 perror("fcntl"); 418 return -1; 419 } 420 421 bzero((char *)&lsin, sizeof(lsin)); 422 lsin.sin_family = AF_INET; 423 bcopy((char *)&ti->ti_src, (char *)&lsin.sin_addr, 424 sizeof(struct in_addr)); 425 if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) == -1) 426 { 427 perror("bind"); 428 return -1; 429 } 430 len = sizeof(lsin); 431 (void) getsockname(fd, (struct sockaddr *)&lsin, &len); 432 ti->ti_sport = lsin.sin_port; 433 printf("sport %d\n", ntohs(lsin.sin_port)); 434 435 nfd = initdevice(dev, 1); 436 if (nfd == -1) 437 return -1; 438 439 if (!(t = find_tcp(fd, ti))) 440 return -1; 441 442 bzero((char *)&rsin, sizeof(rsin)); 443 rsin.sin_family = AF_INET; 444 bcopy((char *)&ti->ti_dst, (char *)&rsin.sin_addr, 445 sizeof(struct in_addr)); 446 rsin.sin_port = ti->ti_dport; 447 if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) == -1 && 448 errno != EINPROGRESS) 449 { 450 perror("connect"); 451 return -1; 452 } 453 KMCPY(&tcb, t, sizeof(tcb)); 454 ti->ti_win = tcb.rcv_adv; 455 ti->ti_seq = tcb.snd_nxt - 1; 456 ti->ti_ack = tcb.rcv_nxt; 457 458 if (send_tcp(nfd, mtu, (ip_t *)ti, gwip) == -1) 459 return -1; 460 (void)write(fd, "Hello World\n", 12); 461 sleep(2); 462 close(fd); 463 return 0; 464} 465