1/*
2 * Copyright (C) 1993-2001 by Darren Reed.
3 *
4 * See the IPFILTER.LICENCE file for details on licencing.
5 */
6/*
7 * kmemcpy() - copies n bytes from kernel memory into user buffer.
8 * returns 0 on success, -1 on error.
9 */
10
11/*
12 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
13 * Use is subject to license terms.
14 */
15
16#pragma ident	"%Z%%M%	%I%	%E% SMI"
17
18#include <stdio.h>
19#include <sys/param.h>
20#include <sys/types.h>
21#include <sys/uio.h>
22#include <unistd.h>
23#include <string.h>
24#include <fcntl.h>
25#include <sys/file.h>
26#if !defined(__sgi) && !defined(__hpux) && !defined(__osf__) && !defined(linux) && !defined(_AIX51)
27#include <kvm.h>
28#endif
29#include <fcntl.h>
30#include <sys/socket.h>
31#include <sys/ioctl.h>
32#include <netinet/in.h>
33#include <arpa/inet.h>
34#include <netinet/in_systm.h>
35#include <netinet/ip.h>
36#include <net/if.h>
37#if __FreeBSD_version >= 300000
38# include <net/if_var.h>
39#endif
40#if defined(linux) || defined(__osf__) || defined(__sgi) || defined(__hpux)
41# include <stdlib.h>
42#endif
43
44#include "kmem.h"
45
46#ifndef __STDC__
47# define	const
48#endif
49
50#if !defined(lint)
51static const char sccsid[] = "@(#)kmem.c	1.4 1/12/96 (C) 1992 Darren Reed";
52static const char rcsid[] = "@(#)$Id: kmem.c,v 1.16.2.2 2005/06/12 07:18:41 darrenr Exp $";
53#endif
54
55
56
57#if !defined(__sgi) && !defined(__hpux) && !defined(__osf__) && \
58    !defined(linux) && !defined(_AIX51)
59/*
60 * For all platforms where there is a libkvm and a kvm_t, we use that...
61 */
62static	kvm_t	*kvm_f = NULL;
63
64#else
65/*
66 *...and for the others (HP-UX, IRIX, Tru64), we have to provide our own.
67 */
68
69typedef	int *	kvm_t;
70
71static	kvm_t	kvm_f = NULL;
72static	char	*kvm_errstr = NULL;
73
74kvm_t kvm_open __P((char *, char *, char *, int, char *));
75int kvm_read __P((kvm_t, u_long, char *, size_t));
76
77kvm_t kvm_open(kernel, core, swap, mode, errstr)
78char *kernel, *core, *swap;
79int mode;
80char *errstr;
81{
82	kvm_t k;
83	int fd;
84
85	kvm_errstr = errstr;
86
87	if (core == NULL)
88		core = "/dev/kmem";
89
90	fd = open(core, mode);
91	if (fd == -1)
92		return NULL;
93	k = malloc(sizeof(*k));
94	if (k == NULL) {
95		close(fd);
96		return NULL;
97	}
98	*k = fd;
99	return k;
100}
101
102int kvm_read(kvm, pos, buffer, size)
103kvm_t kvm;
104u_long pos;
105char *buffer;
106size_t size;
107{
108	int r = 0, left;
109	char *bufp;
110
111	if (lseek(*kvm, pos, 0) == -1) {
112		if (kvm_errstr != NULL) {
113			fprintf(stderr, "%s", kvm_errstr);
114			perror("lseek");
115		}
116		return -1;
117	}
118
119	for (bufp = buffer, left = size; left > 0; bufp += r, left -= r) {
120		r = read(*kvm, bufp, left);
121#ifdef	__osf__
122		/*
123		 * Tru64 returns "0" for successful operation, not the number
124		 * of bytes read.
125		 */
126		if (r == 0)
127			r = left;
128#endif
129		if (r <= 0)
130			return -1;
131	}
132	return r;
133}
134#endif /* !defined(__sgi) && !defined(__hpux) && !defined(__osf__) */
135
136int	openkmem(kern, core)
137char	*kern, *core;
138{
139	kvm_f = kvm_open(kern, core, NULL, O_RDONLY, NULL);
140	if (kvm_f == NULL)
141	    {
142		perror("openkmem:open");
143		return -1;
144	    }
145	return kvm_f != NULL;
146}
147
148int	kmemcpy(buf, pos, n)
149register char	*buf;
150long	pos;
151register int	n;
152{
153	register int	r;
154
155	if (!n)
156		return 0;
157
158	if (kvm_f == NULL)
159		if (openkmem(NULL, NULL) == -1)
160			return -1;
161
162	while ((r = kvm_read(kvm_f, pos, buf, n)) < n)
163		if (r <= 0)
164		    {
165			fprintf(stderr, "pos=0x%lx ", (u_long)pos);
166			perror("kmemcpy:read");
167			return -1;
168		    }
169		else
170		    {
171			buf += r;
172			pos += r;
173			n -= r;
174		    }
175	return 0;
176}
177
178int	kstrncpy(buf, pos, n)
179register char	*buf;
180long	pos;
181register int	n;
182{
183	register int	r;
184
185	if (!n)
186		return 0;
187
188	if (kvm_f == NULL)
189		if (openkmem(NULL, NULL) == -1)
190			return -1;
191
192	while (n > 0)
193	    {
194		r = kvm_read(kvm_f, pos, buf, 1);
195		if (r <= 0)
196		    {
197			fprintf(stderr, "pos=0x%lx ", (u_long)pos);
198			perror("kmemcpy:read");
199			return -1;
200		    }
201		else
202		    {
203			if (*buf == '\0')
204				break;
205			buf++;
206			pos++;
207			n--;
208		    }
209	    }
210	return 0;
211}
212