xref: /freebsd/usr.sbin/ppp/route.c (revision 927145be97d8d5b69a0a1a86dc7e9d637102c7d0)
1af57ed9fSAtsushi Murai /*
2af57ed9fSAtsushi Murai  *	      PPP Routing related Module
3af57ed9fSAtsushi Murai  *
4af57ed9fSAtsushi Murai  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5af57ed9fSAtsushi Murai  *
6af57ed9fSAtsushi Murai  *   Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd.
7af57ed9fSAtsushi Murai  *
8af57ed9fSAtsushi Murai  * Redistribution and use in source and binary forms are permitted
9af57ed9fSAtsushi Murai  * provided that the above copyright notice and this paragraph are
10af57ed9fSAtsushi Murai  * duplicated in all such forms and that any documentation,
11af57ed9fSAtsushi Murai  * advertising materials, and other materials related to such
12af57ed9fSAtsushi Murai  * distribution and use acknowledge that the software was developed
13af57ed9fSAtsushi Murai  * by the Internet Initiative Japan, Inc.  The name of the
14af57ed9fSAtsushi Murai  * IIJ may not be used to endorse or promote products derived
15af57ed9fSAtsushi Murai  * from this software without specific prior written permission.
16af57ed9fSAtsushi Murai  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17af57ed9fSAtsushi Murai  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18af57ed9fSAtsushi Murai  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19af57ed9fSAtsushi Murai  *
20927145beSBrian Somers  * $Id: route.c,v 1.13 1997/05/10 01:22:18 brian Exp $
2153c9f6c0SAtsushi Murai  *
22af57ed9fSAtsushi Murai  */
23af57ed9fSAtsushi Murai #include <sys/types.h>
24af57ed9fSAtsushi Murai #include <machine/endian.h>
25628d2ac1SGarrett Wollman #include <sys/ioctl.h>
26af57ed9fSAtsushi Murai #include <sys/param.h>
27af57ed9fSAtsushi Murai #include <sys/socket.h>
28af57ed9fSAtsushi Murai #include <sys/sysctl.h>
29628d2ac1SGarrett Wollman #include <sys/time.h>
30628d2ac1SGarrett Wollman 
31628d2ac1SGarrett Wollman #include <errno.h>
32af57ed9fSAtsushi Murai #include <stdlib.h>
33af57ed9fSAtsushi Murai #include <stdio.h>
34af57ed9fSAtsushi Murai #include <string.h>
35af57ed9fSAtsushi Murai #include <unistd.h>
36628d2ac1SGarrett Wollman 
37628d2ac1SGarrett Wollman #include <net/route.h>
38628d2ac1SGarrett Wollman #include <net/if.h>
39628d2ac1SGarrett Wollman #include <netinet/in_systm.h>
40628d2ac1SGarrett Wollman #include <netinet/in.h>
41628d2ac1SGarrett Wollman #include <arpa/inet.h>
42628d2ac1SGarrett Wollman 
43215a4696SAtsushi Murai #include "log.h"
44927145beSBrian Somers #include "loadalias.h"
45927145beSBrian Somers #include "vars.h"
46af57ed9fSAtsushi Murai 
47af57ed9fSAtsushi Murai static int IfIndex;
48af57ed9fSAtsushi Murai 
49af57ed9fSAtsushi Murai struct rtmsg {
50af57ed9fSAtsushi Murai   struct rt_msghdr m_rtm;
51af57ed9fSAtsushi Murai   char m_space[64];
52af57ed9fSAtsushi Murai };
53af57ed9fSAtsushi Murai 
54af57ed9fSAtsushi Murai static int seqno;
55af57ed9fSAtsushi Murai 
56af57ed9fSAtsushi Murai void
57af57ed9fSAtsushi Murai OsSetRoute(cmd, dst, gateway, mask)
58af57ed9fSAtsushi Murai int cmd;
59af57ed9fSAtsushi Murai struct in_addr dst;
60af57ed9fSAtsushi Murai struct in_addr gateway;
61af57ed9fSAtsushi Murai struct in_addr mask;
62af57ed9fSAtsushi Murai {
63af57ed9fSAtsushi Murai   struct rtmsg rtmes;
64af57ed9fSAtsushi Murai   int s, nb, wb;
65af57ed9fSAtsushi Murai   char *cp;
66af57ed9fSAtsushi Murai   u_long *lp;
67af57ed9fSAtsushi Murai   struct sockaddr_in rtdata;
68af57ed9fSAtsushi Murai 
69af57ed9fSAtsushi Murai   s = socket(PF_ROUTE, SOCK_RAW, 0);
70af57ed9fSAtsushi Murai   if (s < 0)
71927145beSBrian Somers     LogPrintf(LogERROR, "socket: %s", strerror(errno));
72af57ed9fSAtsushi Murai 
73af57ed9fSAtsushi Murai   bzero(&rtmes, sizeof(rtmes));
74af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_version = RTM_VERSION;
75af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_type = cmd;
76af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_addrs = RTA_DST | RTA_NETMASK;
77af57ed9fSAtsushi Murai   if (cmd == RTM_ADD) rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
78af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_seq = ++seqno;
79af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_pid = getpid();
802db86e5bSPeter Wemm   rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
81af57ed9fSAtsushi Murai 
82af57ed9fSAtsushi Murai   bzero(&rtdata, sizeof(rtdata));
83af57ed9fSAtsushi Murai   rtdata.sin_len = 16;
84af57ed9fSAtsushi Murai   rtdata.sin_family = AF_INET;
85af57ed9fSAtsushi Murai   rtdata.sin_port = 0;
86af57ed9fSAtsushi Murai   rtdata.sin_addr = dst;
87af57ed9fSAtsushi Murai 
88af57ed9fSAtsushi Murai   cp = rtmes.m_space;
89af57ed9fSAtsushi Murai   bcopy(&rtdata, cp, 16);
90af57ed9fSAtsushi Murai   cp += 16;
91af57ed9fSAtsushi Murai   if (gateway.s_addr) {
92af57ed9fSAtsushi Murai     rtdata.sin_addr = gateway;
93af57ed9fSAtsushi Murai     bcopy(&rtdata, cp, 16);
94af57ed9fSAtsushi Murai     cp += 16;
95af57ed9fSAtsushi Murai   }
96af57ed9fSAtsushi Murai 
97af57ed9fSAtsushi Murai   if (dst.s_addr == INADDR_ANY)
98af57ed9fSAtsushi Murai     mask.s_addr = INADDR_ANY;
99af57ed9fSAtsushi Murai 
100af57ed9fSAtsushi Murai   lp = (u_long *)cp;
101af57ed9fSAtsushi Murai 
102af57ed9fSAtsushi Murai   if (mask.s_addr) {
103af57ed9fSAtsushi Murai     *lp++ = 8;
104af57ed9fSAtsushi Murai     cp += sizeof(int);
105af57ed9fSAtsushi Murai     *lp = mask.s_addr;
106af57ed9fSAtsushi Murai   } else
107af57ed9fSAtsushi Murai     *lp = 0;
108af57ed9fSAtsushi Murai   cp += sizeof(u_long);
109af57ed9fSAtsushi Murai 
110af57ed9fSAtsushi Murai   nb = cp - (char *)&rtmes;
111af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_msglen = nb;
112af57ed9fSAtsushi Murai   wb = write(s, &rtmes, nb);
113af57ed9fSAtsushi Murai   if (wb < 0) {
114927145beSBrian Somers      LogPrintf(LogTCPIP, "Already set route addr dst=%x, gateway=%x\n"
115215a4696SAtsushi Murai          ,dst.s_addr, gateway.s_addr);
116af57ed9fSAtsushi Murai   }
117927145beSBrian Somers   LogPrintf(LogDEBUG, "wrote %d: dst = %x, gateway = %x\n", nb,
118927145beSBrian Somers             dst.s_addr, gateway.s_addr);
119af57ed9fSAtsushi Murai   close(s);
120af57ed9fSAtsushi Murai }
121af57ed9fSAtsushi Murai 
122af57ed9fSAtsushi Murai static void
123af57ed9fSAtsushi Murai p_sockaddr(sa, width)
124af57ed9fSAtsushi Murai struct sockaddr *sa;
125af57ed9fSAtsushi Murai int width;
126af57ed9fSAtsushi Murai {
127927145beSBrian Somers   if (VarTerm) {
128af57ed9fSAtsushi Murai     register char *cp;
129af57ed9fSAtsushi Murai     register struct sockaddr_in *sin = (struct sockaddr_in *)sa;
130af57ed9fSAtsushi Murai 
131af57ed9fSAtsushi Murai     cp = (sin->sin_addr.s_addr == 0) ? "default" :
132af57ed9fSAtsushi Murai 	   inet_ntoa(sin->sin_addr);
133927145beSBrian Somers     fprintf(VarTerm, "%-*.*s ", width, width, cp);
134927145beSBrian Somers   }
135af57ed9fSAtsushi Murai }
136af57ed9fSAtsushi Murai 
137af57ed9fSAtsushi Murai struct bits {
138af57ed9fSAtsushi Murai   short b_mask;
139af57ed9fSAtsushi Murai   char  b_val;
140af57ed9fSAtsushi Murai } bits[] = {
141af57ed9fSAtsushi Murai   { RTF_UP,	  'U' },
142af57ed9fSAtsushi Murai   { RTF_GATEWAY,  'G' },
143af57ed9fSAtsushi Murai   { RTF_HOST,	  'H' },
144af57ed9fSAtsushi Murai   { RTF_DYNAMIC,  'D' },
145af57ed9fSAtsushi Murai   { RTF_MODIFIED, 'M' },
146af57ed9fSAtsushi Murai   { RTF_CLONING,  'C' },
147af57ed9fSAtsushi Murai   { RTF_XRESOLVE, 'X' },
148af57ed9fSAtsushi Murai   { RTF_LLINFO,   'L' },
149af57ed9fSAtsushi Murai   { RTF_REJECT,   'R' },
150af57ed9fSAtsushi Murai   { 0 }
151af57ed9fSAtsushi Murai };
152af57ed9fSAtsushi Murai 
153af57ed9fSAtsushi Murai static void
154af57ed9fSAtsushi Murai p_flags(f, format)
155af57ed9fSAtsushi Murai register int f;
156af57ed9fSAtsushi Murai char *format;
157af57ed9fSAtsushi Murai {
158927145beSBrian Somers   if (VarTerm) {
159af57ed9fSAtsushi Murai     char name[33], *flags;
160af57ed9fSAtsushi Murai     register struct bits *p = bits;
161af57ed9fSAtsushi Murai 
162af57ed9fSAtsushi Murai     for (flags = name; p->b_mask; p++)
163af57ed9fSAtsushi Murai       if (p->b_mask & f)
164af57ed9fSAtsushi Murai         *flags++ = p->b_val;
165af57ed9fSAtsushi Murai     *flags = '\0';
166927145beSBrian Somers     fprintf(VarTerm, format, name);
167927145beSBrian Somers   }
168af57ed9fSAtsushi Murai }
169af57ed9fSAtsushi Murai 
170af57ed9fSAtsushi Murai int
171af57ed9fSAtsushi Murai ShowRoute()
172af57ed9fSAtsushi Murai {
173af57ed9fSAtsushi Murai   struct rt_msghdr *rtm;
174af57ed9fSAtsushi Murai   struct sockaddr *sa;
175af57ed9fSAtsushi Murai   char *sp, *ep, *cp;
176af57ed9fSAtsushi Murai   u_char *wp;
177af57ed9fSAtsushi Murai   int *lp;
178af57ed9fSAtsushi Murai   int needed, nb;
179af57ed9fSAtsushi Murai   u_long mask;
180af57ed9fSAtsushi Murai   int mib[6];
181af57ed9fSAtsushi Murai 
182927145beSBrian Somers   if (!VarTerm)
183927145beSBrian Somers     return 1;
184927145beSBrian Somers 
185af57ed9fSAtsushi Murai   mib[0] = CTL_NET;
186af57ed9fSAtsushi Murai   mib[1] = PF_ROUTE;
18753c9f6c0SAtsushi Murai   mib[2] = 0;
18853c9f6c0SAtsushi Murai   mib[3] = 0;
189af57ed9fSAtsushi Murai   mib[4] = NET_RT_DUMP;
19053c9f6c0SAtsushi Murai   mib[5] = 0;
19153c9f6c0SAtsushi Murai   if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
192927145beSBrian Somers     LogPrintf(LogERROR, "sysctl: estimate: %s", strerror(errno));
19353c9f6c0SAtsushi Murai     return(1);
19453c9f6c0SAtsushi Murai   }
195927145beSBrian Somers 
196af57ed9fSAtsushi Murai   if (needed < 0)
197af57ed9fSAtsushi Murai     return(1);
198af57ed9fSAtsushi Murai   sp = malloc(needed);
199af57ed9fSAtsushi Murai   if (sp == NULL)
200af57ed9fSAtsushi Murai     return(1);
20153c9f6c0SAtsushi Murai   if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
202927145beSBrian Somers     LogPrintf(LogERROR, "sysctl: getroute: %s", strerror(errno));
203b0cdb3ceSJordan K. Hubbard     free(sp);
204af57ed9fSAtsushi Murai     return(1);
20553c9f6c0SAtsushi Murai   }
206927145beSBrian Somers 
207af57ed9fSAtsushi Murai   ep = sp + needed;
208af57ed9fSAtsushi Murai 
209af57ed9fSAtsushi Murai   for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
210af57ed9fSAtsushi Murai     rtm = (struct rt_msghdr *)cp;
211af57ed9fSAtsushi Murai     sa = (struct sockaddr *)(rtm + 1);
212af57ed9fSAtsushi Murai     mask = 0xffffffff;
213af57ed9fSAtsushi Murai     if (rtm->rtm_addrs == RTA_DST)
214af57ed9fSAtsushi Murai       p_sockaddr(sa, 36);
215af57ed9fSAtsushi Murai     else {
216af57ed9fSAtsushi Murai       wp = (u_char *)cp + rtm->rtm_msglen;
217af57ed9fSAtsushi Murai       p_sockaddr(sa, 16);
218af57ed9fSAtsushi Murai       if (sa->sa_len == 0)
219af57ed9fSAtsushi Murai 	sa->sa_len = sizeof(long);
220af57ed9fSAtsushi Murai       sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
221af57ed9fSAtsushi Murai       p_sockaddr(sa, 18);
222af57ed9fSAtsushi Murai       lp = (int *)(sa->sa_len + (char *)sa);
223af57ed9fSAtsushi Murai       if ((char *)lp < (char *)wp && *lp) {
224927145beSBrian Somers 	LogPrintf(LogDEBUG, " flag = %x, rest = %d", rtm->rtm_flags, *lp);
225af57ed9fSAtsushi Murai 	wp = (u_char *)(lp + 1);
226af57ed9fSAtsushi Murai 	mask = 0;
227b0cdb3ceSJordan K. Hubbard 	for (nb = *(char *)lp; nb > 4; nb--) {
228af57ed9fSAtsushi Murai 	  mask <<= 8;
229af57ed9fSAtsushi Murai 	  mask |= *wp++;
230af57ed9fSAtsushi Murai 	}
231b0cdb3ceSJordan K. Hubbard 	for (nb = 8 - *(char *)lp; nb > 0; nb--)
232af57ed9fSAtsushi Murai 	  mask <<= 8;
233af57ed9fSAtsushi Murai       }
234af57ed9fSAtsushi Murai     }
235927145beSBrian Somers     fprintf(VarTerm, "%08lx  ", mask);
236af57ed9fSAtsushi Murai     p_flags(rtm->rtm_flags & (RTF_UP|RTF_GATEWAY|RTF_HOST), "%-6.6s ");
237927145beSBrian Somers     fprintf(VarTerm, "(%d)\n", rtm->rtm_index);
238af57ed9fSAtsushi Murai   }
239b0cdb3ceSJordan K. Hubbard   free(sp);
240927145beSBrian Somers   return 0;
241af57ed9fSAtsushi Murai }
242af57ed9fSAtsushi Murai 
243af57ed9fSAtsushi Murai /*
244af57ed9fSAtsushi Murai  *  Delete routes associated with our interface
245af57ed9fSAtsushi Murai  */
246af57ed9fSAtsushi Murai void
247af57ed9fSAtsushi Murai DeleteIfRoutes(all)
248af57ed9fSAtsushi Murai int all;
249af57ed9fSAtsushi Murai {
250af57ed9fSAtsushi Murai   struct rt_msghdr *rtm;
251af57ed9fSAtsushi Murai   struct sockaddr *sa;
2529c749ffbSPoul-Henning Kamp   struct in_addr dstnet, gateway, maddr;
253af57ed9fSAtsushi Murai   int needed;
254af57ed9fSAtsushi Murai   char *sp, *cp, *ep;
255af57ed9fSAtsushi Murai   u_long mask;
256af57ed9fSAtsushi Murai   int *lp, nb;
257af57ed9fSAtsushi Murai   u_char *wp;
258af57ed9fSAtsushi Murai   int mib[6];
259af57ed9fSAtsushi Murai 
260927145beSBrian Somers   LogPrintf(LogDEBUG, "DeleteIfRoutes (%d)\n", IfIndex);
261927145beSBrian Somers 
262af57ed9fSAtsushi Murai   mib[0] = CTL_NET;
263af57ed9fSAtsushi Murai   mib[1] = PF_ROUTE;
26453c9f6c0SAtsushi Murai   mib[2] = 0;
26553c9f6c0SAtsushi Murai   mib[3] = 0;
266af57ed9fSAtsushi Murai   mib[4] = NET_RT_DUMP;
26753c9f6c0SAtsushi Murai   mib[5] = 0;
26853c9f6c0SAtsushi Murai   if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
269927145beSBrian Somers     LogPrintf(LogERROR, "sysctl: estimate: %s", strerror(errno));
27053c9f6c0SAtsushi Murai     return;
27153c9f6c0SAtsushi Murai   }
27253c9f6c0SAtsushi Murai 
273af57ed9fSAtsushi Murai   if (needed < 0)
274af57ed9fSAtsushi Murai     return;
275af57ed9fSAtsushi Murai 
276af57ed9fSAtsushi Murai   sp = malloc(needed);
277af57ed9fSAtsushi Murai   if (sp == NULL)
278af57ed9fSAtsushi Murai     return;
279af57ed9fSAtsushi Murai 
280af57ed9fSAtsushi Murai   if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
281927145beSBrian Somers     LogPrintf(LogERROR, "sysctl: getroute: %s", strerror(errno));
282af57ed9fSAtsushi Murai     free(sp);
283af57ed9fSAtsushi Murai     return;
284af57ed9fSAtsushi Murai   }
285af57ed9fSAtsushi Murai   ep = sp + needed;
286af57ed9fSAtsushi Murai 
287af57ed9fSAtsushi Murai   for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
288af57ed9fSAtsushi Murai     rtm = (struct rt_msghdr *)cp;
289af57ed9fSAtsushi Murai     sa = (struct sockaddr *)(rtm + 1);
290927145beSBrian Somers     LogPrintf(LogDEBUG, "DeleteIfRoutes: addrs: %x, index: %d, flags: %x,"
291927145beSBrian Somers 			" dstnet: %x\n",
292af57ed9fSAtsushi Murai 			rtm->rtm_addrs, rtm->rtm_index, rtm->rtm_flags,
293af57ed9fSAtsushi Murai 			((struct sockaddr_in *)sa)->sin_addr);
294af57ed9fSAtsushi Murai     if (rtm->rtm_addrs != RTA_DST &&
295af57ed9fSAtsushi Murai        (rtm->rtm_index == IfIndex) &&
296af57ed9fSAtsushi Murai        (all || (rtm->rtm_flags & RTF_GATEWAY))) {
297af57ed9fSAtsushi Murai       dstnet = ((struct sockaddr_in *)sa)->sin_addr;
298af57ed9fSAtsushi Murai       wp = (u_char *)cp + rtm->rtm_msglen;
299af57ed9fSAtsushi Murai       if (sa->sa_len == 0)
300af57ed9fSAtsushi Murai 	sa->sa_len = sizeof(long);
301af57ed9fSAtsushi Murai       sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
302af57ed9fSAtsushi Murai       gateway = ((struct sockaddr_in *)sa)->sin_addr;
303af57ed9fSAtsushi Murai       lp = (int *)(sa->sa_len + (char *)sa);
304af57ed9fSAtsushi Murai       mask = 0;
305af57ed9fSAtsushi Murai       if ((char *)lp < (char *)wp && *lp) {
306927145beSBrian Somers 	LogPrintf(LogDEBUG, "DeleteIfRoutes: flag = %x, rest = %d",
307927145beSBrian Somers 		  rtm->rtm_flags, *lp);
308af57ed9fSAtsushi Murai 	wp = (u_char *)(lp + 1);
309af57ed9fSAtsushi Murai 	for (nb = *lp; nb > 4; nb--) {
310af57ed9fSAtsushi Murai 	  mask <<= 8;
311af57ed9fSAtsushi Murai 	  mask |= *wp++;
312af57ed9fSAtsushi Murai 	}
313af57ed9fSAtsushi Murai 	for (nb = 8 - *lp; nb > 0; nb--)
314af57ed9fSAtsushi Murai 	  mask <<= 8;
315af57ed9fSAtsushi Murai       }
316927145beSBrian Somers       LogPrintf(LogDEBUG, "DeleteIfRoutes: Dest: %s\n", inet_ntoa(dstnet));
317927145beSBrian Somers       LogPrintf(LogDEBUG, "DeleteIfRoutes: Gw: %s\n", inet_ntoa(gateway));
318927145beSBrian Somers       LogPrintf(LogDEBUG, "DeleteIfRoutes: Index: %d\n", rtm->rtm_index);
319af57ed9fSAtsushi Murai       if (dstnet.s_addr == INADDR_ANY) {
320af57ed9fSAtsushi Murai         gateway.s_addr = INADDR_ANY;
321af57ed9fSAtsushi Murai         mask = INADDR_ANY;
322af57ed9fSAtsushi Murai       }
3239c749ffbSPoul-Henning Kamp       maddr.s_addr = htonl(mask);
3249c749ffbSPoul-Henning Kamp       OsSetRoute(RTM_DELETE, dstnet, gateway, maddr);
325af57ed9fSAtsushi Murai     }
326927145beSBrian Somers     else if(rtm->rtm_index == IfIndex)
327927145beSBrian Somers       LogPrintf(LogDEBUG, "DeleteIfRoutes: Ignoring (looking for index %d)\n",
328927145beSBrian Somers 		IfIndex);
329af57ed9fSAtsushi Murai   }
330af57ed9fSAtsushi Murai   free(sp);
331af57ed9fSAtsushi Murai }
332af57ed9fSAtsushi Murai 
333d8e55738SJordan K. Hubbard  /*
334d8e55738SJordan K. Hubbard   * 960603 - Modified to use dynamic buffer allocator as in ifconfig
335d8e55738SJordan K. Hubbard   */
336d8e55738SJordan K. Hubbard 
337af57ed9fSAtsushi Murai int
338af57ed9fSAtsushi Murai GetIfIndex(name)
339af57ed9fSAtsushi Murai char *name;
340af57ed9fSAtsushi Murai {
341d8e55738SJordan K. Hubbard   char *buffer;
342af57ed9fSAtsushi Murai   struct ifreq *ifrp;
343af57ed9fSAtsushi Murai   int s, len, elen, index;
344af57ed9fSAtsushi Murai   struct ifconf ifconfs;
345d8e55738SJordan K. Hubbard   /* struct ifreq reqbuf[256]; -- obsoleted :) */
346d8e55738SJordan K. Hubbard   int oldbufsize, bufsize = sizeof(struct ifreq);
347af57ed9fSAtsushi Murai 
348af57ed9fSAtsushi Murai   s = socket(AF_INET, SOCK_DGRAM, 0);
349af57ed9fSAtsushi Murai   if (s < 0) {
350927145beSBrian Somers     LogPrintf(LogERROR, "socket: %s", strerror(errno));
351af57ed9fSAtsushi Murai     return(-1);
352af57ed9fSAtsushi Murai   }
353af57ed9fSAtsushi Murai 
354d8e55738SJordan K. Hubbard   buffer = malloc(bufsize);   /* allocate first buffer */
355d8e55738SJordan K. Hubbard   ifconfs.ifc_len = bufsize;  /* Initial setting */
356d8e55738SJordan K. Hubbard   /*
357d8e55738SJordan K. Hubbard    * Iterate through here until we don't get many more data
358d8e55738SJordan K. Hubbard    */
359d8e55738SJordan K. Hubbard 
360d8e55738SJordan K. Hubbard   do {
361d8e55738SJordan K. Hubbard       oldbufsize = ifconfs.ifc_len;
362d8e55738SJordan K. Hubbard       bufsize += 1+sizeof(struct ifreq);
363d8e55738SJordan K. Hubbard       buffer = realloc((void *)buffer, bufsize);      /* Make it bigger */
364927145beSBrian Somers       LogPrintf(LogDEBUG, "GetIfIndex: Growing buffer to %d\n", bufsize);
365d8e55738SJordan K. Hubbard       ifconfs.ifc_len = bufsize;
366d8e55738SJordan K. Hubbard       ifconfs.ifc_buf = buffer;
367af57ed9fSAtsushi Murai       if (ioctl(s, SIOCGIFCONF, &ifconfs) < 0) {
368927145beSBrian Somers           LogPrintf(LogERROR, "ioctl(SIOCGIFCONF): %s", strerror(errno));
369d8e55738SJordan K. Hubbard           free(buffer);
370af57ed9fSAtsushi Murai           return(-1);
371af57ed9fSAtsushi Murai       }
372d8e55738SJordan K. Hubbard   } while (ifconfs.ifc_len > oldbufsize);
373af57ed9fSAtsushi Murai 
374af57ed9fSAtsushi Murai   ifrp = ifconfs.ifc_req;
375af57ed9fSAtsushi Murai 
376af57ed9fSAtsushi Murai   index = 1;
377af57ed9fSAtsushi Murai   for (len = ifconfs.ifc_len; len > 0; len -= sizeof(struct ifreq)) {
378af57ed9fSAtsushi Murai     elen = ifrp->ifr_addr.sa_len - sizeof(struct sockaddr);
379af57ed9fSAtsushi Murai     if (ifrp->ifr_addr.sa_family == AF_LINK) {
380927145beSBrian Somers       LogPrintf(LogDEBUG, "GetIfIndex: %d: %-*.*s, %d, %d\n",
381927145beSBrian Somers 		index, IFNAMSIZ, IFNAMSIZ, ifrp->ifr_name,
382af57ed9fSAtsushi Murai 		ifrp->ifr_addr.sa_family, elen);
383af57ed9fSAtsushi Murai       if (strcmp(ifrp->ifr_name, name) == 0) {
384af57ed9fSAtsushi Murai         IfIndex = index;
385d8e55738SJordan K. Hubbard 	free(buffer);
386af57ed9fSAtsushi Murai         return(index);
387af57ed9fSAtsushi Murai       }
388af57ed9fSAtsushi Murai       index++;
389af57ed9fSAtsushi Murai     }
390af57ed9fSAtsushi Murai 
391af57ed9fSAtsushi Murai     len -= elen;
392af57ed9fSAtsushi Murai     ifrp = (struct ifreq *)((char *)ifrp + elen);
393af57ed9fSAtsushi Murai     ifrp++;
394af57ed9fSAtsushi Murai   }
395af57ed9fSAtsushi Murai 
396af57ed9fSAtsushi Murai   close(s);
397d8e55738SJordan K. Hubbard   free(buffer);
398af57ed9fSAtsushi Murai   return(-1);
399af57ed9fSAtsushi Murai }
400