|  | /* | 
|  | * Copyright (C) 2000-2005 by Darren Reed. | 
|  | * | 
|  | * See the IPFILTER.LICENCE file for details on licencing. | 
|  | */ | 
|  | /* | 
|  | * kmemcpy() - copies n bytes from kernel memory into user buffer. | 
|  | * returns 0 on success, -1 on error. | 
|  | */ | 
|  |  | 
|  | #include <stdio.h> | 
|  | #include <sys/param.h> | 
|  | #include <sys/types.h> | 
|  | #include <sys/uio.h> | 
|  | #include <unistd.h> | 
|  | #include <string.h> | 
|  | #include <fcntl.h> | 
|  | #include <sys/file.h> | 
|  | #if !defined(__sgi) && !defined(__hpux) && !defined(__osf__) && !defined(linux) && !defined(_AIX51) | 
|  | #include <kvm.h> | 
|  | #endif | 
|  | #include <fcntl.h> | 
|  | #include <sys/socket.h> | 
|  | #include <sys/ioctl.h> | 
|  | #include <netinet/in.h> | 
|  | #include <arpa/inet.h> | 
|  | #include <netinet/in_systm.h> | 
|  | #include <netinet/ip.h> | 
|  | #include <net/if.h> | 
|  | #if __FreeBSD_version >= 300000 | 
|  | # include <net/if_var.h> | 
|  | #endif | 
|  | #if defined(linux) || defined(__osf__) || defined(__sgi) || defined(__hpux) | 
|  | # include <stdlib.h> | 
|  | #endif | 
|  |  | 
|  | #include "kmem.h" | 
|  |  | 
|  | #ifndef __STDC__ | 
|  | # define	const | 
|  | #endif | 
|  |  | 
|  | #if !defined(lint) | 
|  | static const char sccsid[] = "@(#)kmem.c	1.4 1/12/96 (C) 1992 Darren Reed"; | 
|  | static const char rcsid[] = "@(#)$Id$"; | 
|  | #endif | 
|  |  | 
|  |  | 
|  |  | 
|  | #if !defined(__sgi) && !defined(__hpux) && !defined(__osf__) && \ | 
|  | !defined(linux) && !defined(_AIX51) | 
|  | /* | 
|  | * For all platforms where there is a libkvm and a kvm_t, we use that... | 
|  | */ | 
|  | static	kvm_t	*kvm_f = NULL; | 
|  |  | 
|  | #else | 
|  | /* | 
|  | *...and for the others (HP-UX, IRIX, Tru64), we have to provide our own. | 
|  | */ | 
|  |  | 
|  | typedef	int *	kvm_t; | 
|  |  | 
|  | static	kvm_t	kvm_f = NULL; | 
|  | static	char	*kvm_errstr = NULL; | 
|  |  | 
|  | kvm_t kvm_open __P((char *, char *, char *, int, char *)); | 
|  | int kvm_read __P((kvm_t, u_long, char *, size_t)); | 
|  |  | 
|  | kvm_t kvm_open(kernel, core, swap, mode, errstr) | 
|  | char *kernel, *core, *swap; | 
|  | int mode; | 
|  | char *errstr; | 
|  | { | 
|  | kvm_t k; | 
|  | int fd; | 
|  |  | 
|  | kvm_errstr = errstr; | 
|  |  | 
|  | if (core == NULL) | 
|  | core = "/dev/kmem"; | 
|  |  | 
|  | fd = open(core, mode); | 
|  | if (fd == -1) | 
|  | return NULL; | 
|  | k = malloc(sizeof(*k)); | 
|  | if (k == NULL) | 
|  | return NULL; | 
|  | *k = fd; | 
|  | return k; | 
|  | } | 
|  |  | 
|  | int kvm_read(kvm, pos, buffer, size) | 
|  | kvm_t kvm; | 
|  | u_long pos; | 
|  | char *buffer; | 
|  | size_t size; | 
|  | { | 
|  | int r = 0, left; | 
|  | char *bufp; | 
|  |  | 
|  | if (lseek(*kvm, pos, 0) == -1) { | 
|  | if (kvm_errstr != NULL) { | 
|  | fprintf(stderr, "%s", kvm_errstr); | 
|  | perror("lseek"); | 
|  | } | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | for (bufp = buffer, left = size; left > 0; bufp += r, left -= r) { | 
|  | r = read(*kvm, bufp, left); | 
|  | #ifdef	__osf__ | 
|  | /* | 
|  | * Tru64 returns "0" for successful operation, not the number | 
|  | * of bytes read. | 
|  | */ | 
|  | if (r == 0) | 
|  | r = left; | 
|  | #endif | 
|  | if (r <= 0) | 
|  | return -1; | 
|  | } | 
|  | return r; | 
|  | } | 
|  | #endif /* !defined(__sgi) && !defined(__hpux) && !defined(__osf__) */ | 
|  |  | 
|  | int	openkmem(kern, core) | 
|  | char	*kern, *core; | 
|  | { | 
|  | kvm_f = kvm_open(kern, core, NULL, O_RDONLY, NULL); | 
|  | if (kvm_f == NULL) | 
|  | { | 
|  | perror("openkmem:open"); | 
|  | return -1; | 
|  | } | 
|  | return kvm_f != NULL; | 
|  | } | 
|  |  | 
|  | int	kmemcpy(buf, pos, n) | 
|  | register char	*buf; | 
|  | long	pos; | 
|  | register int	n; | 
|  | { | 
|  | register int	r; | 
|  |  | 
|  | if (!n) | 
|  | return 0; | 
|  |  | 
|  | if (kvm_f == NULL) | 
|  | if (openkmem(NULL, NULL) == -1) | 
|  | return -1; | 
|  |  | 
|  | while ((r = kvm_read(kvm_f, pos, buf, n)) < n) | 
|  | if (r <= 0) | 
|  | { | 
|  | fprintf(stderr, "pos=0x%lx ", (u_long)pos); | 
|  | perror("kmemcpy:read"); | 
|  | return -1; | 
|  | } | 
|  | else | 
|  | { | 
|  | buf += r; | 
|  | pos += r; | 
|  | n -= r; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int	kstrncpy(buf, pos, n) | 
|  | register char	*buf; | 
|  | long	pos; | 
|  | register int	n; | 
|  | { | 
|  | register int	r; | 
|  |  | 
|  | if (!n) | 
|  | return 0; | 
|  |  | 
|  | if (kvm_f == NULL) | 
|  | if (openkmem(NULL, NULL) == -1) | 
|  | return -1; | 
|  |  | 
|  | while (n > 0) | 
|  | { | 
|  | r = kvm_read(kvm_f, pos, buf, 1); | 
|  | if (r <= 0) | 
|  | { | 
|  | fprintf(stderr, "pos=0x%lx ", (u_long)pos); | 
|  | perror("kmemcpy:read"); | 
|  | return -1; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (*buf == '\0') | 
|  | break; | 
|  | buf++; | 
|  | pos++; | 
|  | n--; | 
|  | } | 
|  | } | 
|  | return 0; | 
|  | } |