Annotation of embedaddon/libnet/src/libnet_link_bpf.c, revision 1.1.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>