1*a2f04351SSebastien Roy /*
2*a2f04351SSebastien Roy * CDDL HEADER START
3*a2f04351SSebastien Roy *
4*a2f04351SSebastien Roy * This file and its contents are supplied under the terms of the
5*a2f04351SSebastien Roy * Common Development and Distribution License ("CDDL"), version 1.0.
6*a2f04351SSebastien Roy * You may only use this file in accordance with the terms of version
7*a2f04351SSebastien Roy * 1.0 of the CDDL.
8*a2f04351SSebastien Roy *
9*a2f04351SSebastien Roy * A full copy of the text of the CDDL should have accompanied this
10*a2f04351SSebastien Roy * source. A copy of the CDDL is also available via the Internet at
11*a2f04351SSebastien Roy * http://www.illumos.org/license/CDDL.
12*a2f04351SSebastien Roy *
13*a2f04351SSebastien Roy * CDDL HEADER END
14*a2f04351SSebastien Roy */
15*a2f04351SSebastien Roy /*
16*a2f04351SSebastien Roy * Copyright (c) 2015 by Delphix. All rights reserved.
17*a2f04351SSebastien Roy */
18*a2f04351SSebastien Roy
19*a2f04351SSebastien Roy #include <err.h>
20*a2f04351SSebastien Roy #include <stdio.h>
21*a2f04351SSebastien Roy #include <stdlib.h>
22*a2f04351SSebastien Roy #include <errno.h>
23*a2f04351SSebastien Roy #include <fcntl.h>
24*a2f04351SSebastien Roy #include <strings.h>
25*a2f04351SSebastien Roy #include <unistd.h>
26*a2f04351SSebastien Roy #include <stropts.h>
27*a2f04351SSebastien Roy #include <sys/debug.h>
28*a2f04351SSebastien Roy #include <sys/tihdr.h>
29*a2f04351SSebastien Roy #include "connstat.h"
30*a2f04351SSebastien Roy
31*a2f04351SSebastien Roy int
mibopen(const char * proto)32*a2f04351SSebastien Roy mibopen(const char *proto)
33*a2f04351SSebastien Roy {
34*a2f04351SSebastien Roy int saved;
35*a2f04351SSebastien Roy int fd;
36*a2f04351SSebastien Roy
37*a2f04351SSebastien Roy fd = open("/dev/arp", O_RDWR);
38*a2f04351SSebastien Roy if (fd == -1) {
39*a2f04351SSebastien Roy return (-1);
40*a2f04351SSebastien Roy }
41*a2f04351SSebastien Roy
42*a2f04351SSebastien Roy if (ioctl(fd, I_PUSH, proto) == -1) {
43*a2f04351SSebastien Roy saved = errno;
44*a2f04351SSebastien Roy (void) close(fd);
45*a2f04351SSebastien Roy errno = saved;
46*a2f04351SSebastien Roy return (-1);
47*a2f04351SSebastien Roy }
48*a2f04351SSebastien Roy
49*a2f04351SSebastien Roy return (fd);
50*a2f04351SSebastien Roy }
51*a2f04351SSebastien Roy
52*a2f04351SSebastien Roy int
conn_walk(int fd,connstat_proto_t * proto,conn_walk_state_t * state)53*a2f04351SSebastien Roy conn_walk(int fd, connstat_proto_t *proto, conn_walk_state_t *state)
54*a2f04351SSebastien Roy {
55*a2f04351SSebastien Roy struct strbuf cbuf, dbuf;
56*a2f04351SSebastien Roy struct opthdr *hdr;
57*a2f04351SSebastien Roy int flags, r, err = 0;
58*a2f04351SSebastien Roy struct {
59*a2f04351SSebastien Roy struct T_optmgmt_req req;
60*a2f04351SSebastien Roy struct opthdr hdr;
61*a2f04351SSebastien Roy } req;
62*a2f04351SSebastien Roy union {
63*a2f04351SSebastien Roy struct T_optmgmt_ack ack;
64*a2f04351SSebastien Roy uint8_t space[sizeof (struct T_optmgmt_ack) +
65*a2f04351SSebastien Roy sizeof (struct opthdr) * 2];
66*a2f04351SSebastien Roy } ack;
67*a2f04351SSebastien Roy
68*a2f04351SSebastien Roy bzero(&cbuf, sizeof (cbuf));
69*a2f04351SSebastien Roy bzero(&dbuf, sizeof (dbuf));
70*a2f04351SSebastien Roy
71*a2f04351SSebastien Roy req.req.PRIM_type = T_OPTMGMT_REQ;
72*a2f04351SSebastien Roy req.req.OPT_offset = (caddr_t)&req.hdr - (caddr_t)&req;
73*a2f04351SSebastien Roy req.req.OPT_length = sizeof (req.hdr);
74*a2f04351SSebastien Roy req.req.MGMT_flags = T_CURRENT;
75*a2f04351SSebastien Roy
76*a2f04351SSebastien Roy req.hdr.level = proto->csp_miblevel;
77*a2f04351SSebastien Roy req.hdr.name = 0;
78*a2f04351SSebastien Roy req.hdr.len = 0;
79*a2f04351SSebastien Roy
80*a2f04351SSebastien Roy cbuf.buf = (caddr_t)&req;
81*a2f04351SSebastien Roy cbuf.len = sizeof (req);
82*a2f04351SSebastien Roy
83*a2f04351SSebastien Roy if (putmsg(fd, &cbuf, NULL, 0) == -1) {
84*a2f04351SSebastien Roy warn("failed to request connection info: putmsg");
85*a2f04351SSebastien Roy return (-1);
86*a2f04351SSebastien Roy }
87*a2f04351SSebastien Roy
88*a2f04351SSebastien Roy /*
89*a2f04351SSebastien Roy * Each reply consists of a control part for one fixed structure or
90*a2f04351SSebastien Roy * table, as defined in mib2.h. The format is a T_OPTMGMT_ACK
91*a2f04351SSebastien Roy * containing an opthdr structure. The level and name identify the
92*a2f04351SSebastien Roy * entry, and len is the size of the data part of the message.
93*a2f04351SSebastien Roy */
94*a2f04351SSebastien Roy for (;;) {
95*a2f04351SSebastien Roy cbuf.buf = (caddr_t)&ack;
96*a2f04351SSebastien Roy cbuf.maxlen = sizeof (ack);
97*a2f04351SSebastien Roy flags = 0;
98*a2f04351SSebastien Roy
99*a2f04351SSebastien Roy /*
100*a2f04351SSebastien Roy * We first do a getmsg() for the control part so that we
101*a2f04351SSebastien Roy * can allocate a properly sized buffer to read the data
102*a2f04351SSebastien Roy * part.
103*a2f04351SSebastien Roy */
104*a2f04351SSebastien Roy do {
105*a2f04351SSebastien Roy r = getmsg(fd, &cbuf, NULL, &flags);
106*a2f04351SSebastien Roy } while (r < 0 && errno == EINTR);
107*a2f04351SSebastien Roy
108*a2f04351SSebastien Roy if (r < 0) {
109*a2f04351SSebastien Roy warn("failed to fetch further connection info");
110*a2f04351SSebastien Roy err = -1;
111*a2f04351SSebastien Roy break;
112*a2f04351SSebastien Roy } else if ((r & MORECTL) != 0) {
113*a2f04351SSebastien Roy warnx("failed to fetch full control message");
114*a2f04351SSebastien Roy err = -1;
115*a2f04351SSebastien Roy break;
116*a2f04351SSebastien Roy }
117*a2f04351SSebastien Roy
118*a2f04351SSebastien Roy if (cbuf.len < sizeof (struct T_optmgmt_ack) ||
119*a2f04351SSebastien Roy ack.ack.PRIM_type != T_OPTMGMT_ACK ||
120*a2f04351SSebastien Roy ack.ack.MGMT_flags != T_SUCCESS ||
121*a2f04351SSebastien Roy ack.ack.OPT_length < sizeof (struct opthdr)) {
122*a2f04351SSebastien Roy warnx("cannot process invalid message from getmsg()");
123*a2f04351SSebastien Roy err = -1;
124*a2f04351SSebastien Roy break;
125*a2f04351SSebastien Roy }
126*a2f04351SSebastien Roy
127*a2f04351SSebastien Roy /* LINTED E_BAD_PTR_CAST_ALIGN */
128*a2f04351SSebastien Roy hdr = (struct opthdr *)((caddr_t)&ack + ack.ack.OPT_offset);
129*a2f04351SSebastien Roy if (r == 0 && hdr->level == 0 && hdr->name == 0) {
130*a2f04351SSebastien Roy /*
131*a2f04351SSebastien Roy * snmpcom_req() has sent us the final End-Of-Data
132*a2f04351SSebastien Roy * message, so there's nothing further to read.
133*a2f04351SSebastien Roy */
134*a2f04351SSebastien Roy break;
135*a2f04351SSebastien Roy }
136*a2f04351SSebastien Roy
137*a2f04351SSebastien Roy /* Only data should remain. */
138*a2f04351SSebastien Roy VERIFY3S(r, ==, MOREDATA);
139*a2f04351SSebastien Roy
140*a2f04351SSebastien Roy /* Allocate a buffer to hold the data portion of the message */
141*a2f04351SSebastien Roy if ((dbuf.buf = realloc(dbuf.buf, hdr->len)) == NULL) {
142*a2f04351SSebastien Roy warn("failed to realloc() buffer");
143*a2f04351SSebastien Roy err = -1;
144*a2f04351SSebastien Roy break;
145*a2f04351SSebastien Roy }
146*a2f04351SSebastien Roy dbuf.maxlen = hdr->len;
147*a2f04351SSebastien Roy dbuf.len = 0;
148*a2f04351SSebastien Roy flags = 0;
149*a2f04351SSebastien Roy
150*a2f04351SSebastien Roy do {
151*a2f04351SSebastien Roy r = getmsg(fd, NULL, &dbuf, &flags);
152*a2f04351SSebastien Roy } while (r < 0 && errno == EINTR);
153*a2f04351SSebastien Roy
154*a2f04351SSebastien Roy if (r < 0) {
155*a2f04351SSebastien Roy warn("failed to fetch connection data: getmsg()");
156*a2f04351SSebastien Roy err = -1;
157*a2f04351SSebastien Roy break;
158*a2f04351SSebastien Roy } else if (r != 0) {
159*a2f04351SSebastien Roy warnx("failed to fetch all data: "
160*a2f04351SSebastien Roy "getmsg() returned %d", r);
161*a2f04351SSebastien Roy err = -1;
162*a2f04351SSebastien Roy break;
163*a2f04351SSebastien Roy }
164*a2f04351SSebastien Roy
165*a2f04351SSebastien Roy if ((state->cws_flags & CS_IPV4) &&
166*a2f04351SSebastien Roy hdr->name == proto->csp_mibv4name) {
167*a2f04351SSebastien Roy proto->csp_v4walk(&dbuf, state);
168*a2f04351SSebastien Roy } else if ((state->cws_flags & CS_IPV6) &&
169*a2f04351SSebastien Roy hdr->name == proto->csp_mibv6name) {
170*a2f04351SSebastien Roy proto->csp_v6walk(&dbuf, state);
171*a2f04351SSebastien Roy }
172*a2f04351SSebastien Roy }
173*a2f04351SSebastien Roy
174*a2f04351SSebastien Roy free(dbuf.buf);
175*a2f04351SSebastien Roy
176*a2f04351SSebastien Roy return (err);
177*a2f04351SSebastien Roy }
178