Annotation of embedaddon/arping/src/findif_sysctl.c, revision 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>