1 /*-
2  * Copyright (c) 2014 Gleb Kurtsou <gleb@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/param.h>
28 #include <sys/user.h>
29 #include <sys/socket.h>
30 #include <string.h>
31 
32 #include "libprocstat.h"
33 
34 #define	SPECNAMELEN_COMPAT12	63
35 
36 struct freebsd11_ptsstat {
37 	uint32_t	dev;
38 	char		devname[SPECNAMELEN_COMPAT12 + 1];
39 };
40 
41 struct freebsd11_vnstat {
42 	uint64_t	vn_fileid;
43 	uint64_t	vn_size;
44 	char		*vn_mntdir;
45 	uint32_t	vn_dev;
46 	uint32_t	vn_fsid;
47 	int		vn_type;
48 	uint16_t	vn_mode;
49 	char		vn_devname[SPECNAMELEN_COMPAT12 + 1];
50 };
51 struct freebsd11_semstat {
52 	uint32_t	value;
53 	uint16_t	mode;
54 };
55 struct freebsd11_shmstat {
56 	uint64_t	size;
57 	uint16_t	mode;
58 };
59 
60 struct freebsd11_sockstat {
61 	uint64_t	inp_ppcb;
62 	uint64_t	so_addr;
63 	uint64_t	so_pcb;
64 	uint64_t	unp_conn;
65 	int		dom_family;
66 	int		proto;
67 	int		so_rcv_sb_state;
68 	int		so_snd_sb_state;
69 	struct sockaddr_storage	sa_local;	/* Socket address. */
70 	struct sockaddr_storage	sa_peer;	/* Peer address. */
71 	int		type;
72 	char		dname[32];
73 };
74 
75 struct freebsd12_vnstat {
76 	uint64_t	vn_fileid;
77 	uint64_t	vn_size;
78 	uint64_t	vn_dev;
79 	uint64_t	vn_fsid;
80 	char		*vn_mntdir;
81 	int		vn_type;
82 	uint16_t	vn_mode;
83 	char		vn_devname[SPECNAMELEN_COMPAT12 + 1];
84 };
85 struct freebsd12_ptsstat {
86 	uint64_t	dev;
87 	char		devname[SPECNAMELEN_COMPAT12 + 1];
88 };
89 
90 int	freebsd11_procstat_get_pts_info(struct procstat *procstat,
91     struct filestat *fst, struct freebsd11_ptsstat *pts, char *errbuf);
92 int	freebsd12_procstat_get_pts_info(struct procstat *procstat,
93     struct filestat *fst, struct freebsd12_ptsstat *pts_compat, char *errbuf);
94 int	freebsd11_procstat_get_sem_info(struct procstat *procstat,
95     struct filestat *fst, struct freebsd11_semstat *sem, char *errbuf);
96 int	freebsd11_procstat_get_shm_info(struct procstat *procstat,
97     struct filestat *fst, struct freebsd11_shmstat *shm, char *errbuf);
98 int	freebsd11_procstat_get_socket_info(struct procstat *procstat,
99     struct filestat *fst, struct freebsd11_sockstat *sock, char *errbuf);
100 int	freebsd11_procstat_get_vnode_info(struct procstat *procstat,
101     struct filestat *fst, struct freebsd11_vnstat *vn, char *errbuf);
102 int	freebsd12_procstat_get_vnode_info(struct procstat *procstat,
103     struct filestat *fst, struct freebsd12_vnstat *vn_compat, char *errbuf);
104 
105 static const char trunc_name[] = "<TRUNCATED>";
106 
107 int
freebsd11_procstat_get_pts_info(struct procstat * procstat,struct filestat * fst,struct freebsd11_ptsstat * pts_compat,char * errbuf)108 freebsd11_procstat_get_pts_info(struct procstat *procstat,
109     struct filestat *fst, struct freebsd11_ptsstat *pts_compat, char *errbuf)
110 {
111 	struct ptsstat pts;
112 	int r;
113 
114 	r = procstat_get_pts_info(procstat, fst, &pts, errbuf);
115 	if (r != 0)
116 		return (r);
117 	pts_compat->dev = pts.dev;
118 	if (strlen(pts.devname) >= sizeof(pts_compat->devname))
119 		strcpy(pts_compat->devname, trunc_name);
120 	else
121 		memcpy(pts_compat->devname, pts.devname,
122 		    sizeof(pts_compat->devname));
123 	return (0);
124 }
125 
126 int
freebsd12_procstat_get_pts_info(struct procstat * procstat,struct filestat * fst,struct freebsd12_ptsstat * pts_compat,char * errbuf)127 freebsd12_procstat_get_pts_info(struct procstat *procstat,
128     struct filestat *fst, struct freebsd12_ptsstat *pts_compat, char *errbuf)
129 {
130 	struct ptsstat pts;
131 	int r;
132 
133 	r = procstat_get_pts_info(procstat, fst, &pts, errbuf);
134 	if (r != 0)
135 		return (r);
136 	pts_compat->dev = pts.dev;
137 	if (strlen(pts.devname) >= sizeof(pts_compat->devname))
138 		strcpy(pts_compat->devname, trunc_name);
139 	else
140 		memcpy(pts_compat->devname, pts.devname,
141 		    sizeof(pts_compat->devname));
142 	return (0);
143 }
144 
145 int
freebsd11_procstat_get_sem_info(struct procstat * procstat,struct filestat * fst,struct freebsd11_semstat * sem_compat,char * errbuf)146 freebsd11_procstat_get_sem_info(struct procstat *procstat,
147     struct filestat *fst, struct freebsd11_semstat *sem_compat, char *errbuf)
148 {
149 	struct semstat sem;
150 	int r;
151 
152 	r = procstat_get_sem_info(procstat, fst, &sem, errbuf);
153 	if (r != 0)
154 		return (r);
155 	sem_compat->value = sem.value;
156 	sem_compat->mode = sem.mode;
157 	return (0);
158 }
159 
160 int
freebsd11_procstat_get_shm_info(struct procstat * procstat,struct filestat * fst,struct freebsd11_shmstat * shm_compat,char * errbuf)161 freebsd11_procstat_get_shm_info(struct procstat *procstat,
162     struct filestat *fst, struct freebsd11_shmstat *shm_compat, char *errbuf)
163 {
164 	struct shmstat shm;
165 	int r;
166 
167 	r = procstat_get_shm_info(procstat, fst, &shm, errbuf);
168 	if (r != 0)
169 		return (r);
170 	shm_compat->size = shm.size;
171 	shm_compat->mode = shm.mode;
172 	return (0);
173 }
174 
175 int
freebsd11_procstat_get_socket_info(struct procstat * procstat,struct filestat * fst,struct freebsd11_sockstat * sock_compat,char * errbuf)176 freebsd11_procstat_get_socket_info(struct procstat *procstat, struct filestat *fst,
177     struct freebsd11_sockstat *sock_compat, char *errbuf)
178 {
179 	struct sockstat sock;
180 	int r;
181 
182 	r = procstat_get_socket_info(procstat, fst, &sock, errbuf);
183 	if (r != 0)
184 		return (r);
185 	sock_compat->inp_ppcb = sock.so_pcb;
186 	sock_compat->so_addr = sock.so_addr;
187 	sock_compat->so_pcb = sock.so_pcb;
188 	sock_compat->unp_conn = sock.unp_conn;
189 	sock_compat->dom_family = sock.dom_family;
190 	sock_compat->proto = sock.proto;
191 	sock_compat->so_rcv_sb_state = sock.so_rcv_sb_state;
192 	sock_compat->so_snd_sb_state = sock.so_snd_sb_state;
193 	sock_compat->sa_local = sock.sa_local;
194 	sock_compat->sa_peer = sock.sa_peer;
195 	sock_compat->type = sock.type;
196 	memcpy(sock_compat->dname, sock.dname, sizeof(sock.dname));
197 	return (0);
198 }
199 
200 int
freebsd11_procstat_get_vnode_info(struct procstat * procstat,struct filestat * fst,struct freebsd11_vnstat * vn_compat,char * errbuf)201 freebsd11_procstat_get_vnode_info(struct procstat *procstat,
202     struct filestat *fst, struct freebsd11_vnstat *vn_compat, char *errbuf)
203 {
204 	struct vnstat vn;
205 	int r;
206 
207 	r = procstat_get_vnode_info(procstat, fst, &vn, errbuf);
208 	if (r != 0)
209 		return (r);
210 	vn_compat->vn_fileid = vn.vn_fileid;
211 	vn_compat->vn_size = vn.vn_size;
212 	vn_compat->vn_mntdir = vn.vn_mntdir;
213 	vn_compat->vn_dev = vn.vn_dev;
214 	vn_compat->vn_fsid = vn.vn_fsid;
215 	vn_compat->vn_type = vn.vn_type;
216 	vn_compat->vn_mode = vn.vn_mode;
217 	if (strlen(vn.vn_devname) >= sizeof(vn_compat->vn_devname))
218 		strcpy(vn_compat->vn_devname, trunc_name);
219 	else
220 		memcpy(vn_compat->vn_devname, vn.vn_devname,
221 		    sizeof(vn_compat->vn_devname));
222 	return (0);
223 }
224 
225 int
freebsd12_procstat_get_vnode_info(struct procstat * procstat,struct filestat * fst,struct freebsd12_vnstat * vn_compat,char * errbuf)226 freebsd12_procstat_get_vnode_info(struct procstat *procstat,
227     struct filestat *fst, struct freebsd12_vnstat *vn_compat, char *errbuf)
228 {
229 	struct vnstat vn;
230 	int r;
231 
232 	r = procstat_get_vnode_info(procstat, fst, &vn, errbuf);
233 	if (r != 0)
234 		return (r);
235 	vn_compat->vn_fileid = vn.vn_fileid;
236 	vn_compat->vn_size = vn.vn_size;
237 	vn_compat->vn_mntdir = vn.vn_mntdir;
238 	vn_compat->vn_dev = vn.vn_dev;
239 	vn_compat->vn_fsid = vn.vn_fsid;
240 	vn_compat->vn_type = vn.vn_type;
241 	vn_compat->vn_mode = vn.vn_mode;
242 	if (strlen(vn.vn_devname) >= sizeof(vn_compat->vn_devname))
243 		strcpy(vn_compat->vn_devname, trunc_name);
244 	else
245 		memcpy(vn_compat->vn_devname, vn.vn_devname,
246 		    sizeof(vn_compat->vn_devname));
247 	return (0);
248 }
249 
250 __sym_compat(procstat_get_pts_info, freebsd11_procstat_get_pts_info, FBSD_1.2);
251 __sym_compat(procstat_get_socket_info, freebsd11_procstat_get_socket_info,
252     FBSD_1.2);
253 __sym_compat(procstat_get_vnode_info, freebsd11_procstat_get_vnode_info,
254     FBSD_1.2);
255 __sym_compat(procstat_get_sem_info, freebsd11_procstat_get_sem_info, FBSD_1.3);
256 __sym_compat(procstat_get_shm_info, freebsd11_procstat_get_shm_info, FBSD_1.3);
257 __sym_compat(procstat_get_pts_info, freebsd12_procstat_get_pts_info, FBSD_1.5);
258 __sym_compat(procstat_get_vnode_info, freebsd12_procstat_get_vnode_info,
259     FBSD_1.5);
260