Annotation of embedaddon/arping/src/findif_sysctl.c, revision 1.1.1.2
1.1 misho 1: /* arping/src/findif_sysctl.c
2: *
1.1.1.2 ! misho 3: * Copyright (C) 2000-2014 Thomas Habets <thomas@habets.se>
1.1 misho 4: *
1.1.1.2 ! misho 5: * This program is free software; you can redistribute it and/or modify
! 6: * it under the terms of the GNU General Public License as published by
! 7: * the Free Software Foundation; either version 2 of the License, or
! 8: * (at your option) any later version.
1.1 misho 9: *
1.1.1.2 ! misho 10: * This program is distributed in the hope that it will be useful,
1.1 misho 11: * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.1.1.2 ! misho 12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 13: * GNU General Public License for more details.
1.1 misho 14: *
15: * You should have received a copy of the GNU General Public License along
16: * with this program; if not, write to the Free Software Foundation, Inc.,
17: * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18: */
19: /**
20: * This file should never be used. Systems that are chosen for sysctl()
21: * should always have getifaddrs() which is preferred to this.
22: */
23: #if HAVE_CONFIG_H
24: #include "config.h"
25: #endif
26:
27: #include <stdio.h>
28: #include <stdlib.h>
29: #include <string.h>
30: #include <errno.h>
31: #include <netinet/in.h>
32: #include <arpa/inet.h>
33:
34: #include <sys/types.h>
35: #include <sys/socket.h>
36:
37: #include <sys/param.h>
38: #include <sys/sysctl.h>
39: #include <net/if.h>
40: #include <net/if_dl.h>
41: #include <net/route.h>
42:
1.1.1.2 ! misho 43: #if HAVE_LIBNET_H
! 44: #include <libnet.h>
! 45: #endif
! 46:
1.1 misho 47: #include "arping.h"
48:
49: #ifndef SALIGN
50: #define SALIGN (sizeof(int32_t) - 1)
51: #endif
52:
53: #ifndef SA_SIZE
54: #define SA_SIZE(sa) ((sa)->sa_len \
55: ? (((sa)->sa_len + SALIGN) & ~SALIGN)\
56: : (SALIGN + 1))
57: #endif
58:
59:
60: /**
61: *
62: */
63: const char *
64: arping_lookupdev(uint32_t srcip,
65: uint32_t dstip,
66: char *ebuf)
67: {
68: int mib[6] = {
69: CTL_NET,
70: PF_ROUTE,
71: 0, /* Protocol */
72: AF_INET, /* Address family */
73: NET_RT_IFLIST,
74: 0
75: };
76: int c;
77:
78: /* buffer */
1.1.1.2 ! misho 79: char *buf_memory = NULL;
! 80: char *lim;
1.1 misho 81: size_t bufsize;
82:
83: /* Matching interfaces */
84: int match_count = 0;
85:
86: /* best match */
87: in_addr_t best_mask = 0;
88: struct in_addr best_addr;
89:
90: /* Results */
91: static char ifName[IFNAMSIZ];
1.1.1.2 ! misho 92: *ebuf = 0;
1.1 misho 93:
94: /* Allocate buffer and retrieve data. */
95: for (c = 0;;) {
96: if (sysctl(mib, 6, NULL, &bufsize, NULL, 0) < 0) {
1.1.1.2 ! misho 97: snprintf(ebuf, LIBNET_ERRBUF_SIZE,
! 98: "sysctl: get buffer size error: %s",
! 99: strerror(errno));
1.1 misho 100: goto failed;
101: }
1.1.1.2 ! misho 102: if ((buf_memory = malloc(bufsize)) == NULL) {
! 103: snprintf(ebuf, LIBNET_ERRBUF_SIZE,
! 104: "malloc: error: %s", strerror(errno));
1.1 misho 105: goto failed;
106: }
1.1.1.2 ! misho 107: if (sysctl(mib, 6, buf_memory, &bufsize, NULL, 0) == 0) {
1.1 misho 108: break;
109: }
110: if (errno != ENOMEM || ++c >= 10 ) {
1.1.1.2 ! misho 111: snprintf(ebuf, LIBNET_ERRBUF_SIZE,
! 112: "sysctl: get ifaces error: %s",
! 113: strerror(errno));
1.1 misho 114: goto failed;
115: }
1.1.1.2 ! misho 116: if (verbose > 2) {
! 117: printf("sysctl: buffer size changed.");
! 118: }
! 119: free(buf_memory);
! 120: buf_memory = NULL;
1.1 misho 121: }
122:
1.1.1.2 ! misho 123: const char* buf = buf_memory;
1.1 misho 124: lim = buf + bufsize;
125:
126: /* Loop through all interfaces */
127: while (buf < lim) {
128: struct sockaddr_dl *sdl;
129: char tmpIfName[IFNAMSIZ];
130: int i;
131:
132: struct if_msghdr *ifh = (struct if_msghdr *)buf;
133: if (ifh->ifm_type != RTM_IFINFO) {
1.1.1.2 ! misho 134: snprintf(ebuf, LIBNET_ERRBUF_SIZE,
! 135: "Wrong data in NET_RT_IFLIST.");
1.1 misho 136: return NULL;
137: }
138: sdl = (struct sockaddr_dl *)(buf +
139: sizeof(struct if_msghdr) -
140: sizeof(struct if_data) +
141: sizeof(struct if_data));
142:
143: i = sdl->sdl_nlen < sizeof(ifName)
144: ? sdl->sdl_nlen
145: : (sizeof(tmpIfName)-1);
146: memcpy(tmpIfName, sdl->sdl_data, i);
147: tmpIfName[i] = 0;
148:
149: buf += ifh->ifm_msglen;
150:
151: /* Loop through all addresses of interface. */
152: while (buf < lim) {
153: struct ifa_msghdr *ifht = (struct ifa_msghdr *)buf;
154: char* addrptr;
155: struct sockaddr_in *if_addr = NULL;
156: struct sockaddr_in *if_nmsk = NULL;
157: struct sockaddr_in *if_bcst = NULL;
158: in_addr_t mask;
159:
160: if (ifht->ifam_type != RTM_NEWADDR) {
161: break;
162: }
163:
164: addrptr = buf + sizeof(struct ifa_msghdr);
165: buf += ifht->ifam_msglen;
166:
167: if (ifh->ifm_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) {
168: continue;
169: }
170:
171: /* Loop through all the address attributes. */
172: for (c=1; c < (1<<RTAX_MAX); c<<=1) {
173: size_t len;
174: struct sockaddr_in *sa;
175: sa = addrptr;
176: switch (c & ifht->ifam_addrs) {
177: case 0:
178: continue;
179: case RTA_NETMASK:
180: if_nmsk = sa;
181: break;
182: case RTA_IFA:
183: if_addr = sa;
184: break;
185: case RTA_BRD:
186: if_bcst = sa;
187: break;
188: }
189: addrptr += SA_SIZE((struct sockaddr*)sa);
190: }
191:
192: if (!if_addr || !if_nmsk || !if_bcst) {
193: continue;
194: }
195:
196: if (if_addr->sin_family != AF_INET) {
197: continue;
198: }
199:
200: if ((dstip & if_nmsk->sin_addr.s_addr)
201: != (if_addr->sin_addr.s_addr
202: & if_nmsk->sin_addr.s_addr)) {
203: continue;
204: }
205:
206: match_count++;
207:
1.1.1.2 ! misho 208: if (verbose > 1) {
1.1 misho 209: printf("Specified addr matches "
210: "interface '%s':\n", tmpIfName);
211: printf(" IP addr %s, ",
212: inet_ntoa(if_addr->sin_addr));
213: printf("mask %s, ",
214: inet_ntoa(if_nmsk->sin_addr));
215: printf("bcast %s\n",
216: inet_ntoa(if_bcst->sin_addr));
217: }
218:
219: mask = ntohl(if_nmsk->sin_addr.s_addr);
220: if (mask > best_mask) {
221: memcpy(ifName,
222: tmpIfName,
223: sizeof(ifName));
224: best_mask = mask;
225: best_addr = if_addr->sin_addr;
226: }
227: }
228: }
229:
230: if (match_count == 0 ) {
231: if (verbose) {
1.1.1.2 ! misho 232: snprintf(ebuf, LIBNET_ERRBUF_SIZE,
! 233: "No interface found that matches"
! 234: " specified IP.");
1.1 misho 235: }
236: goto failed;
237: }
238:
239: if (verbose && match_count > 1) {
1.1.1.2 ! misho 240: printf("arping: Using interface '%s' with src IP %s due "
! 241: "to longer mask.\n", ifName, inet_ntoa(best_addr));
1.1 misho 242: }
243: #if 0
244: if (ifce_ip != 0) {
245: *ifce_ip = best_addr.s_addr;
246: }
247: #endif
1.1.1.2 ! misho 248: free(buf_memory);
1.1 misho 249: return ifName;
250:
251: failed:
1.1.1.2 ! misho 252: free(buf_memory);
1.1 misho 253: return NULL;
254: }
255:
256: /* ---- Emacs Variables ----
257: * Local Variables:
258: * c-basic-offset: 8
259: * indent-tabs-mode: nil
260: * End:
261: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>