Annotation of embedaddon/libnet/src/libnet_link_bpf.c, revision 1.1.1.4

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: 
1.1.1.4 ! misho      30: #include "common.h"
        !            31: 
1.1       misho      32: #include <sys/param.h>  /* optionally get BSD define */
1.1.1.4 ! misho      33: #if !defined(__OpenBSD__) && !defined(__FreeBSD__)
1.1       misho      34: #include <sys/timeb.h>
1.1.1.4 ! misho      35: #endif
1.1       misho      36: #include <sys/file.h>
                     37: #include <sys/ioctl.h>
                     38: 
                     39: #include <sys/types.h>
                     40: #include <sys/time.h>
                     41: #include <net/bpf.h>
                     42: 
                     43: #include <sys/sysctl.h>
                     44: #include <net/route.h>
                     45: #include <net/if_dl.h>
1.1.1.2   misho      46: #include <net/if_types.h>
1.1       misho      47: #include "../include/gnuc.h"
1.1.1.2   misho      48: 
1.1.1.4 ! misho      49: #include "../include/bpf.h"
1.1       misho      50: 
                     51: #ifdef HAVE_OS_PROTO_H
                     52: #include "../include/os-proto.h"
                     53: #endif
                     54: 
                     55: int
1.1.1.2   misho      56: libnet_bpf_open(char *err_buf)
1.1       misho      57: {
                     58:     int i, fd;
1.1.1.2   misho      59:     char device[] = "/dev/bpf000";
1.1       misho      60: 
                     61:     /*
                     62:      *  Go through all the minors and find one that isn't in use.
                     63:      */
1.1.1.4 ! misho      64:     for (i = 0; i < 1000; i++)
1.1       misho      65:     {
1.1.1.4 ! misho      66:         snprintf(device, sizeof(device), "/dev/bpf%d", i);
1.1       misho      67: 
                     68:         fd = open(device, O_RDWR);
                     69:         if (fd == -1 && errno == EBUSY)
                     70:         {
                     71:             /*
                     72:              *  Device is busy.
                     73:              */
                     74:             continue;
                     75:         }
                     76:         else
                     77:         {
                     78:             /*
                     79:              *  Either we've got a valid file descriptor, or errno is not
                     80:              *  EBUSY meaning we've probably run out of devices.
                     81:              */
                     82:             break;
                     83:         }
                     84:     }
                     85: 
                     86:     if (fd == -1)
                     87:     {
1.1.1.4 ! misho      88:         snprintf(err_buf, LIBNET_ERRBUF_SIZE, "%s(): open(): (%s): %s",
1.1       misho      89:                 __func__, device, strerror(errno));
                     90:     }
                     91:     return (fd);
                     92: }
                     93: 
                     94: 
                     95: int
                     96: libnet_open_link(libnet_t *l)
                     97: {
                     98:     struct ifreq ifr;
                     99:     struct bpf_version bv;
1.1.1.2   misho     100:     uint v;
1.1       misho     101: 
                    102: #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) && !(__APPLE__)
1.1.1.2   misho     103:     uint spoof_eth_src = 1;
1.1       misho     104: #endif
                    105: 
                    106:     if (l == NULL)
                    107:     { 
                    108:         return (-1);
                    109:     } 
                    110: 
                    111:     if (l->device == NULL)
                    112:     {
1.1.1.4 ! misho     113:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): NULL device", 
1.1       misho     114:                 __func__);
                    115:         goto bad;
                    116:     }
                    117: 
1.1.1.2   misho     118:     l->fd = libnet_bpf_open((char*)l->err_buf);
1.1       misho     119:     if (l->fd == -1)
                    120:     {
                    121:         goto bad;
                    122:     }
                    123: 
                    124:     /*
                    125:      *  Get bpf version.
                    126:      */
                    127:     if (ioctl(l->fd, BIOCVERSION, (caddr_t)&bv) < 0)
                    128:     {
1.1.1.4 ! misho     129:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCVERSION: %s",
1.1       misho     130:                 __func__, strerror(errno));
                    131:         goto bad;
                    132:     }
                    133: 
                    134:     if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION)
                    135:     {
                    136:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.4 ! misho     137:                 "%s(): kernel bpf filter out of date", __func__);
