1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright 1991-2003 Sun Microsystems, Inc. All rights reserved.
24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*7c478bd9Sstevel@tonic-gate
29*7c478bd9Sstevel@tonic-gate #include <stdio.h>
30*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
31*7c478bd9Sstevel@tonic-gate #include <string.h>
32*7c478bd9Sstevel@tonic-gate #include <unistd.h>
33*7c478bd9Sstevel@tonic-gate #include <errno.h>
34*7c478bd9Sstevel@tonic-gate
35*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/tihdr.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/tiuser.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/timod.h>
41*7c478bd9Sstevel@tonic-gate
42*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
44*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
45*7c478bd9Sstevel@tonic-gate #include <net/if.h>
46*7c478bd9Sstevel@tonic-gate
47*7c478bd9Sstevel@tonic-gate #include <inet/common.h>
48*7c478bd9Sstevel@tonic-gate #include <inet/mib2.h>
49*7c478bd9Sstevel@tonic-gate #include <inet/ip.h>
50*7c478bd9Sstevel@tonic-gate #include <netinet/igmp_var.h>
51*7c478bd9Sstevel@tonic-gate #include <netinet/ip_mroute.h>
52*7c478bd9Sstevel@tonic-gate
53*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
54*7c478bd9Sstevel@tonic-gate
55*7c478bd9Sstevel@tonic-gate #include <netdb.h>
56*7c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
57*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
58*7c478bd9Sstevel@tonic-gate #include <stropts.h>
59*7c478bd9Sstevel@tonic-gate
60*7c478bd9Sstevel@tonic-gate #include "bootparam_private.h"
61*7c478bd9Sstevel@tonic-gate
62*7c478bd9Sstevel@tonic-gate typedef struct mib_item_s {
63*7c478bd9Sstevel@tonic-gate struct mib_item_s *next_item;
64*7c478bd9Sstevel@tonic-gate long group;
65*7c478bd9Sstevel@tonic-gate long mib_id;
66*7c478bd9Sstevel@tonic-gate long length;
67*7c478bd9Sstevel@tonic-gate char *valp;
68*7c478bd9Sstevel@tonic-gate } mib_item_t;
69*7c478bd9Sstevel@tonic-gate
70*7c478bd9Sstevel@tonic-gate static void free_itemlist(mib_item_t *);
71*7c478bd9Sstevel@tonic-gate
72*7c478bd9Sstevel@tonic-gate static mib_item_t *
mibget(int sd)73*7c478bd9Sstevel@tonic-gate mibget(int sd)
74*7c478bd9Sstevel@tonic-gate {
75*7c478bd9Sstevel@tonic-gate char buf[512];
76*7c478bd9Sstevel@tonic-gate int flags;
77*7c478bd9Sstevel@tonic-gate int i, j, getcode;
78*7c478bd9Sstevel@tonic-gate struct strbuf ctlbuf, databuf;
79*7c478bd9Sstevel@tonic-gate struct T_optmgmt_req *tor = (struct T_optmgmt_req *)(void *)buf;
80*7c478bd9Sstevel@tonic-gate struct T_optmgmt_ack *toa = (struct T_optmgmt_ack *)(void *)buf;
81*7c478bd9Sstevel@tonic-gate struct T_error_ack *tea = (struct T_error_ack *)(void *)buf;
82*7c478bd9Sstevel@tonic-gate struct opthdr *req;
83*7c478bd9Sstevel@tonic-gate mib_item_t *first_item = nilp(mib_item_t);
84*7c478bd9Sstevel@tonic-gate mib_item_t *last_item = nilp(mib_item_t);
85*7c478bd9Sstevel@tonic-gate mib_item_t *temp;
86*7c478bd9Sstevel@tonic-gate
87*7c478bd9Sstevel@tonic-gate tor->PRIM_type = T_SVR4_OPTMGMT_REQ;
88*7c478bd9Sstevel@tonic-gate tor->OPT_offset = sizeof (struct T_optmgmt_req);
89*7c478bd9Sstevel@tonic-gate tor->OPT_length = sizeof (struct opthdr);
90*7c478bd9Sstevel@tonic-gate tor->MGMT_flags = T_CURRENT;
91*7c478bd9Sstevel@tonic-gate req = (struct opthdr *)&tor[1];
92*7c478bd9Sstevel@tonic-gate req->level = MIB2_IP; /* any MIB2_xxx value ok here */
93*7c478bd9Sstevel@tonic-gate req->name = 0;
94*7c478bd9Sstevel@tonic-gate req->len = 0;
95*7c478bd9Sstevel@tonic-gate
96*7c478bd9Sstevel@tonic-gate ctlbuf.buf = buf;
97*7c478bd9Sstevel@tonic-gate ctlbuf.len = tor->OPT_length + tor->OPT_offset;
98*7c478bd9Sstevel@tonic-gate flags = 0;
99*7c478bd9Sstevel@tonic-gate if (putmsg(sd, &ctlbuf, nilp(struct strbuf), flags) == -1) {
100*7c478bd9Sstevel@tonic-gate perror("mibget: putmsg(ctl) failed");
101*7c478bd9Sstevel@tonic-gate goto error_exit;
102*7c478bd9Sstevel@tonic-gate }
103*7c478bd9Sstevel@tonic-gate /*
104*7c478bd9Sstevel@tonic-gate * each reply consists of a ctl part for one fixed structure
105*7c478bd9Sstevel@tonic-gate * or table, as defined in mib2.h. The format is a T_OPTMGMT_ACK,
106*7c478bd9Sstevel@tonic-gate * containing an opthdr structure. level/name identify the entry,
107*7c478bd9Sstevel@tonic-gate * len is the size of the data part of the message.
108*7c478bd9Sstevel@tonic-gate */
109*7c478bd9Sstevel@tonic-gate req = (struct opthdr *)&toa[1];
110*7c478bd9Sstevel@tonic-gate ctlbuf.maxlen = sizeof (buf);
111*7c478bd9Sstevel@tonic-gate for (j = 1; ; j++) {
112*7c478bd9Sstevel@tonic-gate flags = 0;
113*7c478bd9Sstevel@tonic-gate getcode = getmsg(sd, &ctlbuf, nilp(struct strbuf), &flags);
114*7c478bd9Sstevel@tonic-gate if (getcode == -1) {
115*7c478bd9Sstevel@tonic-gate perror("mibget getmsg(ctl) failed");
116*7c478bd9Sstevel@tonic-gate if (debug) {
117*7c478bd9Sstevel@tonic-gate msgout("# level name len");
118*7c478bd9Sstevel@tonic-gate i = 0;
119*7c478bd9Sstevel@tonic-gate for (last_item = first_item; last_item;
120*7c478bd9Sstevel@tonic-gate last_item = last_item->next_item)
121*7c478bd9Sstevel@tonic-gate msgout("%d %4ld %5ld %ld", ++i,
122*7c478bd9Sstevel@tonic-gate last_item->group,
123*7c478bd9Sstevel@tonic-gate last_item->mib_id,
124*7c478bd9Sstevel@tonic-gate last_item->length);
125*7c478bd9Sstevel@tonic-gate }
126*7c478bd9Sstevel@tonic-gate goto error_exit;
127*7c478bd9Sstevel@tonic-gate }
128*7c478bd9Sstevel@tonic-gate if ((getcode == 0) &&
129*7c478bd9Sstevel@tonic-gate (ctlbuf.len >= sizeof (struct T_optmgmt_ack))&&
130*7c478bd9Sstevel@tonic-gate (toa->PRIM_type == T_OPTMGMT_ACK) &&
131*7c478bd9Sstevel@tonic-gate (toa->MGMT_flags == T_SUCCESS) &&
132*7c478bd9Sstevel@tonic-gate (req->len == 0)) {
133*7c478bd9Sstevel@tonic-gate if (debug)
134*7c478bd9Sstevel@tonic-gate msgout("mibget getmsg() %d returned EOD "
135*7c478bd9Sstevel@tonic-gate "(level %lu, name %lu)",
136*7c478bd9Sstevel@tonic-gate j, req->level, req->name);
137*7c478bd9Sstevel@tonic-gate return (first_item); /* this is EOD msg */
138*7c478bd9Sstevel@tonic-gate }
139*7c478bd9Sstevel@tonic-gate
140*7c478bd9Sstevel@tonic-gate if (ctlbuf.len >= sizeof (struct T_error_ack) &&
141*7c478bd9Sstevel@tonic-gate tea->PRIM_type == T_ERROR_ACK) {
142*7c478bd9Sstevel@tonic-gate msgout("mibget %d gives T_ERROR_ACK: "
143*7c478bd9Sstevel@tonic-gate "TLI_error = 0x%lx, UNIX_error = 0x%lx",
144*7c478bd9Sstevel@tonic-gate j, tea->TLI_error, tea->UNIX_error);
145*7c478bd9Sstevel@tonic-gate errno = (tea->TLI_error == TSYSERR)
146*7c478bd9Sstevel@tonic-gate ? tea->UNIX_error : EPROTO;
147*7c478bd9Sstevel@tonic-gate goto error_exit;
148*7c478bd9Sstevel@tonic-gate }
149*7c478bd9Sstevel@tonic-gate
150*7c478bd9Sstevel@tonic-gate if (getcode != MOREDATA ||
151*7c478bd9Sstevel@tonic-gate ctlbuf.len < sizeof (struct T_optmgmt_ack) ||
152*7c478bd9Sstevel@tonic-gate toa->PRIM_type != T_OPTMGMT_ACK ||
153*7c478bd9Sstevel@tonic-gate toa->MGMT_flags != T_SUCCESS) {
154*7c478bd9Sstevel@tonic-gate msgout("mibget getmsg(ctl) %d returned %d, "
155*7c478bd9Sstevel@tonic-gate "ctlbuf.len = %d, PRIM_type = %ld",
156*7c478bd9Sstevel@tonic-gate j, getcode, ctlbuf.len, toa->PRIM_type);
157*7c478bd9Sstevel@tonic-gate if (toa->PRIM_type == T_OPTMGMT_ACK)
158*7c478bd9Sstevel@tonic-gate msgout("T_OPTMGMT_ACK: MGMT_flags = 0x%lx, "
159*7c478bd9Sstevel@tonic-gate "req->len = %lu",
160*7c478bd9Sstevel@tonic-gate toa->MGMT_flags, req->len);
161*7c478bd9Sstevel@tonic-gate errno = ENOMSG;
162*7c478bd9Sstevel@tonic-gate goto error_exit;
163*7c478bd9Sstevel@tonic-gate }
164*7c478bd9Sstevel@tonic-gate
165*7c478bd9Sstevel@tonic-gate temp = (mib_item_t *)malloc(sizeof (mib_item_t));
166*7c478bd9Sstevel@tonic-gate if (!temp) {
167*7c478bd9Sstevel@tonic-gate perror("mibget malloc failed");
168*7c478bd9Sstevel@tonic-gate goto error_exit;
169*7c478bd9Sstevel@tonic-gate }
170*7c478bd9Sstevel@tonic-gate if (last_item)
171*7c478bd9Sstevel@tonic-gate last_item->next_item = temp;
172*7c478bd9Sstevel@tonic-gate else
173*7c478bd9Sstevel@tonic-gate first_item = temp;
174*7c478bd9Sstevel@tonic-gate last_item = temp;
175*7c478bd9Sstevel@tonic-gate last_item->next_item = nilp(mib_item_t);
176*7c478bd9Sstevel@tonic-gate last_item->group = req->level;
177*7c478bd9Sstevel@tonic-gate last_item->mib_id = req->name;
178*7c478bd9Sstevel@tonic-gate last_item->length = req->len;
179*7c478bd9Sstevel@tonic-gate last_item->valp = (char *)malloc(req->len);
180*7c478bd9Sstevel@tonic-gate if (debug)
181*7c478bd9Sstevel@tonic-gate msgout(
182*7c478bd9Sstevel@tonic-gate "msg %d: group = %4ld mib_id = %5ld length = %ld",
183*7c478bd9Sstevel@tonic-gate j, last_item->group, last_item->mib_id,
184*7c478bd9Sstevel@tonic-gate last_item->length);
185*7c478bd9Sstevel@tonic-gate
186*7c478bd9Sstevel@tonic-gate databuf.maxlen = last_item->length;
187*7c478bd9Sstevel@tonic-gate databuf.buf = last_item->valp;
188*7c478bd9Sstevel@tonic-gate databuf.len = 0;
189*7c478bd9Sstevel@tonic-gate flags = 0;
190*7c478bd9Sstevel@tonic-gate getcode = getmsg(sd, nilp(struct strbuf), &databuf, &flags);
191*7c478bd9Sstevel@tonic-gate if (getcode == -1) {
192*7c478bd9Sstevel@tonic-gate perror("mibget getmsg(data) failed");
193*7c478bd9Sstevel@tonic-gate goto error_exit;
194*7c478bd9Sstevel@tonic-gate } else if (getcode != 0) {
195*7c478bd9Sstevel@tonic-gate msgout("xmibget getmsg(data) returned %d, "
196*7c478bd9Sstevel@tonic-gate "databuf.maxlen = %d, databuf.len = %d",
197*7c478bd9Sstevel@tonic-gate getcode, databuf.maxlen, databuf.len);
198*7c478bd9Sstevel@tonic-gate goto error_exit;
199*7c478bd9Sstevel@tonic-gate }
200*7c478bd9Sstevel@tonic-gate }
201*7c478bd9Sstevel@tonic-gate
202*7c478bd9Sstevel@tonic-gate error_exit:
203*7c478bd9Sstevel@tonic-gate free_itemlist(first_item);
204*7c478bd9Sstevel@tonic-gate return (NULL);
205*7c478bd9Sstevel@tonic-gate }
206*7c478bd9Sstevel@tonic-gate
207*7c478bd9Sstevel@tonic-gate static void
free_itemlist(mib_item_t * item_list)208*7c478bd9Sstevel@tonic-gate free_itemlist(mib_item_t *item_list)
209*7c478bd9Sstevel@tonic-gate {
210*7c478bd9Sstevel@tonic-gate mib_item_t *item;
211*7c478bd9Sstevel@tonic-gate
212*7c478bd9Sstevel@tonic-gate while (item_list) {
213*7c478bd9Sstevel@tonic-gate item = item_list;
214*7c478bd9Sstevel@tonic-gate item_list = item->next_item;
215*7c478bd9Sstevel@tonic-gate if (item->valp)
216*7c478bd9Sstevel@tonic-gate free(item->valp);
217*7c478bd9Sstevel@tonic-gate free(item);
218*7c478bd9Sstevel@tonic-gate }
219*7c478bd9Sstevel@tonic-gate }
220*7c478bd9Sstevel@tonic-gate
221*7c478bd9Sstevel@tonic-gate /*
222*7c478bd9Sstevel@tonic-gate * If we are a router, return address of interface closest to client.
223*7c478bd9Sstevel@tonic-gate * If we are not a router, look through our routing table and return
224*7c478bd9Sstevel@tonic-gate * address of "best" router that is on same net as client.
225*7c478bd9Sstevel@tonic-gate *
226*7c478bd9Sstevel@tonic-gate * We expect the router flag to show up first, followed by interface
227*7c478bd9Sstevel@tonic-gate * addr group, followed by the routing table.
228*7c478bd9Sstevel@tonic-gate */
229*7c478bd9Sstevel@tonic-gate
230*7c478bd9Sstevel@tonic-gate in_addr_t
get_ip_route(struct in_addr client_addr)231*7c478bd9Sstevel@tonic-gate get_ip_route(struct in_addr client_addr)
232*7c478bd9Sstevel@tonic-gate {
233*7c478bd9Sstevel@tonic-gate boolean_t found;
234*7c478bd9Sstevel@tonic-gate mib_item_t *item_list;
235*7c478bd9Sstevel@tonic-gate mib_item_t *item;
236*7c478bd9Sstevel@tonic-gate int sd;
237*7c478bd9Sstevel@tonic-gate mib2_ip_t *mip;
238*7c478bd9Sstevel@tonic-gate mib2_ipAddrEntry_t *map;
239*7c478bd9Sstevel@tonic-gate mib2_ipRouteEntry_t *rp;
240*7c478bd9Sstevel@tonic-gate int ip_forwarding = 2; /* off */
241*7c478bd9Sstevel@tonic-gate /* mask of interface used to route to client and best_router */
242*7c478bd9Sstevel@tonic-gate struct in_addr interface_mask;
243*7c478bd9Sstevel@tonic-gate /* address of interface used to route to client and best_router */
244*7c478bd9Sstevel@tonic-gate struct in_addr interface_addr;
245*7c478bd9Sstevel@tonic-gate /* address of "best router"; i.e. the answer */
246*7c478bd9Sstevel@tonic-gate struct in_addr best_router;
247*7c478bd9Sstevel@tonic-gate
248*7c478bd9Sstevel@tonic-gate interface_mask.s_addr = 0L;
249*7c478bd9Sstevel@tonic-gate interface_addr.s_addr = 0L;
250*7c478bd9Sstevel@tonic-gate best_router.s_addr = 0L;
251*7c478bd9Sstevel@tonic-gate
252*7c478bd9Sstevel@tonic-gate /* open a stream to IP */
253*7c478bd9Sstevel@tonic-gate sd = open("/dev/ip", O_RDWR);
254*7c478bd9Sstevel@tonic-gate if (sd == -1) {
255*7c478bd9Sstevel@tonic-gate perror("ip open");
256*7c478bd9Sstevel@tonic-gate (void) close(sd);
257*7c478bd9Sstevel@tonic-gate msgout("can't open mib stream");
258*7c478bd9Sstevel@tonic-gate return (0);
259*7c478bd9Sstevel@tonic-gate }
260*7c478bd9Sstevel@tonic-gate
261*7c478bd9Sstevel@tonic-gate /* send down a request and suck up all the mib info from IP */
262*7c478bd9Sstevel@tonic-gate if ((item_list = mibget(sd)) == nilp(mib_item_t)) {
263*7c478bd9Sstevel@tonic-gate msgout("mibget() failed");
264*7c478bd9Sstevel@tonic-gate (void) close(sd);
265*7c478bd9Sstevel@tonic-gate return (0);
266*7c478bd9Sstevel@tonic-gate }
267*7c478bd9Sstevel@tonic-gate
268*7c478bd9Sstevel@tonic-gate /*
269*7c478bd9Sstevel@tonic-gate * We make three passes through the list of collected IP mib
270*7c478bd9Sstevel@tonic-gate * information. First we figure out if we are a router. Next,
271*7c478bd9Sstevel@tonic-gate * we find which of our interfaces is on the same subnet as
272*7c478bd9Sstevel@tonic-gate * the client. Third, we paw through our own routing table
273*7c478bd9Sstevel@tonic-gate * looking for a useful router address.
274*7c478bd9Sstevel@tonic-gate */
275*7c478bd9Sstevel@tonic-gate
276*7c478bd9Sstevel@tonic-gate /*
277*7c478bd9Sstevel@tonic-gate * The general IP group.
278*7c478bd9Sstevel@tonic-gate */
279*7c478bd9Sstevel@tonic-gate for (item = item_list; item; item = item->next_item) {
280*7c478bd9Sstevel@tonic-gate if ((item->group == MIB2_IP) && (item->mib_id == 0)) {
281*7c478bd9Sstevel@tonic-gate /* are we an IP router? */
282*7c478bd9Sstevel@tonic-gate mip = (mib2_ip_t *)(void *)item->valp;
283*7c478bd9Sstevel@tonic-gate ip_forwarding = mip->ipForwarding;
284*7c478bd9Sstevel@tonic-gate break;
285*7c478bd9Sstevel@tonic-gate }
286*7c478bd9Sstevel@tonic-gate }
287*7c478bd9Sstevel@tonic-gate
288*7c478bd9Sstevel@tonic-gate /*
289*7c478bd9Sstevel@tonic-gate * The interface group.
290*7c478bd9Sstevel@tonic-gate */
291*7c478bd9Sstevel@tonic-gate for (item = item_list, found = B_FALSE; item != NULL && !found;
292*7c478bd9Sstevel@tonic-gate item = item->next_item) {
293*7c478bd9Sstevel@tonic-gate if ((item->group == MIB2_IP) && (item->mib_id == MIB2_IP_20)) {
294*7c478bd9Sstevel@tonic-gate /*
295*7c478bd9Sstevel@tonic-gate * Try to find out which interface is up, configured,
296*7c478bd9Sstevel@tonic-gate * not loopback, and on the same subnet as the client.
297*7c478bd9Sstevel@tonic-gate * Save its address and netmask.
298*7c478bd9Sstevel@tonic-gate */
299*7c478bd9Sstevel@tonic-gate map = (mib2_ipAddrEntry_t *)(void *)item->valp;
300*7c478bd9Sstevel@tonic-gate while ((char *)map < item->valp + item->length) {
301*7c478bd9Sstevel@tonic-gate in_addr_t addr, mask, net;
302*7c478bd9Sstevel@tonic-gate int ifflags;
303*7c478bd9Sstevel@tonic-gate
304*7c478bd9Sstevel@tonic-gate ifflags = map->ipAdEntInfo.ae_flags;
305*7c478bd9Sstevel@tonic-gate addr = map->ipAdEntAddr;
306*7c478bd9Sstevel@tonic-gate mask = map->ipAdEntNetMask;
307*7c478bd9Sstevel@tonic-gate net = addr & mask;
308*7c478bd9Sstevel@tonic-gate
309*7c478bd9Sstevel@tonic-gate if ((ifflags & IFF_LOOPBACK | IFF_UP) ==
310*7c478bd9Sstevel@tonic-gate IFF_UP && addr != INADDR_ANY &&
311*7c478bd9Sstevel@tonic-gate net == (client_addr.s_addr & mask)) {
312*7c478bd9Sstevel@tonic-gate interface_addr.s_addr = addr;
313*7c478bd9Sstevel@tonic-gate interface_mask.s_addr = mask;
314*7c478bd9Sstevel@tonic-gate found = B_TRUE;
315*7c478bd9Sstevel@tonic-gate break;
316*7c478bd9Sstevel@tonic-gate }
317*7c478bd9Sstevel@tonic-gate map++;
318*7c478bd9Sstevel@tonic-gate }
319*7c478bd9Sstevel@tonic-gate }
320*7c478bd9Sstevel@tonic-gate }
321*7c478bd9Sstevel@tonic-gate
322*7c478bd9Sstevel@tonic-gate /*
323*7c478bd9Sstevel@tonic-gate * If this exercise found no interface on the same subnet as
324*7c478bd9Sstevel@tonic-gate * the client, then we can't suggest any router address to
325*7c478bd9Sstevel@tonic-gate * use.
326*7c478bd9Sstevel@tonic-gate */
327*7c478bd9Sstevel@tonic-gate if (interface_addr.s_addr == 0) {
328*7c478bd9Sstevel@tonic-gate if (debug)
329*7c478bd9Sstevel@tonic-gate msgout("get_ip_route: no interface on same net "
330*7c478bd9Sstevel@tonic-gate "as client");
331*7c478bd9Sstevel@tonic-gate (void) close(sd);
332*7c478bd9Sstevel@tonic-gate free_itemlist(item_list);
333*7c478bd9Sstevel@tonic-gate return (0);
334*7c478bd9Sstevel@tonic-gate }
335*7c478bd9Sstevel@tonic-gate
336*7c478bd9Sstevel@tonic-gate /*
337*7c478bd9Sstevel@tonic-gate * If we are a router, we return to client the address of our
338*7c478bd9Sstevel@tonic-gate * interface on the same net as the client.
339*7c478bd9Sstevel@tonic-gate */
340*7c478bd9Sstevel@tonic-gate if (ip_forwarding == 1) {
341*7c478bd9Sstevel@tonic-gate if (debug)
342*7c478bd9Sstevel@tonic-gate msgout("get_ip_route: returning local addr %s",
343*7c478bd9Sstevel@tonic-gate inet_ntoa(interface_addr));
344*7c478bd9Sstevel@tonic-gate (void) close(sd);
345*7c478bd9Sstevel@tonic-gate free_itemlist(item_list);
346*7c478bd9Sstevel@tonic-gate return (interface_addr.s_addr);
347*7c478bd9Sstevel@tonic-gate }
348*7c478bd9Sstevel@tonic-gate
349*7c478bd9Sstevel@tonic-gate if (debug) {
350*7c478bd9Sstevel@tonic-gate msgout("interface_addr = %s.", inet_ntoa(interface_addr));
351*7c478bd9Sstevel@tonic-gate msgout("interface_mask = %s", inet_ntoa(interface_mask));
352*7c478bd9Sstevel@tonic-gate }
353*7c478bd9Sstevel@tonic-gate
354*7c478bd9Sstevel@tonic-gate
355*7c478bd9Sstevel@tonic-gate /*
356*7c478bd9Sstevel@tonic-gate * The routing table group.
357*7c478bd9Sstevel@tonic-gate */
358*7c478bd9Sstevel@tonic-gate for (item = item_list; item; item = item->next_item) {
359*7c478bd9Sstevel@tonic-gate if ((item->group == MIB2_IP) && (item->mib_id == MIB2_IP_21)) {
360*7c478bd9Sstevel@tonic-gate if (debug)
361*7c478bd9Sstevel@tonic-gate msgout("%lu records for ipRouteEntryTable",
362*7c478bd9Sstevel@tonic-gate item->length /
363*7c478bd9Sstevel@tonic-gate sizeof (mib2_ipRouteEntry_t));
364*7c478bd9Sstevel@tonic-gate
365*7c478bd9Sstevel@tonic-gate for (rp = (mib2_ipRouteEntry_t *)(void *)item->valp;
366*7c478bd9Sstevel@tonic-gate (char *)rp < item->valp + item->length;
367*7c478bd9Sstevel@tonic-gate rp++) {
368*7c478bd9Sstevel@tonic-gate if (debug >= 2)
369*7c478bd9Sstevel@tonic-gate msgout("ire_type = %d, next_hop = 0x%x",
370*7c478bd9Sstevel@tonic-gate rp->ipRouteInfo.re_ire_type,
371*7c478bd9Sstevel@tonic-gate rp->ipRouteNextHop);
372*7c478bd9Sstevel@tonic-gate
373*7c478bd9Sstevel@tonic-gate /*
374*7c478bd9Sstevel@tonic-gate * We are only interested in real
375*7c478bd9Sstevel@tonic-gate * gateway routes.
376*7c478bd9Sstevel@tonic-gate */
377*7c478bd9Sstevel@tonic-gate if ((rp->ipRouteInfo.re_ire_type !=
378*7c478bd9Sstevel@tonic-gate IRE_DEFAULT) &&
379*7c478bd9Sstevel@tonic-gate (rp->ipRouteInfo.re_ire_type !=
380*7c478bd9Sstevel@tonic-gate IRE_PREFIX) &&
381*7c478bd9Sstevel@tonic-gate (rp->ipRouteInfo.re_ire_type !=
382*7c478bd9Sstevel@tonic-gate IRE_HOST) &&
383*7c478bd9Sstevel@tonic-gate (rp->ipRouteInfo.re_ire_type !=
384*7c478bd9Sstevel@tonic-gate IRE_HOST_REDIRECT))
385*7c478bd9Sstevel@tonic-gate continue;
386*7c478bd9Sstevel@tonic-gate
387*7c478bd9Sstevel@tonic-gate /*
388*7c478bd9Sstevel@tonic-gate * We are only interested in routes with
389*7c478bd9Sstevel@tonic-gate * a next hop on the same subnet as
390*7c478bd9Sstevel@tonic-gate * the client.
391*7c478bd9Sstevel@tonic-gate */
392*7c478bd9Sstevel@tonic-gate if ((rp->ipRouteNextHop &
393*7c478bd9Sstevel@tonic-gate interface_mask.s_addr) !=
394*7c478bd9Sstevel@tonic-gate (interface_addr.s_addr &
395*7c478bd9Sstevel@tonic-gate interface_mask.s_addr))
396*7c478bd9Sstevel@tonic-gate continue;
397*7c478bd9Sstevel@tonic-gate
398*7c478bd9Sstevel@tonic-gate /*
399*7c478bd9Sstevel@tonic-gate * We have a valid route. Give preference
400*7c478bd9Sstevel@tonic-gate * to default routes.
401*7c478bd9Sstevel@tonic-gate */
402*7c478bd9Sstevel@tonic-gate if ((rp->ipRouteDest == 0) ||
403*7c478bd9Sstevel@tonic-gate (best_router.s_addr == 0))
404*7c478bd9Sstevel@tonic-gate best_router.s_addr =
405*7c478bd9Sstevel@tonic-gate rp->ipRouteNextHop;
406*7c478bd9Sstevel@tonic-gate }
407*7c478bd9Sstevel@tonic-gate }
408*7c478bd9Sstevel@tonic-gate }
409*7c478bd9Sstevel@tonic-gate
410*7c478bd9Sstevel@tonic-gate if (debug && (best_router.s_addr == 0))
411*7c478bd9Sstevel@tonic-gate msgout("get_ip_route: no route found for client");
412*7c478bd9Sstevel@tonic-gate
413*7c478bd9Sstevel@tonic-gate (void) close(sd);
414*7c478bd9Sstevel@tonic-gate free_itemlist(item_list);
415*7c478bd9Sstevel@tonic-gate return (best_router.s_addr);
416*7c478bd9Sstevel@tonic-gate }
417*7c478bd9Sstevel@tonic-gate
418*7c478bd9Sstevel@tonic-gate /*
419*7c478bd9Sstevel@tonic-gate * Return address of server interface closest to client.
420*7c478bd9Sstevel@tonic-gate *
421*7c478bd9Sstevel@tonic-gate * If the server has only a single IP address return it. Otherwise check
422*7c478bd9Sstevel@tonic-gate * if the server has an interface on the same subnet as the client and
423*7c478bd9Sstevel@tonic-gate * return the address of that interface.
424*7c478bd9Sstevel@tonic-gate */
425*7c478bd9Sstevel@tonic-gate
426*7c478bd9Sstevel@tonic-gate in_addr_t
find_best_server_int(char ** addr_list,char * client_name)427*7c478bd9Sstevel@tonic-gate find_best_server_int(char **addr_list, char *client_name)
428*7c478bd9Sstevel@tonic-gate {
429*7c478bd9Sstevel@tonic-gate in_addr_t server_addr = 0;
430*7c478bd9Sstevel@tonic-gate struct hostent h, *hp;
431*7c478bd9Sstevel@tonic-gate char hbuf[NSS_BUFLEN_HOSTS];
432*7c478bd9Sstevel@tonic-gate int err;
433*7c478bd9Sstevel@tonic-gate struct in_addr client_addr;
434*7c478bd9Sstevel@tonic-gate mib_item_t *item_list;
435*7c478bd9Sstevel@tonic-gate mib_item_t *item;
436*7c478bd9Sstevel@tonic-gate int sd;
437*7c478bd9Sstevel@tonic-gate mib2_ipAddrEntry_t *map;
438*7c478bd9Sstevel@tonic-gate in_addr_t client_net = 0, client_mask = 0;
439*7c478bd9Sstevel@tonic-gate boolean_t found_client_int;
440*7c478bd9Sstevel@tonic-gate
441*7c478bd9Sstevel@tonic-gate (void) memcpy(&server_addr, addr_list[0], sizeof (in_addr_t));
442*7c478bd9Sstevel@tonic-gate if (addr_list[1] == NULL)
443*7c478bd9Sstevel@tonic-gate return (server_addr);
444*7c478bd9Sstevel@tonic-gate
445*7c478bd9Sstevel@tonic-gate hp = gethostbyname_r(client_name, &h, hbuf, sizeof (hbuf), &err);
446*7c478bd9Sstevel@tonic-gate if (hp == NULL)
447*7c478bd9Sstevel@tonic-gate return (server_addr);
448*7c478bd9Sstevel@tonic-gate (void) memcpy(&client_addr, hp->h_addr_list[0], sizeof (client_addr));
449*7c478bd9Sstevel@tonic-gate
450*7c478bd9Sstevel@tonic-gate /* open a stream to IP */
451*7c478bd9Sstevel@tonic-gate sd = open("/dev/ip", O_RDWR);
452*7c478bd9Sstevel@tonic-gate if (sd == -1) {
453*7c478bd9Sstevel@tonic-gate perror("ip open");
454*7c478bd9Sstevel@tonic-gate (void) close(sd);
455*7c478bd9Sstevel@tonic-gate msgout("can't open mib stream");
456*7c478bd9Sstevel@tonic-gate return (server_addr);
457*7c478bd9Sstevel@tonic-gate }
458*7c478bd9Sstevel@tonic-gate
459*7c478bd9Sstevel@tonic-gate /* send down a request and suck up all the mib info from IP */
460*7c478bd9Sstevel@tonic-gate if ((item_list = mibget(sd)) == nilp(mib_item_t)) {
461*7c478bd9Sstevel@tonic-gate msgout("mibget() failed");
462*7c478bd9Sstevel@tonic-gate (void) close(sd);
463*7c478bd9Sstevel@tonic-gate return (server_addr);
464*7c478bd9Sstevel@tonic-gate }
465*7c478bd9Sstevel@tonic-gate (void) close(sd);
466*7c478bd9Sstevel@tonic-gate
467*7c478bd9Sstevel@tonic-gate /*
468*7c478bd9Sstevel@tonic-gate * Search through the list for our interface which is on the same
469*7c478bd9Sstevel@tonic-gate * subnet as the client and get the netmask.
470*7c478bd9Sstevel@tonic-gate */
471*7c478bd9Sstevel@tonic-gate for (item = item_list, found_client_int = B_FALSE;
472*7c478bd9Sstevel@tonic-gate item != NULL && !found_client_int; item = item->next_item) {
473*7c478bd9Sstevel@tonic-gate if ((item->group == MIB2_IP) && (item->mib_id == MIB2_IP_20)) {
474*7c478bd9Sstevel@tonic-gate /*
475*7c478bd9Sstevel@tonic-gate * Try to find out which interface is up, configured,
476*7c478bd9Sstevel@tonic-gate * not loopback, and on the same subnet as the client.
477*7c478bd9Sstevel@tonic-gate * Save its address and netmask.
478*7c478bd9Sstevel@tonic-gate */
479*7c478bd9Sstevel@tonic-gate map = (mib2_ipAddrEntry_t *)(void *)item->valp;
480*7c478bd9Sstevel@tonic-gate while ((char *)map < item->valp + item->length) {
481*7c478bd9Sstevel@tonic-gate in_addr_t addr, mask, net;
482*7c478bd9Sstevel@tonic-gate int ifflags;
483*7c478bd9Sstevel@tonic-gate
484*7c478bd9Sstevel@tonic-gate ifflags = map->ipAdEntInfo.ae_flags;
485*7c478bd9Sstevel@tonic-gate addr = map->ipAdEntAddr;
486*7c478bd9Sstevel@tonic-gate mask = map->ipAdEntNetMask;
487*7c478bd9Sstevel@tonic-gate net = addr & mask;
488*7c478bd9Sstevel@tonic-gate
489*7c478bd9Sstevel@tonic-gate if ((ifflags & IFF_LOOPBACK|IFF_UP) == IFF_UP &&
490*7c478bd9Sstevel@tonic-gate addr != INADDR_ANY &&
491*7c478bd9Sstevel@tonic-gate (client_addr.s_addr & mask) == net) {
492*7c478bd9Sstevel@tonic-gate client_net = net;
493*7c478bd9Sstevel@tonic-gate client_mask = mask;
494*7c478bd9Sstevel@tonic-gate found_client_int = B_TRUE;
495*7c478bd9Sstevel@tonic-gate break;
496*7c478bd9Sstevel@tonic-gate }
497*7c478bd9Sstevel@tonic-gate map++;
498*7c478bd9Sstevel@tonic-gate }
499*7c478bd9Sstevel@tonic-gate }
500*7c478bd9Sstevel@tonic-gate }
501*7c478bd9Sstevel@tonic-gate
502*7c478bd9Sstevel@tonic-gate /*
503*7c478bd9Sstevel@tonic-gate * If we found the interface check which is the best IP address.
504*7c478bd9Sstevel@tonic-gate */
505*7c478bd9Sstevel@tonic-gate if (found_client_int) {
506*7c478bd9Sstevel@tonic-gate while (*addr_list != NULL) {
507*7c478bd9Sstevel@tonic-gate in_addr_t addr;
508*7c478bd9Sstevel@tonic-gate
509*7c478bd9Sstevel@tonic-gate (void) memcpy(&addr, *addr_list, sizeof (in_addr_t));
510*7c478bd9Sstevel@tonic-gate if ((addr & client_mask) == client_net) {
511*7c478bd9Sstevel@tonic-gate server_addr = addr;
512*7c478bd9Sstevel@tonic-gate break;
513*7c478bd9Sstevel@tonic-gate }
514*7c478bd9Sstevel@tonic-gate addr_list++;
515*7c478bd9Sstevel@tonic-gate }
516*7c478bd9Sstevel@tonic-gate }
517*7c478bd9Sstevel@tonic-gate
518*7c478bd9Sstevel@tonic-gate if (debug && server_addr == 0)
519*7c478bd9Sstevel@tonic-gate msgout("No usable interface for returning reply");
520*7c478bd9Sstevel@tonic-gate
521*7c478bd9Sstevel@tonic-gate free_itemlist(item_list);
522*7c478bd9Sstevel@tonic-gate return (server_addr);
523*7c478bd9Sstevel@tonic-gate }
524