1145519Sdarrenr/* $FreeBSD$ */ 2145510Sdarrenr 3145510Sdarrenr/* 4255332Scy * Copyright (C) 2012 by Darren Reed. 5145510Sdarrenr * 6145510Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 7145510Sdarrenr */ 8145510Sdarrenr/* 9145510Sdarrenr * kmemcpy() - copies n bytes from kernel memory into user buffer. 10145510Sdarrenr * returns 0 on success, -1 on error. 11145510Sdarrenr */ 12145510Sdarrenr 13145510Sdarrenr#include <stdio.h> 14145510Sdarrenr#include <sys/param.h> 15145510Sdarrenr#include <sys/types.h> 16145510Sdarrenr#include <sys/uio.h> 17145510Sdarrenr#include <unistd.h> 18145510Sdarrenr#include <string.h> 19145510Sdarrenr#include <fcntl.h> 20145510Sdarrenr#include <sys/file.h> 21153881Sguido#if !defined(__sgi) && !defined(__hpux) && !defined(__osf__) && !defined(linux) && !defined(_AIX51) 22145510Sdarrenr#include <kvm.h> 23145510Sdarrenr#endif 24145510Sdarrenr#include <fcntl.h> 25145510Sdarrenr#include <sys/socket.h> 26145510Sdarrenr#include <sys/ioctl.h> 27145510Sdarrenr#include <netinet/in.h> 28145510Sdarrenr#include <arpa/inet.h> 29145510Sdarrenr#include <netinet/in_systm.h> 30145510Sdarrenr#include <netinet/ip.h> 31145510Sdarrenr#include <net/if.h> 32145510Sdarrenr#if __FreeBSD_version >= 300000 33145510Sdarrenr# include <net/if_var.h> 34145510Sdarrenr#endif 35145510Sdarrenr#if defined(linux) || defined(__osf__) || defined(__sgi) || defined(__hpux) 36145510Sdarrenr# include <stdlib.h> 37145510Sdarrenr#endif 38145510Sdarrenr 39145510Sdarrenr#include "kmem.h" 40145510Sdarrenr 41145510Sdarrenr#ifndef __STDC__ 42145510Sdarrenr# define const 43145510Sdarrenr#endif 44145510Sdarrenr 45145510Sdarrenr#if !defined(lint) 46145510Sdarrenrstatic const char sccsid[] = "@(#)kmem.c 1.4 1/12/96 (C) 1992 Darren Reed"; 47255332Scystatic const char rcsid[] = "@(#)$Id$"; 48145510Sdarrenr#endif 49145510Sdarrenr 50145510Sdarrenr 51145510Sdarrenr 52153881Sguido#if !defined(__sgi) && !defined(__hpux) && !defined(__osf__) && \ 53153881Sguido !defined(linux) && !defined(_AIX51) 54145510Sdarrenr/* 55145510Sdarrenr * For all platforms where there is a libkvm and a kvm_t, we use that... 56145510Sdarrenr */ 57145510Sdarrenrstatic kvm_t *kvm_f = NULL; 58145510Sdarrenr 59145510Sdarrenr#else 60145510Sdarrenr/* 61145510Sdarrenr *...and for the others (HP-UX, IRIX, Tru64), we have to provide our own. 62145510Sdarrenr */ 63145510Sdarrenr 64145510Sdarrenrtypedef int * kvm_t; 65145510Sdarrenr 66145510Sdarrenrstatic kvm_t kvm_f = NULL; 67145510Sdarrenrstatic char *kvm_errstr = NULL; 68145510Sdarrenr 69145510Sdarrenrkvm_t kvm_open __P((char *, char *, char *, int, char *)); 70145510Sdarrenrint kvm_read __P((kvm_t, u_long, char *, size_t)); 71145510Sdarrenr 72145510Sdarrenrkvm_t kvm_open(kernel, core, swap, mode, errstr) 73255332Scy char *kernel, *core, *swap; 74255332Scy int mode; 75255332Scy char *errstr; 76145510Sdarrenr{ 77145510Sdarrenr kvm_t k; 78145510Sdarrenr int fd; 79145510Sdarrenr 80145510Sdarrenr kvm_errstr = errstr; 81145510Sdarrenr 82145510Sdarrenr if (core == NULL) 83145510Sdarrenr core = "/dev/kmem"; 84145510Sdarrenr 85145510Sdarrenr fd = open(core, mode); 86145510Sdarrenr if (fd == -1) 87145510Sdarrenr return NULL; 88145510Sdarrenr k = malloc(sizeof(*k)); 89145510Sdarrenr if (k == NULL) 90145510Sdarrenr return NULL; 91145510Sdarrenr *k = fd; 92145510Sdarrenr return k; 93145510Sdarrenr} 94145510Sdarrenr 95145510Sdarrenrint kvm_read(kvm, pos, buffer, size) 96255332Scy kvm_t kvm; 97255332Scy u_long pos; 98255332Scy char *buffer; 99255332Scy size_t size; 100145510Sdarrenr{ 101145510Sdarrenr int r = 0, left; 102145510Sdarrenr char *bufp; 103145510Sdarrenr 104145510Sdarrenr if (lseek(*kvm, pos, 0) == -1) { 105145510Sdarrenr if (kvm_errstr != NULL) { 106145510Sdarrenr fprintf(stderr, "%s", kvm_errstr); 107145510Sdarrenr perror("lseek"); 108145510Sdarrenr } 109145510Sdarrenr return -1; 110145510Sdarrenr } 111145510Sdarrenr 112145510Sdarrenr for (bufp = buffer, left = size; left > 0; bufp += r, left -= r) { 113145510Sdarrenr r = read(*kvm, bufp, left); 114145510Sdarrenr#ifdef __osf__ 115145510Sdarrenr /* 116145510Sdarrenr * Tru64 returns "0" for successful operation, not the number 117145510Sdarrenr * of bytes read. 118145510Sdarrenr */ 119145510Sdarrenr if (r == 0) 120145510Sdarrenr r = left; 121145510Sdarrenr#endif 122145510Sdarrenr if (r <= 0) 123145510Sdarrenr return -1; 124145510Sdarrenr } 125145510Sdarrenr return r; 126145510Sdarrenr} 127145510Sdarrenr#endif /* !defined(__sgi) && !defined(__hpux) && !defined(__osf__) */ 128145510Sdarrenr 129145510Sdarrenrint openkmem(kern, core) 130255332Scy char *kern, *core; 131145510Sdarrenr{ 132145510Sdarrenr kvm_f = kvm_open(kern, core, NULL, O_RDONLY, NULL); 133145510Sdarrenr if (kvm_f == NULL) 134145510Sdarrenr { 135145510Sdarrenr perror("openkmem:open"); 136145510Sdarrenr return -1; 137145510Sdarrenr } 138145510Sdarrenr return kvm_f != NULL; 139145510Sdarrenr} 140145510Sdarrenr 141145510Sdarrenrint kmemcpy(buf, pos, n) 142255332Scy register char *buf; 143255332Scy long pos; 144255332Scy register int n; 145145510Sdarrenr{ 146145510Sdarrenr register int r; 147145510Sdarrenr 148145510Sdarrenr if (!n) 149145510Sdarrenr return 0; 150145510Sdarrenr 151145510Sdarrenr if (kvm_f == NULL) 152145510Sdarrenr if (openkmem(NULL, NULL) == -1) 153145510Sdarrenr return -1; 154145510Sdarrenr 155145510Sdarrenr while ((r = kvm_read(kvm_f, pos, buf, n)) < n) 156145510Sdarrenr if (r <= 0) 157145510Sdarrenr { 158145510Sdarrenr fprintf(stderr, "pos=0x%lx ", (u_long)pos); 159145510Sdarrenr perror("kmemcpy:read"); 160145510Sdarrenr return -1; 161145510Sdarrenr } 162145510Sdarrenr else 163145510Sdarrenr { 164145510Sdarrenr buf += r; 165145510Sdarrenr pos += r; 166145510Sdarrenr n -= r; 167145510Sdarrenr } 168145510Sdarrenr return 0; 169145510Sdarrenr} 170145510Sdarrenr 171145510Sdarrenrint kstrncpy(buf, pos, n) 172255332Scy register char *buf; 173255332Scy long pos; 174255332Scy register int n; 175145510Sdarrenr{ 176145510Sdarrenr register int r; 177145510Sdarrenr 178145510Sdarrenr if (!n) 179145510Sdarrenr return 0; 180145510Sdarrenr 181145510Sdarrenr if (kvm_f == NULL) 182145510Sdarrenr if (openkmem(NULL, NULL) == -1) 183145510Sdarrenr return -1; 184145510Sdarrenr 185145510Sdarrenr while (n > 0) 186145510Sdarrenr { 187145510Sdarrenr r = kvm_read(kvm_f, pos, buf, 1); 188145510Sdarrenr if (r <= 0) 189145510Sdarrenr { 190145510Sdarrenr fprintf(stderr, "pos=0x%lx ", (u_long)pos); 191145510Sdarrenr perror("kmemcpy:read"); 192145510Sdarrenr return -1; 193145510Sdarrenr } 194145510Sdarrenr else 195145510Sdarrenr { 196145510Sdarrenr if (*buf == '\0') 197145510Sdarrenr break; 198145510Sdarrenr buf++; 199145510Sdarrenr pos++; 200145510Sdarrenr n--; 201145510Sdarrenr } 202145510Sdarrenr } 203145510Sdarrenr return 0; 204145510Sdarrenr} 205