1.1       misho     138:         goto bad;
                    139:     }
                    140: 
                    141:     /*
                    142:      *  Attach network interface to bpf device.
                    143:      */
                    144:        strncpy(ifr.ifr_name, l->device, sizeof(ifr.ifr_name) - 1);
                    145:     ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
                    146: 
                    147:     if (ioctl(l->fd, BIOCSETIF, (caddr_t)&ifr) == -1)
                    148:     {
1.1.1.4 ! misho     149:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCSETIF: (%s): %s",
1.1       misho     150:                 __func__, l->device, strerror(errno));
                    151:         goto bad;
                    152:     }
                    153: 
                    154:     /*
                    155:      *  Get the data link-layer type.
                    156:      */
                    157:     if (ioctl(l->fd, BIOCGDLT, (caddr_t)&v) == -1)
                    158:     {
1.1.1.4 ! misho     159:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCGDLT: %s",
1.1       misho     160:                 __func__, strerror(errno));
                    161:         goto bad;
                    162:     }
                    163: 
                    164:     /*
                    165:      *  NetBSD and FreeBSD BPF have an ioctl for enabling/disabling
                    166:      *  automatic filling of the link level source address.
                    167:      */
                    168: #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) && !(__APPLE__)
                    169:     if (ioctl(l->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1)
                    170:     {
1.1.1.4 ! misho     171:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCSHDRCMPLT: %s",
1.1       misho     172:                 __func__, strerror(errno));
                    173:         goto bad;
                    174:     }
                    175: #endif
                    176: 
                    177:     /*
                    178:      *  Assign link type and offset.
                    179:      */
                    180:     switch (v)
                    181:     {
                    182:         case DLT_SLIP:
                    183:             l->link_offset = 0x10;
                    184:             break;
                    185:         case DLT_RAW:
                    186:             l->link_offset = 0x0;
                    187:             break;
                    188:         case DLT_PPP:
                    189:             l->link_offset = 0x04;
                    190:             break;
                    191:         case DLT_EN10MB:
                    192:         default:
                    193:             l->link_offset = 0xe;     /* default to ethernet */
                    194:             break;
                    195:     }
                    196: #if _BSDI_VERSION - 0 >= 199510
                    197:     switch (v)
                    198:     {
                    199:         case DLT_SLIP:
                    200:             v = DLT_SLIP_BSDOS;
                    201:             l->link_offset = 0x10;
                    202:             break;
                    203:         case DLT_PPP:
                    204:             v = DLT_PPP_BSDOS;
                    205:             l->link_offset = 0x04;
                    206:             break;
                    207:     }
                    208: #endif
                    209:     l->link_type = v;
                    210: 
                    211:     return (1);
                    212: 
                    213: bad:
                    214:     if (l->fd > 0)
                    215:     {
                    216:         close(l->fd);      /* this can fail ok */
                    217:     }
                    218:     return (-1);
                    219: }
                    220: 
                    221: 
                    222: int
                    223: libnet_close_link(libnet_t *l)
                    224: {
                    225:     if (close(l->fd) == 0)
                    226:     {
                    227:         return (1);
                    228:     }
                    229:     else
                    230:     {
                    231:         return (-1);
                    232:     }
                    233: }
                    234: 
                    235: 
                    236: int
