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