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