1.1.1.2   misho     237: libnet_write_link(libnet_t *l, const uint8_t *packet, uint32_t size)
1.1       misho     238: {
                    239:     int c;
                    240: 
                    241:     if (l == NULL)
                    242:     { 
                    243:         return (-1);
                    244:     } 
                    245: 
                    246:     c = write(l->fd, packet, size);
                    247:     if (c != size)
                    248:     {
                    249:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.4 ! misho     250:                 "%s(): %d bytes written (%s)", __func__, c, strerror(errno));
1.1       misho     251:     }
                    252:     return (c);
                    253: }
                    254: 
                    255: 
                    256: struct libnet_ether_addr *
                    257: libnet_get_hwaddr(libnet_t *l)
                    258: {
                    259:     int mib[6];
                    260:     size_t len;
                    261:     int8_t *buf, *next, *end;
                    262:     struct if_msghdr *ifm;
                    263:     struct sockaddr_dl *sdl;
                    264: 
                    265:     mib[0] = CTL_NET;
                    266:     mib[1] = AF_ROUTE;
                    267:     mib[2] = 0;
                    268:     mib[3] = AF_LINK;
                    269:     mib[4] = NET_RT_IFLIST;
                    270:     mib[5] = 0;
                    271: 
                    272:     if (l == NULL)
                    273:     { 
                    274:         return (NULL);
                    275:     } 
                    276: 
                    277:     if (l->device == NULL)
                    278:     {           
                    279:         if (libnet_select_device(l) == -1)
                    280:         {
                    281:             /* err msg set in libnet_select_device */ 
                    282:             return (NULL);
                    283:         }
                    284:     }
                    285: 
                    286:     if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
                    287:     {
1.1.1.4 ! misho     288:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): sysctl(): %s",
1.1       misho     289:                 __func__, strerror(errno));
                    290:         return (NULL);
                    291:     }
                    292: 
                    293:     buf = (int8_t *)malloc(len);
                    294:     if (buf == NULL)
                    295:     {
1.1.1.4 ! misho     296:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s",
1.1       misho     297:                 __func__, strerror(errno));
                    298:         return (NULL);
                    299:     }
                    300:     if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
                    301:     {
1.1.1.4 ! misho     302:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): sysctl(): %s",
1.1       misho     303:                 __func__, strerror(errno));
                    304:         free(buf);
                    305:         return (NULL);
                    306:     }
                    307:     end = buf + len;
                    308: 
                    309:     for (next = buf ; next < end ; next += ifm->ifm_msglen)
                    310:     {
                    311:         ifm = (struct if_msghdr *)next;
1.1.1.4 ! misho     312: 
1.1.1.2   misho     313:         if (ifm->ifm_version != RTM_VERSION)
                    314:             continue;
1.1.1.4 ! misho     315: 
1.1       misho     316:         if (ifm->ifm_type == RTM_IFINFO)
                    317:         {
                    318:             sdl = (struct sockaddr_dl *)(ifm + 1);
1.1.1.3   misho     319:             if (sdl->sdl_type != IFT_ETHER
1.1.1.4 ! misho     320: #ifdef IFT_FASTETHER
1.1.1.3   misho     321:                 && sdl->sdl_type != IFT_FASTETHER
1.1.1.4 ! misho     322: #endif
        !           323: #ifdef IFT_FASTETHERFX
1.1.1.3   misho     324:                 && sdl->sdl_type != IFT_FASTETHERFX
1.1.1.4 ! misho     325: #endif
        !           326: #ifdef IFT_GIGABITETHERNET
1.1.1.3   misho     327:                 && sdl->sdl_type != IFT_GIGABITETHERNET
1.1.1.4 ! misho     328: #endif
        !           329: 
1.1.1.3   misho     330:                 && sdl->sdl_type != IFT_L2VLAN)
1.1.1.2   misho     331:                 continue;
1.1.1.4 ! misho     332:             if (sdl->sdl_nlen == strlen(l->device)
        !           333:                 && strncmp(&sdl->sdl_data[0], l->device, sdl->sdl_nlen) == 0)
1.1       misho     334:             {
1.1.1.4 ! misho     335:                 memcpy(l->link_addr.ether_addr_octet, LLADDR(sdl), ETHER_ADDR_LEN);
1.1       misho     336:                 break;
                    337:             }
                    338:         }
                    339:     }
                    340:     free(buf);
1.1.1.4 ! misho     341:     if (next == end)
        !           342:     {
1.1.1.3   misho     343:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
                    344:                  "%s(): interface %s of known type not found.",
                    345:                  __func__, l->device);
                    346:         return NULL;
                    347:     }
1.1       misho     348: 
1.1.1.4 ! misho     349:     return (&l->link_addr);
        !           350: }
1.1       misho     351: 
1.1.1.4 ! misho     352: /**
        !           353:  * Local Variables:
        !           354:  *  indent-tabs-mode: nil
        !           355:  *  c-file-style: "stroustrup"
        !           356:  * End:
        !           357:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>