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>