Annotation of embedaddon/libnet/src/libnet_link_bpf.c, revision 1.1
1.1 ! misho 1: /*
! 2: * $Id: libnet_link_bpf.c,v 1.6 2004/01/28 19:45:00 mike Exp $
! 3: *
! 4: * libnet
! 5: * libnet_link_bpf.c - low-level bpf routines
! 6: *
! 7: * Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
! 8: * All rights reserved.
! 9: *
! 10: * Copyright (c) 1993, 1994, 1995, 1996, 1998
! 11: * The Regents of the University of California. All rights reserved.
! 12: *
! 13: * Redistribution and use in source and binary forms, with or without
! 14: * modification, are permitted provided that: (1) source code distributions
! 15: * retain the above copyright notice and this paragraph in its entirety, (2)
! 16: * distributions including binary code include the above copyright notice and
! 17: * this paragraph in its entirety in the documentation or other materials
! 18: * provided with the distribution, and (3) all advertising materials mentioning
! 19: * features or use of this software display the following acknowledgement:
! 20: * ``This product includes software developed by the University of California,
! 21: * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
! 22: * the University nor the names of its contributors may be used to endorse
! 23: * or promote products derived from this software without specific prior
! 24: * written permission.
! 25: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
! 26: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
! 27: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
! 28: */
! 29:
! 30: #include <sys/param.h> /* optionally get BSD define */
! 31: #include <sys/timeb.h>
! 32: #include <sys/file.h>
! 33: #include <sys/ioctl.h>
! 34:
! 35: #include <sys/types.h>
! 36: #include <sys/time.h>
! 37: #include <net/bpf.h>
! 38:
! 39: #if (HAVE_CONFIG_H)
! 40: #include "../include/config.h"
! 41: #endif
! 42: #include "../include/libnet.h"
! 43: #include <sys/sysctl.h>
! 44: #include <net/route.h>
! 45: #include <net/if_dl.h>
! 46: #include "../include/gnuc.h"
! 47: #include "../include/bpf.h"
! 48:
! 49: #ifdef HAVE_OS_PROTO_H
! 50: #include "../include/os-proto.h"
! 51: #endif
! 52:
! 53: int
! 54: libnet_bpf_open(int8_t *err_buf)
! 55: {
! 56: int i, fd;
! 57: int8_t device[sizeof "/dev/bpf000"];
! 58:
! 59: /*
! 60: * Go through all the minors and find one that isn't in use.
! 61: */
! 62: for (i = 0;;i++)
! 63: {
! 64: sprintf(device, "/dev/bpf%d", i);
! 65:
! 66: fd = open(device, O_RDWR);
! 67: if (fd == -1 && errno == EBUSY)
! 68: {
! 69: /*
! 70: * Device is busy.
! 71: */
! 72: continue;
! 73: }
! 74: else
! 75: {
! 76: /*
! 77: * Either we've got a valid file descriptor, or errno is not
! 78: * EBUSY meaning we've probably run out of devices.
! 79: */
! 80: break;
! 81: }
! 82: }
! 83:
! 84: if (fd == -1)
! 85: {
! 86: snprintf(err_buf, LIBNET_ERRBUF_SIZE, "%s(): open(): (%s): %s\n",
! 87: __func__, device, strerror(errno));
! 88: }
! 89: return (fd);
! 90: }
! 91:
! 92:
! 93: int
! 94: libnet_open_link(libnet_t *l)
! 95: {
! 96: struct ifreq ifr;
! 97: struct bpf_version bv;
! 98: u_int v;
! 99:
! 100: #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) && !(__APPLE__)
! 101: u_int spoof_eth_src = 1;
! 102: #endif
! 103:
! 104: if (l == NULL)
! 105: {
! 106: return (-1);
! 107: }
! 108:
! 109: if (l->device == NULL)
! 110: {
! 111: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): NULL device\n",
! 112: __func__);
! 113: goto bad;
! 114: }
! 115:
! 116: l->fd = libnet_bpf_open(l->err_buf);
! 117: if (l->fd == -1)
! 118: {
! 119: goto bad;
! 120: }
! 121:
! 122: /*
! 123: * Get bpf version.
! 124: */
! 125: if (ioctl(l->fd, BIOCVERSION, (caddr_t)&bv) < 0)
! 126: {
! 127: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCVERSION: %s\n",
! 128: __func__, strerror(errno));
! 129: goto bad;
! 130: }
! 131:
! 132: if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION)
! 133: {
! 134: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 135: "%s(): kernel bpf filter out of date\n", __func__);
! 136: goto bad;
! 137: }
! 138:
! 139: /*
! 140: * Attach network interface to bpf device.
! 141: */
! 142: strncpy(ifr.ifr_name, l->device, sizeof(ifr.ifr_name) - 1);
! 143: ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
! 144:
! 145: if (ioctl(l->fd, BIOCSETIF, (caddr_t)&ifr) == -1)
! 146: {
! 147: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCSETIF: (%s): %s\n",
! 148: __func__, l->device, strerror(errno));
! 149: goto bad;
! 150: }
! 151:
! 152: /*
! 153: * Get the data link-layer type.
! 154: */
! 155: if (ioctl(l->fd, BIOCGDLT, (caddr_t)&v) == -1)
! 156: {
! 157: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCGDLT: %s\n",
! 158: __func__, strerror(errno));
! 159: goto bad;
! 160: }
! 161:
! 162: /*
! 163: * NetBSD and FreeBSD BPF have an ioctl for enabling/disabling
! 164: * automatic filling of the link level source address.
! 165: */
! 166: #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) && !(__APPLE__)
! 167: if (ioctl(l->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1)
! 168: {
! 169: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCSHDRCMPLT: %s\n",
! 170: __func__, strerror(errno));
! 171: goto bad;
! 172: }
! 173: #endif
! 174:
! 175: /*
! 176: * Assign link type and offset.
! 177: */
! 178: switch (v)
! 179: {
! 180: case DLT_SLIP:
! 181: l->link_offset = 0x10;
! 182: break;
! 183: case DLT_RAW:
! 184: l->link_offset = 0x0;
! 185: break;
! 186: case DLT_PPP:
! 187: l->link_offset = 0x04;
! 188: break;
! 189: case DLT_EN10MB:
! 190: default:
! 191: l->link_offset = 0xe; /* default to ethernet */
! 192: break;
! 193: }
! 194: #if _BSDI_VERSION - 0 >= 199510
! 195: switch (v)
! 196: {
! 197: case DLT_SLIP:
! 198: v = DLT_SLIP_BSDOS;
! 199: l->link_offset = 0x10;
! 200: break;
! 201: case DLT_PPP:
! 202: v = DLT_PPP_BSDOS;
! 203: l->link_offset = 0x04;
! 204: break;
! 205: }
! 206: #endif
! 207: l->link_type = v;
! 208:
! 209: return (1);
! 210:
! 211: bad:
! 212: if (l->fd > 0)
! 213: {
! 214: close(l->fd); /* this can fail ok */
! 215: }
! 216: return (-1);
! 217: }
! 218:
! 219:
! 220: int
! 221: libnet_close_link(libnet_t *l)
! 222: {
! 223: if (close(l->fd) == 0)
! 224: {
! 225: return (1);
! 226: }
! 227: else
! 228: {
! 229: return (-1);
! 230: }
! 231: }
! 232:
! 233:
! 234: int
! 235: libnet_write_link(libnet_t *l, u_int8_t *packet, u_int32_t size)
! 236: {
! 237: int c;
! 238:
! 239: if (l == NULL)
! 240: {
! 241: return (-1);
! 242: }
! 243:
! 244: c = write(l->fd, packet, size);
! 245: if (c != size)
! 246: {
! 247: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 248: "%s(): %d bytes written (%s)\n", __func__, c, strerror(errno));
! 249: }
! 250: return (c);
! 251: }
! 252:
! 253:
! 254: struct libnet_ether_addr *
! 255: libnet_get_hwaddr(libnet_t *l)
! 256: {
! 257: int mib[6];
! 258: size_t len;
! 259: int8_t *buf, *next, *end;
! 260: struct if_msghdr *ifm;
! 261: struct sockaddr_dl *sdl;
! 262: struct libnet_ether_addr *ea = NULL;
! 263:
! 264: mib[0] = CTL_NET;
! 265: mib[1] = AF_ROUTE;
! 266: mib[2] = 0;
! 267: mib[3] = AF_LINK;
! 268: mib[4] = NET_RT_IFLIST;
! 269: mib[5] = 0;
! 270:
! 271: if (l == NULL)
! 272: {
! 273: return (NULL);
! 274: }
! 275:
! 276: if (l->device == NULL)
! 277: {
! 278: if (libnet_select_device(l) == -1)
! 279: {
! 280: /* err msg set in libnet_select_device */
! 281: return (NULL);
! 282: }
! 283: }
! 284:
! 285: if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
! 286: {
! 287: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): sysctl(): %s\n",
! 288: __func__, strerror(errno));
! 289: return (NULL);
! 290: }
! 291:
! 292: buf = (int8_t *)malloc(len);
! 293: if (buf == NULL)
! 294: {
! 295: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s\n",
! 296: __func__, strerror(errno));
! 297: return (NULL);
! 298: }
! 299: if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
! 300: {
! 301: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): sysctl(): %s\n",
! 302: __func__, strerror(errno));
! 303: free(buf);
! 304: return (NULL);
! 305: }
! 306: end = buf + len;
! 307:
! 308: for (next = buf ; next < end ; next += ifm->ifm_msglen)
! 309: {
! 310: ifm = (struct if_msghdr *)next;
! 311: if (ifm->ifm_type == RTM_IFINFO)
! 312: {
! 313: sdl = (struct sockaddr_dl *)(ifm + 1);
! 314: if (strncmp(&sdl->sdl_data[0], l->device, sdl->sdl_nlen) == 0)
! 315: {
! 316: if (!(ea = malloc(sizeof(struct libnet_ether_addr))))
! 317: {
! 318: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 319: "%s(): malloc(): %s", __func__, strerror(errno));
! 320: free(buf);
! 321: return (NULL);
! 322: }
! 323: memcpy(ea->ether_addr_octet, LLADDR(sdl), ETHER_ADDR_LEN);
! 324: break;
! 325: }
! 326: }
! 327: }
! 328: free(buf);
! 329: return (ea);
! 330: }
! 331:
! 332:
! 333: /* EOF */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>