File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_link_bpf.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:14:23 2012 UTC (12 years, 5 months ago) by misho
Branches: libnet, MAIN
CVS tags: v1_1_2_1, HEAD
libnet

    1: /*
    2:  *  $Id: libnet_link_bpf.c,v 1.1.1.1 2012/02/21 22:14:23 misho 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>