1 /* $NetBSD: rndpseudo_50.c,v 1.2 2012/08/03 07:51:21 matt Exp $ */ 2 3 /*- 4 * Copyright (c) 1997-2011 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Michael Graff <explorer@flame.org> and Thor Lancelot Simon. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: rndpseudo_50.c,v 1.2 2012/08/03 07:51:21 matt Exp $"); 34 35 #if defined(_KERNEL_OPT) 36 #include "opt_compat_netbsd.h" 37 #include "opt_compat_netbsd32.h" 38 #endif 39 40 #include <sys/param.h> 41 #include <sys/file.h> 42 43 #include <sys/rnd.h> 44 #include <compat/sys/rnd.h> 45 46 /* 47 * Convert from rndsource_t to rndsource50_t, for the results from 48 * RNDGETNUM50 and RNDGETNAME50. 49 */ 50 static void 51 rndsource_to_rndsource50(rndsource_t *r, rndsource50_t *r50) 52 { 53 memset(r50, 0, sizeof(*r50)); 54 strlcpy(r50->name, r->name, sizeof(r50->name)); 55 r50->total = r->total; 56 r50->type = r->type; 57 r50->flags = r->flags; 58 } 59 60 #if defined(COMPAT_NETBSD32) && defined(_LP64) 61 /* 62 * Convert from rndsource_t to rndsource50_32_t, for the results from 63 * RNDGETNUM50_32 and RNDGETNAME50_32. 64 */ 65 static void 66 rndsource_to_rndsource50_32(rndsource_t *r, rndsource50_32_t *r50_32) 67 { 68 memset(r50_32, 0, sizeof(*r50_32)); 69 strlcpy(r50_32->name, r->name, sizeof(r50_32->name)); 70 r50_32->total = r->total; 71 r50_32->type = r->type; 72 r50_32->flags = r->flags; 73 } 74 #endif /* COMPAT_NETBSD32 */ 75 76 /* 77 * COMPAT_50 handling for rnd_ioctl. This is called from rnd_ioctl. 78 * 79 * It also handles the case of (COMPAT_50 && COMPAT_NETBSD32). 80 */ 81 int 82 compat_50_rnd_ioctl(struct file *fp, u_long cmd, void *addr) 83 { 84 int ret = 0; 85 86 switch (cmd) { 87 88 case RNDGETSRCNUM50: 89 { 90 rndstat_t rstbuf = {.start = 0}; 91 rndstat50_t *rst50 = (rndstat50_t *)addr; 92 int count; 93 94 if (rst50->count > RND_MAXSTATCOUNT50) 95 return EINVAL; 96 97 rstbuf.start = rst50->start; 98 rstbuf.count = rst50->count; 99 100 ret = (fp->f_ops->fo_ioctl)(fp, RNDGETSRCNUM, &rstbuf); 101 if (ret != 0) 102 return ret; 103 104 for (count = 0; count < rst50->count; count++) { 105 rndsource_to_rndsource50(&rstbuf.source[count], 106 &rst50->source[count]); 107 } 108 rst50->count = rstbuf.count; 109 110 break; 111 } 112 113 #if defined(COMPAT_NETBSD32) && defined(_LP64) 114 case RNDGETSRCNUM50_32: 115 { 116 rndstat_t rstbuf = {.start = 0}; 117 rndstat50_32_t *rst50_32 = (rndstat50_32_t *)addr; 118 int count; 119 120 if (rst50_32->count > RND_MAXSTATCOUNT50) 121 return (EINVAL); 122 123 rstbuf.start = rst50_32->start; 124 rstbuf.count = rst50_32->count; 125 126 ret = (fp->f_ops->fo_ioctl)(fp, RNDGETSRCNUM, &rstbuf); 127 if (ret != 0) 128 return ret; 129 130 for (count = 0; count < rst50_32->count; count++) { 131 rndsource_to_rndsource50_32(&rstbuf.source[count], 132 &rst50_32->source[count]); 133 } 134 rst50_32->count = rstbuf.count; 135 136 break; 137 } 138 #endif /* COMPAT_NETBSD32 */ 139 140 case RNDGETSRCNAME50: 141 { 142 rndstat_name_t rstnmbuf = {.name[0] = 0}; 143 rndstat_name50_t *rstnm50; 144 rstnm50 = (rndstat_name50_t *)addr; 145 146 strlcpy(rstnmbuf.name, rstnm50->name, sizeof(rstnmbuf.name)); 147 148 ret = (fp->f_ops->fo_ioctl)(fp, RNDGETSRCNAME, &rstnmbuf); 149 if (ret != 0) 150 return ret; 151 152 rndsource_to_rndsource50(&rstnmbuf.source, &rstnm50->source); 153 154 break; 155 } 156 157 #if defined(COMPAT_NETBSD32) && defined(_LP64) 158 case RNDGETSRCNAME50_32: 159 { 160 rndstat_name_t rstnmbuf = {.name[0] = 0}; 161 rndstat_name50_32_t *rstnm50_32; 162 rstnm50_32 = (rndstat_name50_32_t *)addr; 163 164 strlcpy(rstnmbuf.name, rstnm50_32->name, sizeof(rstnmbuf.name)); 165 166 ret = (fp->f_ops->fo_ioctl)(fp, RNDGETSRCNAME, &rstnmbuf); 167 if (ret != 0) 168 return ret; 169 170 rndsource_to_rndsource50_32(&rstnmbuf.source, 171 &rstnm50_32->source); 172 173 break; 174 } 175 #endif 176 177 default: 178 return ENOTTY; 179 } 180 181 return ret; 182 } 183