kmem.c revision 145519
1250323Sdteske/*	$FreeBSD: head/contrib/ipfilter/lib/kmem.c 145519 2005-04-25 18:20:15Z darrenr $	*/
2250323Sdteske
3250323Sdteske/*
4252980Sdteske * Copyright (C) 1993-2001 by Darren Reed.
5250323Sdteske *
6250323Sdteske * See the IPFILTER.LICENCE file for details on licencing.
7250323Sdteske */
8250323Sdteske/*
9250323Sdteske * kmemcpy() - copies n bytes from kernel memory into user buffer.
10250323Sdteske * returns 0 on success, -1 on error.
11250323Sdteske */
12250323Sdteske
13250323Sdteske#include <stdio.h>
14250323Sdteske#include <sys/param.h>
15250323Sdteske#include <sys/types.h>
16252987Sdteske#include <sys/uio.h>
17250323Sdteske#include <unistd.h>
18250323Sdteske#include <string.h>
19250323Sdteske#include <fcntl.h>
20252987Sdteske#include <sys/file.h>
21250323Sdteske#if !defined(__sgi) && !defined(__hpux) && !defined(__osf__) && !defined(linux)
22250323Sdteske#include <kvm.h>
23250323Sdteske#endif
24250323Sdteske#include <fcntl.h>
25250323Sdteske#include <sys/socket.h>
26250323Sdteske#include <sys/ioctl.h>
27250323Sdteske#include <netinet/in.h>
28250323Sdteske#include <arpa/inet.h>
29250323Sdteske#include <netinet/in_systm.h>
30250323Sdteske#include <netinet/ip.h>
31250323Sdteske#include <net/if.h>
32250323Sdteske#if __FreeBSD_version >= 300000
33250323Sdteske# include <net/if_var.h>
34250323Sdteske#endif
35252745Sdteske#if defined(linux) || defined(__osf__) || defined(__sgi) || defined(__hpux)
36252745Sdteske# include <stdlib.h>
37250323Sdteske#endif
38250323Sdteske
39252077Sdteske#include "kmem.h"
40250323Sdteske
41250323Sdteske#ifndef __STDC__
42250323Sdteske# define	const
43250323Sdteske#endif
44250323Sdteske
45250323Sdteske#if !defined(lint)
46250323Sdteskestatic const char sccsid[] = "@(#)kmem.c	1.4 1/12/96 (C) 1992 Darren Reed";
47250323Sdteskestatic const char rcsid[] = "@(#)Id: kmem.c,v 1.16.2.1 2004/06/20 10:25:58 darrenr Exp";
48250323Sdteske#endif
49250323Sdteske
50250323Sdteske
51250323Sdteske
52250323Sdteske#if !defined(__sgi) && !defined(__hpux) && !defined(__osf__) && !defined(linux)
53252740Sdteske/*
54252745Sdteske * For all platforms where there is a libkvm and a kvm_t, we use that...
55252745Sdteske */
56257795Sdteskestatic	kvm_t	*kvm_f = NULL;
57252745Sdteske
58252745Sdteske#else
59252740Sdteske/*
60252740Sdteske *...and for the others (HP-UX, IRIX, Tru64), we have to provide our own.
61252745Sdteske */
62252740Sdteske
63252740Sdtesketypedef	int *	kvm_t;
64250323Sdteske
65250323Sdteskestatic	kvm_t	kvm_f = NULL;
66250323Sdteskestatic	char	*kvm_errstr = NULL;
67250323Sdteske
68250323Sdteskekvm_t kvm_open __P((char *, char *, char *, int, char *));
69250323Sdteskeint kvm_read __P((kvm_t, u_long, char *, size_t));
70250323Sdteske
71250323Sdteskekvm_t kvm_open(kernel, core, swap, mode, errstr)
72250323Sdteskechar *kernel, *core, *swap;
73250323Sdteskeint mode;
74250323Sdteskechar *errstr;
75250323Sdteske{
76250323Sdteske	kvm_t k;
77250323Sdteske	int fd;
78250323Sdteske
79250323Sdteske	kvm_errstr = errstr;
80250323Sdteske
81250323Sdteske	if (core == NULL)
82250323Sdteske		core = "/dev/kmem";
83250323Sdteske
84250323Sdteske	fd = open(core, mode);
85250323Sdteske	if (fd == -1)
86250323Sdteske		return NULL;
87251355Sdteske	k = malloc(sizeof(*k));
88250323Sdteske	if (k == NULL)
89250323Sdteske		return NULL;
90251355Sdteske	*k = fd;
91250323Sdteske	return k;
92250323Sdteske}
93251355Sdteske
94250538Sdteskeint kvm_read(kvm, pos, buffer, size)
95250323Sdteskekvm_t kvm;
96250323Sdteskeu_long pos;
97250323Sdteskechar *buffer;
98250538Sdteskesize_t size;
99250538Sdteske{
100250538Sdteske	int r = 0, left;
101250538Sdteske	char *bufp;
102251354Sdteske
103250323Sdteske	if (lseek(*kvm, pos, 0) == -1) {
104250323Sdteske		if (kvm_errstr != NULL) {
105250323Sdteske			fprintf(stderr, "%s", kvm_errstr);
106250538Sdteske			perror("lseek");
107250538Sdteske		}
108250538Sdteske		return -1;
109250538Sdteske	}
110251354Sdteske
111250323Sdteske	for (bufp = buffer, left = size; left > 0; bufp += r, left -= r) {
112251354Sdteske		r = read(*kvm, bufp, left);
113251355Sdteske#ifdef	__osf__
114250538Sdteske		/*
115250323Sdteske		 * Tru64 returns "0" for successful operation, not the number
116250323Sdteske		 * of bytes read.
117251355Sdteske		 */
118250323Sdteske		if (r == 0)
119250323Sdteske			r = left;
120250323Sdteske#endif
121250323Sdteske		if (r <= 0)
122250323Sdteske			return -1;
123250323Sdteske	}
124250323Sdteske	return r;
125250323Sdteske}
126250323Sdteske#endif /* !defined(__sgi) && !defined(__hpux) && !defined(__osf__) */
127250323Sdteske
128250323Sdteskeint	openkmem(kern, core)
129250323Sdteskechar	*kern, *core;
130250323Sdteske{
131250323Sdteske	kvm_f = kvm_open(kern, core, NULL, O_RDONLY, NULL);
132250323Sdteske	if (kvm_f == NULL)
133250323Sdteske	    {
134250323Sdteske		perror("openkmem:open");
135256181Sdteske		return -1;
136250323Sdteske	    }
137250323Sdteske	return kvm_f != NULL;
138252771Sdteske}
139250323Sdteske
140250323Sdteskeint	kmemcpy(buf, pos, n)
141250323Sdteskeregister char	*buf;
142250323Sdteskelong	pos;
143250323Sdteskeregister int	n;
144250323Sdteske{
145250323Sdteske	register int	r;
146250323Sdteske
147250323Sdteske	if (!n)
148250323Sdteske		return 0;
149250323Sdteske
150250323Sdteske	if (kvm_f == NULL)
151250323Sdteske		if (openkmem(NULL, NULL) == -1)
152250323Sdteske			return -1;
153250323Sdteske
154250323Sdteske	while ((r = kvm_read(kvm_f, pos, buf, n)) < n)
155250323Sdteske		if (r <= 0)
156250323Sdteske		    {
157250323Sdteske			fprintf(stderr, "pos=0x%lx ", (u_long)pos);
158250323Sdteske			perror("kmemcpy:read");
159250323Sdteske			return -1;
160250323Sdteske		    }
161252771Sdteske		else
162250323Sdteske		    {
163250323Sdteske			buf += r;
164250323Sdteske			pos += r;
165250323Sdteske			n -= r;
166250323Sdteske		    }
167257795Sdteske	return 0;
168250323Sdteske}
169250323Sdteske
170250323Sdteskeint	kstrncpy(buf, pos, n)
171250323Sdteskeregister char	*buf;
172257795Sdteskelong	pos;
173257795Sdteskeregister int	n;
174250323Sdteske{
175250323Sdteske	register int	r;
176250323Sdteske
177250323Sdteske	if (!n)
178250323Sdteske		return 0;
179250323Sdteske
180250323Sdteske	if (kvm_f == NULL)
181250323Sdteske		if (openkmem(NULL, NULL) == -1)
182250323Sdteske			return -1;
183250323Sdteske
184250323Sdteske	while (n > 0)
185250323Sdteske	    {
186250323Sdteske		r = kvm_read(kvm_f, pos, buf, 1);
187250323Sdteske		if (r <= 0)
188250323Sdteske		    {
189250323Sdteske			fprintf(stderr, "pos=0x%lx ", (u_long)pos);
190250323Sdteske			perror("kmemcpy:read");
191250323Sdteske			return -1;
192250323Sdteske		    }
193250323Sdteske		else
194250323Sdteske		    {
195250323Sdteske			if (*buf == '\0')
196250323Sdteske				break;
197250323Sdteske			buf++;
198250323Sdteske			pos++;
199250323Sdteske			n--;
200250323Sdteske		    }
201250323Sdteske	    }
202250323Sdteske	return 0;
203250323Sdteske}
204250323Sdteske