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
36struct freebsd11_ptsstat {
37	uint32_t	dev;
38	char		devname[SPECNAMELEN_COMPAT12 + 1];
39};
40
41struct 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};
51struct freebsd11_semstat {
52	uint32_t	value;
53	uint16_t	mode;
54};
55struct freebsd11_shmstat {
56	uint64_t	size;
57	uint16_t	mode;
58};
59
60struct 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
75struct 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};
85struct freebsd12_ptsstat {
86	uint64_t	dev;
87	char		devname[SPECNAMELEN_COMPAT12 + 1];
88};
89
90int	freebsd11_procstat_get_pts_info(struct procstat *procstat,
91    struct filestat *fst, struct freebsd11_ptsstat *pts, char *errbuf);
92int	freebsd12_procstat_get_pts_info(struct procstat *procstat,
93    struct filestat *fst, struct freebsd12_ptsstat *pts_compat, char *errbuf);
94int	freebsd11_procstat_get_sem_info(struct procstat *procstat,
95    struct filestat *fst, struct freebsd11_semstat *sem, char *errbuf);
96int	freebsd11_procstat_get_shm_info(struct procstat *procstat,
97    struct filestat *fst, struct freebsd11_shmstat *shm, char *errbuf);
98int	freebsd11_procstat_get_socket_info(struct procstat *procstat,
99    struct filestat *fst, struct freebsd11_sockstat *sock, char *errbuf);
100int	freebsd11_procstat_get_vnode_info(struct procstat *procstat,
101    struct filestat *fst, struct freebsd11_vnstat *vn, char *errbuf);
102int	freebsd12_procstat_get_vnode_info(struct procstat *procstat,
103    struct filestat *fst, struct freebsd12_vnstat *vn_compat, char *errbuf);
104
105static const char trunc_name[] = "<TRUNCATED>";
106
107int
108freebsd11_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
126int
127freebsd12_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
145int
146freebsd11_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
160int
161freebsd11_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
175int
176freebsd11_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
200int
201freebsd11_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
225int
226freebsd12_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