Annotation of tme/host/bsd/bsd-bpf.c, revision 1.1.1.3

1.1.1.3 ! root        1: /* $Id: bsd-bpf.c,v 1.6 2004/05/17 11:57:01 fredette Exp $ */
1.1       root        2: 
                      3: /* host/bsd/bsd-bpf.c - BSD Berkeley Packet Filter Ethernet support: */
                      4: 
                      5: /*
                      6:  * Copyright (c) 2001, 2003 Matt Fredette
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *      This product includes software developed by Matt Fredette.
                     20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     33:  * POSSIBILITY OF SUCH DAMAGE.
                     34:  */
                     35: 
                     36: #include <tme/common.h>
1.1.1.3 ! root       37: _TME_RCSID("$Id: bsd-bpf.c,v 1.6 2004/05/17 11:57:01 fredette Exp $");
1.1       root       38: 
                     39: /* includes: */
                     40: #include "bsd-impl.h"
                     41: #include <tme/generic/ethernet.h>
1.1.1.3 ! root       42: #include <tme/misc.h>
1.1       root       43: #include <stdio.h>
                     44: #include <string.h>
                     45: #include <errno.h>
                     46: #include <fcntl.h>
                     47: #include <netdb.h>
                     48: #include <sys/param.h>
                     49: #include <sys/socket.h>
                     50: #include <sys/stat.h>
                     51: #include <net/if.h>
                     52: #include <netinet/in_systm.h>
                     53: #include <netinet/in.h>
                     54: #if defined(HAVE_SYS_SOCKIO_H)
                     55: #include <sys/sockio.h>
                     56: #elif defined(HAVE_SYS_SOCKETIO_H)
                     57: #include <sys/socketio.h> 
                     58: #endif /* HAVE_SYS_SOCKETIO_H */
                     59: #include <sys/ioctl.h>
                     60: #ifdef HAVE_IOCTLS_H
                     61: #include <ioctls.h>
                     62: #endif /* HAVE_IOCTLS_H */
                     63: #ifdef HAVE_NET_IF_ETHER_H
                     64: #include <net/if_ether.h>
                     65: #endif /* HAVE_NET_IF_ETHER_H */
                     66: #ifdef HAVE_NET_ETHERNET_H
                     67: #include <net/ethernet.h>
                     68: #endif /* HAVE_NET_ETHERNET_H */
                     69: #include <netinet/ip.h>
                     70: #ifdef HAVE_NET_IF_DL_H
                     71: #include <net/if_dl.h>
                     72: #endif /* HAVE_NET_IF_DL_H */
                     73: #include <arpa/inet.h>
                     74: #include <net/bpf.h>
                     75: 
                     76: /* macros: */
                     77: 
                     78: /* the callout flags: */
                     79: #define TME_BSD_BPF_CALLOUT_CHECK      (0)
                     80: #define TME_BSD_BPF_CALLOUT_RUNNING    TME_BIT(0)
                     81: #define TME_BSD_BPF_CALLOUTS_MASK      (-2)
                     82: #define  TME_BSD_BPF_CALLOUT_CTRL      TME_BIT(1)
                     83: #define  TME_BSD_BPF_CALLOUT_READ      TME_BIT(2)
                     84: 
                     85: /* structures: */
                     86: 
                     87: /* our internal data structure: */
                     88: struct tme_bsd_bpf {
                     89: 
                     90:   /* backpointer to our element: */
                     91:   struct tme_element *tme_bsd_bpf_element;
                     92: 
                     93:   /* our mutex: */
                     94:   tme_mutex_t tme_bsd_bpf_mutex;
                     95: 
1.1.1.3 ! root       96:   /* our reader condition: */
1.1       root       97:   tme_cond_t tme_bsd_bpf_cond_reader;
                     98: 
                     99:   /* the callout flags: */
                    100:   unsigned int tme_bsd_bpf_callout_flags;
                    101: 
                    102:   /* our Ethernet connection: */
                    103:   struct tme_ethernet_connection *tme_bsd_bpf_eth_connection;
                    104: 
                    105:   /* the BPF file descriptor: */
                    106:   int tme_bsd_bpf_fd;
                    107: 
                    108:   /* the size of the packet buffer for the interface: */
                    109:   size_t tme_bsd_bpf_buffer_size;
                    110: 
                    111:   /* the packet buffer for the interface: */
                    112:   tme_uint8_t *tme_bsd_bpf_buffer;
                    113: 
                    114:   /* the next offset within the packet buffer, and the end of the data
                    115:      in the packet buffer: */
                    116:   size_t tme_bsd_bpf_buffer_offset;
                    117:   size_t tme_bsd_bpf_buffer_end;
1.1.1.3 ! root      118: 
        !           119:   /* when nonzero, the packet delay time, in microseconds: */
        !           120:   unsigned long tme_bsd_bpf_delay_time;
        !           121: 
        !           122:   /* all packets received on or before this time can be released: */
        !           123:   struct timeval tme_bsd_bpf_delay_release;
        !           124: 
        !           125:   /* when nonzero, the packet delay sleep time, in microseconds: */
        !           126:   unsigned long tme_bsd_bpf_delay_sleep;
        !           127: 
        !           128:   /* when nonzero, the packet delay is sleeping: */
        !           129:   int tme_bsd_bpf_delay_sleeping;
1.1       root      130: };
                    131: 
                    132: /* the accept and reject packet insns: */
                    133: static const struct bpf_insn _tme_bsd_bpf_insn_accept = BPF_STMT(BPF_RET + BPF_K, (u_int) -1);
                    134: static const struct bpf_insn _tme_bsd_bpf_insn_reject = BPF_STMT(BPF_RET + BPF_K, 0);
                    135: 
                    136: /* this creates a BPF filter that accepts Ethernet packets with
                    137:    destination addresses in the configured set.  the broadcast address
                    138:    must be in this set, it isn't accepted automatically: */
                    139: static int
                    140: _tme_bsd_bpf_filter(struct tme_ethernet_config *config, 
                    141:                    const tme_uint8_t *prefix,
                    142:                    unsigned int prefix_len,
                    143:                    struct bpf_insn *bpf_filter,
                    144:                    int bpf_filter_size,
                    145:                    int *_first_pc)
                    146: {
                    147:   unsigned int addr_i;
                    148:   tme_uint8_t byte;
                    149:   tme_uint8_t byte_bitmap[(1 << (8 * sizeof(byte))) >> 3];
                    150:   int match_pc, miss_pc, this_pc;
                    151: 
                    152:   /* clear the byte bitmap: */
                    153:   memset(byte_bitmap, 0, sizeof(byte_bitmap));
                    154: 
                    155:   /* the last instruction jumps to the reject insn when it fails: */
                    156:   miss_pc = bpf_filter_size - 1;
                    157: 
                    158:   /* loop over all of the addresses: */
                    159:   for (addr_i = 0;
                    160:        addr_i < config->tme_ethernet_config_addr_count;
                    161:        addr_i++) {
                    162: 
                    163:     /* skip this address if it doesn't match the prefix: */
                    164:     if (prefix_len > 0
                    165:        && memcmp(config->tme_ethernet_config_addrs[addr_i],
                    166:                  prefix,
                    167:                  prefix_len)) {
                    168:       continue;
                    169:     }
                    170: 
                    171:     /* get the next byte, and skip this address if this byte has
                    172:        already been done: */
                    173:     byte = config->tme_ethernet_config_addrs[addr_i][prefix_len];
                    174:     if (byte_bitmap[byte >> 3] & TME_BIT(byte & 7)) {
                    175:       continue;
                    176:     }
                    177:     byte_bitmap[byte >> 3] |= TME_BIT(byte & 7);
                    178: 
                    179:     /* get the PC of the instruction to branch to if this byte
                    180:        matches.  if this is the last byte of the address, the branch
                    181:        target is the accept insn, otherwise recurse and get the first
                    182:        insn of the rest of the matcher: */
                    183:     match_pc = ((prefix_len == (TME_ETHERNET_ADDR_SIZE - 1))
                    184:                ? bpf_filter_size - 2
                    185:                : _tme_bsd_bpf_filter(config,
                    186:                                      config->tme_ethernet_config_addrs[addr_i],
                    187:                                      prefix_len + 1,
                    188:                                      bpf_filter,
                    189:                                      bpf_filter_size,
                    190:                                      _first_pc));
                    191: 
                    192:     /* add this testing instruction: */
                    193:     this_pc = --(*_first_pc);
                    194:     assert(this_pc >= 0);
                    195:     bpf_filter[this_pc].code = BPF_JMP + BPF_JEQ + BPF_K;
                    196:     bpf_filter[this_pc].jt = match_pc - (this_pc + 1);
                    197:     bpf_filter[this_pc].jf = miss_pc - (this_pc + 1);
                    198:     bpf_filter[this_pc].k = byte;
                    199: 
                    200:     /* update the miss pc: */
                    201:     miss_pc = this_pc;
                    202:   }
                    203: 
                    204:   /* add this load instruction: */
                    205:   this_pc = --(*_first_pc);
                    206:   assert(this_pc >= 0);
                    207:   bpf_filter[this_pc].code = BPF_LD + BPF_B + BPF_ABS;
                    208:   bpf_filter[this_pc].k = prefix_len;
                    209: 
                    210:   /* return our pc: */
                    211:   return (this_pc);
                    212: }
                    213: 
                    214: /* this dumps a BPF filter.  not all insns are supported, just
                    215:    those used by our address matching filters: */
                    216: void
                    217: _tme_bsd_bpf_dump_filter(const struct bpf_program *program)
                    218: {
1.1.1.2   root      219:   unsigned int pc;
1.1       root      220:   FILE *fp;
                    221:   const struct bpf_insn *insn;
                    222:   char ldsize;
                    223:   const char *opc;
                    224: 
                    225:   fp = stderr;
                    226:   for (pc = 0, insn = program->bf_insns;
1.1.1.2   root      227:        pc < (unsigned int) program->bf_len;
1.1       root      228:        pc++, insn++) {
                    229:     
                    230:     /* the PC: */
                    231:     fprintf(fp, "%d:\t", pc);
                    232: 
                    233:     /* dispatch on the instruction class: */
                    234:     switch (BPF_CLASS(insn->code)) {
                    235: 
                    236:     case BPF_LD:
                    237: 
                    238:       switch (BPF_SIZE(insn->code)) {
                    239:       case BPF_B: ldsize = 'b'; break;
                    240:       case BPF_H: ldsize = 'w'; break;
                    241:       case BPF_W: ldsize = 'l'; break;
                    242:       default: ldsize = '?'; break;
                    243:       }
                    244:       fprintf(fp, "ld.%c ", ldsize);
                    245: 
                    246:       switch (BPF_MODE(insn->code)) {
                    247:       case BPF_ABS: fprintf(fp, "0x%x", insn->k); break;
                    248:       default: fprintf(fp, "??");
                    249:       }
                    250: 
                    251:       break;
                    252: 
                    253:     case BPF_JMP:
                    254: 
                    255:       switch (BPF_OP(insn->code)) {
                    256:       case BPF_JEQ: opc = "jeq"; break;
                    257:       default: opc = "??"; break;
                    258:       }
                    259:       fprintf(fp, "%s ", opc);
                    260: 
                    261:       switch (BPF_SRC(insn->code)) {
                    262:       case BPF_K: fprintf(fp, "#0x%x", insn->k); break;
                    263:       case BPF_X: fprintf(fp, "x"); break;
                    264:       default: fprintf(fp, "??"); break;
                    265:       }
                    266: 
                    267:       fprintf(fp, ", %d, %d", pc + 1 + insn->jt, pc + 1 + insn->jf);
                    268:       break;
                    269: 
                    270:     case BPF_RET:
                    271:       switch (BPF_RVAL(insn->code)) {
                    272:       case BPF_A: fprintf(fp, "ret a"); break;
                    273:       case BPF_X: fprintf(fp, "ret x"); break;
                    274:       case BPF_K: fprintf(fp, "ret #0x%x", insn->k); break;
                    275:       default: fprintf(fp, "ret ??"); break;
                    276:       }
                    277:       break;
                    278: 
                    279:     default:
                    280:       fprintf(fp, "??");
                    281:       break;
                    282:     }
                    283: 
                    284:     putc('\n', fp);
                    285:   }
                    286: }
                    287: 
                    288: /* the bpf callout function.  it must be called with the mutex locked: */
                    289: static void
                    290: _tme_bsd_bpf_callout(struct tme_bsd_bpf *bpf, int new_callouts)
                    291: {
                    292:   struct tme_ethernet_connection *conn_eth;
                    293:   int callouts, later_callouts;
                    294:   unsigned int ctrl;
                    295:   int rc;
                    296:   tme_ethernet_fid_t frame_id;
                    297:   struct tme_ethernet_frame_chunk frame_chunk_buffer;
                    298:   tme_uint8_t frame[TME_ETHERNET_FRAME_MAX];
                    299:   
                    300:   /* add in any new callouts: */
                    301:   bpf->tme_bsd_bpf_callout_flags |= new_callouts;
                    302: 
                    303:   /* if this function is already running in another thread, simply
                    304:      return now.  the other thread will do our work: */
                    305:   if (bpf->tme_bsd_bpf_callout_flags & TME_BSD_BPF_CALLOUT_RUNNING) {
                    306:     return;
                    307:   }
                    308: 
                    309:   /* callouts are now running: */
                    310:   bpf->tme_bsd_bpf_callout_flags |= TME_BSD_BPF_CALLOUT_RUNNING;
                    311: 
                    312:   /* assume that we won't need any later callouts: */
                    313:   later_callouts = 0;
                    314: 
                    315:   /* loop while callouts are needed: */
                    316:   for (; (callouts = bpf->tme_bsd_bpf_callout_flags) & TME_BSD_BPF_CALLOUTS_MASK; ) {
                    317: 
                    318:     /* clear the needed callouts: */
                    319:     bpf->tme_bsd_bpf_callout_flags = callouts & ~TME_BSD_BPF_CALLOUTS_MASK;
                    320:     callouts &= TME_BSD_BPF_CALLOUTS_MASK;
                    321: 
                    322:     /* get our Ethernet connection: */
                    323:     conn_eth = bpf->tme_bsd_bpf_eth_connection;
                    324: 
                    325:     /* if we need to call out new control information: */
                    326:     if (callouts & TME_BSD_BPF_CALLOUT_CTRL) {
                    327: 
                    328:       /* form the new ctrl: */
                    329:       ctrl = 0;
                    330:       if (bpf->tme_bsd_bpf_buffer_offset
                    331:          < bpf->tme_bsd_bpf_buffer_end) {
                    332:        ctrl |= TME_ETHERNET_CTRL_OK_READ;
                    333:       }
                    334: 
                    335:       /* unlock the mutex: */
                    336:       tme_mutex_unlock(&bpf->tme_bsd_bpf_mutex);
                    337:       
                    338:       /* do the callout: */
                    339:       rc = (conn_eth != NULL
                    340:            ? ((*conn_eth->tme_ethernet_connection_ctrl)
                    341:               (conn_eth,
                    342:                ctrl))
                    343:            : TME_OK);
                    344:        
                    345:       /* lock the mutex: */
                    346:       tme_mutex_lock(&bpf->tme_bsd_bpf_mutex);
                    347:       
                    348:       /* if the callout was unsuccessful, remember that at some later
                    349:         time this callout should be attempted again: */
                    350:       if (rc != TME_OK) {
                    351:        later_callouts |= TME_BSD_BPF_CALLOUT_CTRL;
                    352:       }
                    353:     }
                    354:       
                    355:     /* if the Ethernet is readable: */
                    356:     if (callouts & TME_BSD_BPF_CALLOUT_READ) {
                    357: 
                    358:       /* unlock the mutex: */
                    359:       tme_mutex_unlock(&bpf->tme_bsd_bpf_mutex);
                    360:       
                    361:       /* make a frame chunk to receive this frame: */
                    362:       frame_chunk_buffer.tme_ethernet_frame_chunk_next = NULL;
                    363:       frame_chunk_buffer.tme_ethernet_frame_chunk_bytes = frame;
                    364:       frame_chunk_buffer.tme_ethernet_frame_chunk_bytes_count
                    365:        = sizeof(frame);
                    366: 
                    367:       /* do the callout: */
                    368:       rc = (conn_eth == NULL
                    369:            ? TME_OK
                    370:            : ((*conn_eth->tme_ethernet_connection_read)
                    371:               (conn_eth,
                    372:                &frame_id,
                    373:                &frame_chunk_buffer,
                    374:                TME_ETHERNET_READ_NEXT)));
                    375:       
                    376:       /* lock the mutex: */
                    377:       tme_mutex_lock(&bpf->tme_bsd_bpf_mutex);
                    378:       
                    379:       /* if the read was successful: */
                    380:       if (rc > 0) {
                    381: 
                    382:        /* do the write: */
                    383:        tme_thread_write(bpf->tme_bsd_bpf_fd, frame, rc);
                    384: 
                    385:        /* mark that we need to loop to callout to read more frames: */
                    386:        bpf->tme_bsd_bpf_callout_flags |= TME_BSD_BPF_CALLOUT_READ;
                    387:       }
                    388: 
                    389:       /* otherwise, the read failed.  convention dictates that we
                    390:         forget that the connection was readable, which we already
                    391:         have done by clearing the CALLOUT_READ flag: */
                    392:     }
                    393: 
                    394:   }
                    395:   
                    396:   /* put in any later callouts, and clear that callouts are running: */
                    397:   bpf->tme_bsd_bpf_callout_flags = later_callouts;
                    398: }
                    399: 
                    400: /* the BPF reader thread: */
                    401: static void
                    402: _tme_bsd_bpf_th_reader(struct tme_bsd_bpf *bpf)
                    403: {
                    404:   ssize_t buffer_end;
1.1.1.3 ! root      405:   unsigned long sleep_usec;
1.1       root      406:   
                    407:   /* lock the mutex: */
                    408:   tme_mutex_lock(&bpf->tme_bsd_bpf_mutex);
                    409: 
                    410:   /* loop forever: */
                    411:   for (;;) {
                    412: 
1.1.1.3 ! root      413:     /* if the delay sleeping flag is set: */
        !           414:     if (bpf->tme_bsd_bpf_delay_sleeping) {
        !           415: 
        !           416:       /* clear the delay sleeping flag: */
        !           417:       bpf->tme_bsd_bpf_delay_sleeping = FALSE;
        !           418:       
        !           419:       /* call out that we can be read again: */
        !           420:       _tme_bsd_bpf_callout(bpf, TME_BSD_BPF_CALLOUT_CTRL);
        !           421:     }
        !           422: 
        !           423:     /* if a delay has been requested: */
        !           424:     sleep_usec = bpf->tme_bsd_bpf_delay_sleep;
        !           425:     if (sleep_usec > 0) {
        !           426: 
        !           427:       /* clear the delay sleep time: */
        !           428:       bpf->tme_bsd_bpf_delay_sleep = 0;
        !           429: 
        !           430:       /* set the delay sleeping flag: */
        !           431:       bpf->tme_bsd_bpf_delay_sleeping = TRUE;
        !           432: 
        !           433:       /* unlock our mutex: */
        !           434:       tme_mutex_unlock(&bpf->tme_bsd_bpf_mutex);
        !           435:       
        !           436:       /* sleep for the delay sleep time: */
        !           437:       tme_thread_sleep_yield(0, sleep_usec);
        !           438:       
        !           439:       /* lock our mutex: */
        !           440:       tme_mutex_lock(&bpf->tme_bsd_bpf_mutex);
        !           441:       
        !           442:       continue;
        !           443:     }
        !           444: 
        !           445:     /* if the buffer is not empty, wait until either it is,
        !           446:        or we're asked to do a delay: */
1.1       root      447:     if (bpf->tme_bsd_bpf_buffer_offset
                    448:        < bpf->tme_bsd_bpf_buffer_end) {
                    449:       tme_cond_wait_yield(&bpf->tme_bsd_bpf_cond_reader,
                    450:                          &bpf->tme_bsd_bpf_mutex);
1.1.1.3 ! root      451:       continue;
1.1       root      452:     }
                    453: 
                    454:     /* unlock the mutex: */
                    455:     tme_mutex_unlock(&bpf->tme_bsd_bpf_mutex);
                    456: 
                    457:     /* read the BPF socket: */
                    458:     tme_log(&bpf->tme_bsd_bpf_element->tme_element_log_handle, 1, TME_OK,
                    459:            (&bpf->tme_bsd_bpf_element->tme_element_log_handle,
                    460:             _("calling read")));
                    461:     buffer_end = 
                    462:       tme_thread_read_yield(bpf->tme_bsd_bpf_fd,
                    463:                            bpf->tme_bsd_bpf_buffer,
                    464:                            bpf->tme_bsd_bpf_buffer_size);
                    465: 
                    466:     /* lock the mutex: */
                    467:     tme_mutex_lock(&bpf->tme_bsd_bpf_mutex);
                    468: 
                    469:     /* if the read failed: */
                    470:     if (buffer_end <= 0) {
                    471:       tme_log(&bpf->tme_bsd_bpf_element->tme_element_log_handle, 1, errno,
                    472:              (&bpf->tme_bsd_bpf_element->tme_element_log_handle,
                    473:               _("failed to read packets")));
                    474:       continue;
                    475:     }
                    476: 
                    477:     /* the read succeeded: */
                    478:     tme_log(&bpf->tme_bsd_bpf_element->tme_element_log_handle, 1, TME_OK,
                    479:            (&bpf->tme_bsd_bpf_element->tme_element_log_handle,
                    480:             _("read %ld bytes of packets"), (long) buffer_end));
                    481:     bpf->tme_bsd_bpf_buffer_offset = 0;
                    482:     bpf->tme_bsd_bpf_buffer_end = buffer_end;
                    483: 
                    484:     /* call out that we can be read again: */
                    485:     _tme_bsd_bpf_callout(bpf, TME_BSD_BPF_CALLOUT_CTRL);
                    486:   }
                    487:   /* NOTREACHED */
                    488: }
                    489: 
                    490: /* this is called when the ethernet configuration changes: */
                    491: static int
                    492: _tme_bsd_bpf_config(struct tme_ethernet_connection *conn_eth, 
                    493:                    struct tme_ethernet_config *config)
                    494: {
                    495:   struct tme_bsd_bpf *bpf;
                    496:   struct bpf_insn *bpf_filter;
                    497:   struct bpf_program program;
                    498:   int bpf_filter_size, first_pc;
                    499:   int rc;
                    500: 
                    501:   /* recover our data structures: */
                    502:   bpf = conn_eth->tme_ethernet_connection.tme_connection_element->tme_element_private;
                    503: 
                    504:   /* assume we will succeed: */
                    505:   rc = TME_OK;
                    506: 
                    507:   /* lock the mutex: */
                    508:   tme_mutex_lock(&bpf->tme_bsd_bpf_mutex);
                    509: 
                    510:   /* allocate space for the worst-case filter: one insn for the packet
                    511:      accept, one insn for the packet reject, and TME_ETHERNET_ADDR_SIZE
                    512:      * 2 insns for each address - one insn to load an address byte and
                    513:      one insn to test it and branch: */
                    514:   bpf_filter_size = (1
                    515:                     + 1
                    516:                     + ((1 + 1)
                    517:                        * TME_ETHERNET_ADDR_SIZE
                    518:                        * config->tme_ethernet_config_addr_count));
                    519:   bpf_filter = tme_new(struct bpf_insn, bpf_filter_size);
                    520:   first_pc = bpf_filter_size;
                    521: 
                    522:   /* if this Ethernet is promiscuous, we will accept all packets: */
                    523:   if (config->tme_ethernet_config_flags & TME_ETHERNET_CONFIG_PROMISC) {
                    524:     bpf_filter[--first_pc] = _tme_bsd_bpf_insn_accept;
                    525:   }
                    526: 
                    527:   /* if this Ethernet does have a set of addresses, we will accept all
                    528:      packets for one of those addresses: */
                    529:   else if (config->tme_ethernet_config_addr_count > 0) {
                    530: 
                    531:     /* the last insn in the filter is always the packet reject,
                    532:        and the next-to-last insn in the filter is always the
                    533:        packet accept.  _tme_bsd_bpf_filter depends on this: */
                    534:     bpf_filter[--first_pc] = _tme_bsd_bpf_insn_reject;
                    535:     bpf_filter[--first_pc] = _tme_bsd_bpf_insn_accept;
                    536: 
                    537:     /* make the address filter: */
                    538:     _tme_bsd_bpf_filter(config, 
                    539:                        NULL,
                    540:                        0,
                    541:                        bpf_filter,
                    542:                        bpf_filter_size,
                    543:                        &first_pc);
                    544:   }
                    545: 
                    546:   /* otherwise this filter doesn't need to accept any packets: */
                    547:   else {
                    548:     bpf_filter[--first_pc] = _tme_bsd_bpf_insn_reject;
                    549:   }
                    550: 
                    551:   /* set the filter on the BPF device: */
                    552:   program.bf_len = bpf_filter_size - first_pc;
                    553:   program.bf_insns = bpf_filter + first_pc;
                    554:   if (ioctl(bpf->tme_bsd_bpf_fd, BIOCSETF, &program) < 0) {
                    555:     tme_log(&bpf->tme_bsd_bpf_element->tme_element_log_handle, 1, errno,
                    556:            (&bpf->tme_bsd_bpf_element->tme_element_log_handle,
                    557:             _("failed to set the filter")));
                    558:     rc = errno;
                    559:   }
                    560: 
                    561:   /* free the filter: */
                    562:   tme_free(bpf_filter);
                    563: 
                    564:   /* unlock the mutex: */
                    565:   tme_mutex_unlock(&bpf->tme_bsd_bpf_mutex);
                    566: 
                    567:   /* done: */
                    568:   return (rc);
                    569: }
                    570: 
                    571: /* this is called when control lines change: */
                    572: static int
                    573: _tme_bsd_bpf_ctrl(struct tme_ethernet_connection *conn_eth, 
                    574:                  unsigned int ctrl)
                    575: {
                    576:   struct tme_bsd_bpf *bpf;
                    577:   int new_callouts;
                    578: 
                    579:   /* recover our data structures: */
                    580:   bpf = conn_eth->tme_ethernet_connection.tme_connection_element->tme_element_private;
                    581: 
                    582:   /* assume that we won't need any new callouts: */
                    583:   new_callouts = 0;
                    584: 
                    585:   /* lock the mutex: */
                    586:   tme_mutex_lock(&bpf->tme_bsd_bpf_mutex);
                    587: 
                    588:   /* if this connection is readable, call out a read: */
                    589:   if (ctrl & TME_ETHERNET_CTRL_OK_READ) {
                    590:     new_callouts |= TME_BSD_BPF_CALLOUT_READ;
                    591:   }
                    592: 
                    593:   /* make any new callouts: */
                    594:   _tme_bsd_bpf_callout(bpf, new_callouts);
                    595: 
                    596:   /* unlock the mutex: */
                    597:   tme_mutex_unlock(&bpf->tme_bsd_bpf_mutex);
                    598: 
                    599:   return (TME_OK);
                    600: }
                    601: 
                    602: /* this is called to read a frame: */
                    603: static int
                    604: _tme_bsd_bpf_read(struct tme_ethernet_connection *conn_eth, 
                    605:                  tme_ethernet_fid_t *_frame_id,
                    606:                  struct tme_ethernet_frame_chunk *frame_chunks,
                    607:                  unsigned int flags)
                    608: {
                    609:   struct tme_bsd_bpf *bpf;
                    610:   struct bpf_hdr the_bpf_header;
                    611:   struct tme_ethernet_frame_chunk frame_chunk_buffer;
                    612:   unsigned int count;
                    613:   int rc;
                    614: 
                    615:   /* recover our data structure: */
                    616:   bpf = conn_eth->tme_ethernet_connection.tme_connection_element->tme_element_private;
                    617: 
                    618:   /* lock our mutex: */
                    619:   tme_mutex_lock(&bpf->tme_bsd_bpf_mutex);
                    620: 
                    621:   /* assume that we won't be able to return a packet: */
                    622:   rc = -ENOENT;
                    623: 
                    624:   /* loop until we have a good captured packet or until we 
                    625:      exhaust the buffer: */
                    626:   for (;;) {
                    627:     
                    628:     /* if there's not enough for a BPF header, flush the buffer: */
                    629:     if ((bpf->tme_bsd_bpf_buffer_offset
                    630:         + sizeof(the_bpf_header))
                    631:        > bpf->tme_bsd_bpf_buffer_end) {
                    632:       tme_log(&bpf->tme_bsd_bpf_element->tme_element_log_handle, 1, TME_OK,
                    633:              (&bpf->tme_bsd_bpf_element->tme_element_log_handle,
                    634:               _("flushed garbage BPF header bytes")));
                    635:       bpf->tme_bsd_bpf_buffer_end = 0;
                    636:       break;
                    637:     }
                    638: 
                    639:     /* get the BPF header and check it: */
                    640:     memcpy(&the_bpf_header,
                    641:           bpf->tme_bsd_bpf_buffer
                    642:           + bpf->tme_bsd_bpf_buffer_offset,
                    643:           sizeof(the_bpf_header));
                    644:     bpf->tme_bsd_bpf_buffer_offset += the_bpf_header.bh_hdrlen;
                    645: 
                    646:     /* if we're missing some part of the packet: */
                    647:     if (the_bpf_header.bh_caplen != the_bpf_header.bh_datalen
                    648:        || ((bpf->tme_bsd_bpf_buffer_offset + the_bpf_header.bh_datalen)
                    649:            > bpf->tme_bsd_bpf_buffer_end)) {
                    650:       tme_log(&bpf->tme_bsd_bpf_element->tme_element_log_handle, 1, TME_OK,
                    651:              (&bpf->tme_bsd_bpf_element->tme_element_log_handle,
                    652:               _("flushed truncated BPF packet")));
                    653:       bpf->tme_bsd_bpf_buffer_offset += the_bpf_header.bh_datalen;
                    654:       continue;
                    655:     }
                    656: 
                    657:     /* if this packet isn't big enough to even have an Ethernet header: */
                    658:     if (the_bpf_header.bh_datalen < sizeof(struct tme_ethernet_header)) {
                    659:       tme_log(&bpf->tme_bsd_bpf_element->tme_element_log_handle, 1, TME_OK,
                    660:              (&bpf->tme_bsd_bpf_element->tme_element_log_handle,
                    661:               _("flushed short BPF packet")));
                    662:       bpf->tme_bsd_bpf_buffer_offset += the_bpf_header.bh_datalen;
                    663:       continue;
                    664:     }
                    665: 
1.1.1.3 ! root      666:     /* if packets need to be delayed: */
        !           667:     if (bpf->tme_bsd_bpf_delay_time > 0) {
        !           668:       
        !           669:       /* if the current release time is before this packet's time: */
        !           670:       if ((bpf->tme_bsd_bpf_delay_release.tv_sec
        !           671:           < the_bpf_header.bh_tstamp.tv_sec)
        !           672:          || ((bpf->tme_bsd_bpf_delay_release.tv_sec
        !           673:               == the_bpf_header.bh_tstamp.tv_sec)
        !           674:              && (bpf->tme_bsd_bpf_delay_release.tv_usec
        !           675:                  < the_bpf_header.bh_tstamp.tv_usec))) {
        !           676: 
        !           677:        /* update the current release time, by taking the current time
        !           678:           and subtracting the delay time: */
        !           679:        gettimeofday(&bpf->tme_bsd_bpf_delay_release, NULL);
        !           680:        if (bpf->tme_bsd_bpf_delay_release.tv_usec < bpf->tme_bsd_bpf_delay_time) {
        !           681:          bpf->tme_bsd_bpf_delay_release.tv_usec += 1000000UL;
        !           682:          bpf->tme_bsd_bpf_delay_release.tv_sec--;
        !           683:        }
        !           684:        bpf->tme_bsd_bpf_delay_release.tv_usec -= bpf->tme_bsd_bpf_delay_time;
        !           685:       }
        !           686: 
        !           687:       /* if the current release time is still before this packet's
        !           688:          time: */
        !           689:       if ((bpf->tme_bsd_bpf_delay_release.tv_sec
        !           690:           < the_bpf_header.bh_tstamp.tv_sec)
        !           691:          || ((bpf->tme_bsd_bpf_delay_release.tv_sec
        !           692:               == the_bpf_header.bh_tstamp.tv_sec)
        !           693:              && (bpf->tme_bsd_bpf_delay_release.tv_usec
        !           694:                  < the_bpf_header.bh_tstamp.tv_usec))) {
        !           695: 
        !           696:        /* set the sleep time: */
        !           697:        assert ((bpf->tme_bsd_bpf_delay_release.tv_sec
        !           698:                 == the_bpf_header.bh_tstamp.tv_sec)
        !           699:                || ((bpf->tme_bsd_bpf_delay_release.tv_sec + 1)
        !           700:                    == the_bpf_header.bh_tstamp.tv_sec));
        !           701:        bpf->tme_bsd_bpf_delay_sleep
        !           702:          = (((bpf->tme_bsd_bpf_delay_release.tv_sec
        !           703:               == the_bpf_header.bh_tstamp.tv_sec)
        !           704:              ? 0
        !           705:              : 1000000UL)
        !           706:             + the_bpf_header.bh_tstamp.tv_usec
        !           707:             - bpf->tme_bsd_bpf_delay_release.tv_usec);
        !           708: 
        !           709:        /* rewind the buffer pointer: */
        !           710:        bpf->tme_bsd_bpf_buffer_offset -= the_bpf_header.bh_hdrlen;
        !           711: 
        !           712:        /* stop now: */
        !           713:        break;
        !           714:       }
        !           715:     }
        !           716: 
1.1       root      717:     /* form the single frame chunk: */
                    718:     frame_chunk_buffer.tme_ethernet_frame_chunk_next = NULL;
                    719:     frame_chunk_buffer.tme_ethernet_frame_chunk_bytes
                    720:       = bpf->tme_bsd_bpf_buffer + bpf->tme_bsd_bpf_buffer_offset;
                    721:     frame_chunk_buffer.tme_ethernet_frame_chunk_bytes_count
                    722:       = the_bpf_header.bh_datalen;
                    723: 
                    724:     /* copy out the frame: */
                    725:     count = tme_ethernet_chunks_copy(frame_chunks, &frame_chunk_buffer);
                    726: 
1.1.1.3 ! root      727:     /* if this is a peek: */
        !           728:     if (flags & TME_ETHERNET_READ_PEEK) {
        !           729: 
        !           730:       /* rewind the buffer pointer: */
        !           731:       bpf->tme_bsd_bpf_buffer_offset -= the_bpf_header.bh_hdrlen;
        !           732:     }
        !           733: 
        !           734:     /* otherwise, this isn't a peek: */
        !           735:     else {
1.1       root      736: 
                    737:       /* update the buffer pointer: */
                    738:       bpf->tme_bsd_bpf_buffer_offset += the_bpf_header.bh_datalen;
                    739:     }
                    740: 
                    741:     /* success: */
                    742:     rc = count;
                    743:     break;
                    744:   }
                    745: 
1.1.1.3 ! root      746:   /* if the buffer is empty, or if we failed to read a packet,
        !           747:      wake up the reader: */
        !           748:   if ((bpf->tme_bsd_bpf_buffer_offset
        !           749:        >= bpf->tme_bsd_bpf_buffer_end)
        !           750:       || rc <= 0) {
1.1       root      751:     tme_cond_notify(&bpf->tme_bsd_bpf_cond_reader, TRUE);
                    752:   }
                    753: 
                    754:   /* unlock our mutex: */
                    755:   tme_mutex_unlock(&bpf->tme_bsd_bpf_mutex);
                    756: 
                    757:   /* done: */
                    758:   return (rc);
                    759: }
                    760: 
                    761: /* this makes a new Ethernet connection: */
                    762: static int
                    763: _tme_bsd_bpf_connection_make(struct tme_connection *conn, unsigned int state)
                    764: {
                    765:   struct tme_bsd_bpf *bpf;
                    766:   struct tme_ethernet_connection *conn_eth;
                    767:   struct tme_ethernet_connection *conn_eth_other;
                    768: 
                    769:   /* recover our data structures: */
                    770:   bpf = conn->tme_connection_element->tme_element_private;
                    771:   conn_eth = (struct tme_ethernet_connection *) conn;
                    772:   conn_eth_other = (struct tme_ethernet_connection *) conn->tme_connection_other;
                    773: 
                    774:   /* both sides must be Ethernet connections: */
                    775:   assert(conn->tme_connection_type == TME_CONNECTION_ETHERNET);
                    776:   assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_ETHERNET);
                    777: 
                    778:   /* we're always set up to answer calls across the connection, so we
                    779:      only have to do work when the connection has gone full, namely
                    780:      taking the other side of the connection: */
                    781:   if (state == TME_CONNECTION_FULL) {
                    782: 
                    783:     /* lock our mutex: */
                    784:     tme_mutex_lock(&bpf->tme_bsd_bpf_mutex);
                    785: 
                    786:     /* save our connection: */
                    787:     bpf->tme_bsd_bpf_eth_connection = conn_eth_other;
                    788: 
                    789:     /* unlock our mutex: */
                    790:     tme_mutex_unlock(&bpf->tme_bsd_bpf_mutex);
                    791:   }
                    792: 
                    793:   return (TME_OK);
                    794: }
                    795: 
                    796: /* this breaks a connection: */
                    797: static int
                    798: _tme_bsd_bpf_connection_break(struct tme_connection *conn, unsigned int state)
                    799: {
                    800:   abort();
                    801: }
                    802: 
                    803: /* this makes a new connection side for a BPF: */
                    804: static int
                    805: _tme_bsd_bpf_connections_new(struct tme_element *element, 
                    806:                             const char * const *args, 
                    807:                             struct tme_connection **_conns,
                    808:                             char **_output)
                    809: {
                    810:   struct tme_bsd_bpf *bpf;
                    811:   struct tme_ethernet_connection *conn_eth;
                    812:   struct tme_connection *conn;
                    813: 
                    814:   /* recover our data structure: */
                    815:   bpf = (struct tme_bsd_bpf *) element->tme_element_private;
                    816: 
                    817:   /* if we already have an Ethernet connection, do nothing: */
                    818:   if (bpf->tme_bsd_bpf_eth_connection != NULL) {
                    819:     return (TME_OK);
                    820:   }
                    821: 
                    822:   /* allocate the new Ethernet connection: */
                    823:   conn_eth = tme_new0(struct tme_ethernet_connection, 1);
                    824:   conn = &conn_eth->tme_ethernet_connection;
                    825:   
                    826:   /* fill in the generic connection: */
                    827:   conn->tme_connection_next = *_conns;
                    828:   conn->tme_connection_type = TME_CONNECTION_ETHERNET;
                    829:   conn->tme_connection_score = tme_ethernet_connection_score;
                    830:   conn->tme_connection_make = _tme_bsd_bpf_connection_make;
                    831:   conn->tme_connection_break = _tme_bsd_bpf_connection_break;
                    832: 
                    833:   /* fill in the Ethernet connection: */
                    834:   conn_eth->tme_ethernet_connection_config = _tme_bsd_bpf_config;
                    835:   conn_eth->tme_ethernet_connection_ctrl = _tme_bsd_bpf_ctrl;
                    836:   conn_eth->tme_ethernet_connection_read = _tme_bsd_bpf_read;
                    837: 
                    838:   /* return the connection side possibility: */
                    839:   *_conns = conn;
                    840: 
                    841:   /* done: */
                    842:   return (TME_OK);
                    843: }
                    844: 
                    845: /* the new BPF function: */
                    846: TME_ELEMENT_SUB_NEW_DECL(tme_host_bsd,bpf) {
                    847:   struct tme_bsd_bpf *bpf;
                    848:   int bpf_fd;
                    849: #define DEV_BPF_FORMAT "/dev/bpf%d"
                    850:   char dev_bpf_filename[sizeof(DEV_BPF_FORMAT) + (sizeof(int) * 3) + 1];
                    851:   int minor;
                    852:   int saved_errno;
                    853:   u_int bpf_opt;
                    854:   struct bpf_version version;
                    855:   u_int packet_buffer_size;
                    856:   const char *ifr_name_user;
                    857:   struct ifreq *ifr;
1.1.1.3 ! root      858:   unsigned long delay_time;
1.1       root      859:   int arg_i;
                    860:   int usage;
                    861:   int rc;
                    862:   
                    863:   /* check our arguments: */
                    864:   usage = 0;
                    865:   ifr_name_user = NULL;
1.1.1.3 ! root      866:   delay_time = 0;
1.1       root      867:   arg_i = 1;
                    868:   for (;;) {
                    869: 
                    870:     /* the interface we're supposed to use: */
                    871:     if (TME_ARG_IS(args[arg_i + 0], "interface")
                    872:        && args[arg_i + 1] != NULL) {
                    873:       ifr_name_user = args[arg_i + 1];
                    874:       arg_i += 2;
                    875:     }
                    876: 
1.1.1.3 ! root      877:     /* a delay time in microseconds: */
        !           878:     else if (TME_ARG_IS(args[arg_i + 0], "delay")
        !           879:             && (delay_time = tme_misc_unumber_parse(args[arg_i + 1], 0)) > 0) {
        !           880:       arg_i += 2;
        !           881:     }
        !           882:     
1.1       root      883:     /* if we ran out of arguments: */
                    884:     else if (args[arg_i + 0] == NULL) {
                    885:       break;
                    886:     }
                    887: 
                    888:     /* otherwise this is a bad argument: */
                    889:     else {
                    890:       tme_output_append_error(_output,
                    891:                              "%s %s", 
                    892:                              args[arg_i],
                    893:                              _("unexpected"));
                    894:       usage = TRUE;
                    895:       break;
                    896:     }
                    897:   }
                    898: 
                    899:   if (usage) {
                    900:     tme_output_append_error(_output,
1.1.1.3 ! root      901:                            "%s %s [ interface %s ] [ delay %s ]",
1.1       root      902:                            _("usage:"),
                    903:                            args[0],
1.1.1.3 ! root      904:                            _("INTERFACE"),
        !           905:                            _("MICROSECONDS"));
1.1       root      906:     return (EINVAL);
                    907:   }
                    908: 
                    909:   /* find the interface we will use: */
                    910:   rc = tme_bsd_if_find(ifr_name_user, &ifr, NULL, NULL);
                    911:   if (rc != TME_OK) {
                    912:     tme_output_append_error(_output, _("couldn't find an interface"));
                    913:     return (ENOENT);
                    914:   }
                    915:   tme_log(&element->tme_element_log_handle, 1, TME_OK, 
                    916:          (&element->tme_element_log_handle, 
                    917:           "using interface %s",
                    918:           ifr->ifr_name));
                    919: 
                    920:   /* loop trying to open a /dev/bpf device: */
                    921:   for (minor = 0;; minor++) {
                    922:     
                    923:     /* form the name of the next device to try, then try opening
                    924:        it. if we succeed, we're done: */
                    925:     sprintf(dev_bpf_filename, DEV_BPF_FORMAT, minor);
                    926:     tme_log(&element->tme_element_log_handle, 1, TME_OK,
                    927:            (&element->tme_element_log_handle,
                    928:             "trying %s",
                    929:             dev_bpf_filename));
                    930:     if ((bpf_fd = open(dev_bpf_filename, O_RDWR)) >= 0) {
                    931:       tme_log(&element->tme_element_log_handle, 1, TME_OK,
                    932:              (&element->tme_element_log_handle,
                    933:               "opened %s",
                    934:               dev_bpf_filename));
                    935:       break;
                    936:     }
                    937: 
                    938:     /* we failed to open this device.  if this device was simply
                    939:        busy, loop: */
                    940:     saved_errno = errno;
                    941:     tme_log(&element->tme_element_log_handle, 1, saved_errno,
                    942:            (&element->tme_element_log_handle, 
                    943:             "%s", dev_bpf_filename));
                    944:     if (saved_errno == EBUSY
                    945:        || saved_errno == EACCES) {
                    946:       continue;
                    947:     }
                    948: 
                    949:     /* otherwise, we have failed: */
                    950:     return (saved_errno);
                    951:   }
                    952: 
                    953:   /* this macro helps in closing the BPF socket on error: */
                    954: #define _TME_BPF_RAW_OPEN_ERROR(x) saved_errno = errno; x; errno = saved_errno
                    955: 
                    956:   /* check the BPF version: */
                    957:   if (ioctl(bpf_fd, BIOCVERSION, &version) < 0) {
                    958:     tme_log(&element->tme_element_log_handle, 1, errno,
                    959:            (&element->tme_element_log_handle,
                    960:             _("failed to get the BPF version on %s"),
                    961:             dev_bpf_filename));
                    962:     _TME_BPF_RAW_OPEN_ERROR(close(bpf_fd));
                    963:     return (errno);
                    964:   }
                    965:   if (version.bv_major != BPF_MAJOR_VERSION
                    966:       || version.bv_minor < BPF_MINOR_VERSION) {
                    967:     tme_log(&element->tme_element_log_handle, 1, errno,
                    968:            (&element->tme_element_log_handle,
                    969:             _("kernel BPF version is %d.%d, my BPF version is %d.%d"),
                    970:             version.bv_major, version.bv_minor,
                    971:             BPF_MAJOR_VERSION, BPF_MINOR_VERSION));
                    972:     close(bpf_fd);
                    973:     return (ENXIO);
                    974:   }
                    975: 
                    976:   /* put the BPF device into immediate mode: */
                    977:   bpf_opt = TRUE;
                    978:   if (ioctl(bpf_fd, BIOCIMMEDIATE, &bpf_opt) < 0) {
                    979:     tme_log(&element->tme_element_log_handle, 1, errno,
                    980:            (&element->tme_element_log_handle,
                    981:             _("failed to put %s into immediate mode"),
                    982:             dev_bpf_filename));
                    983:     _TME_BPF_RAW_OPEN_ERROR(close(bpf_fd));
                    984:     return (errno);
                    985:   }
                    986: 
                    987:   /* tell the BPF device we're providing complete Ethernet headers: */
                    988:   bpf_opt = TRUE;
                    989:   if (ioctl(bpf_fd, BIOCSHDRCMPLT, &bpf_opt) < 0) {
                    990:     tme_log(&element->tme_element_log_handle, 1, errno,
                    991:            (&element->tme_element_log_handle,
                    992:             _("failed to put %s into complete-headers mode"),
                    993:             dev_bpf_filename));
                    994:     _TME_BPF_RAW_OPEN_ERROR(close(bpf_fd));
                    995:     return (errno);
                    996:   }
                    997: 
                    998:   /* point the BPF device at the interface we're using: */
                    999:   if (ioctl(bpf_fd, BIOCSETIF, ifr) < 0) {
                   1000:     tme_log(&element->tme_element_log_handle, 1, errno,
                   1001:            (&element->tme_element_log_handle,
                   1002:             _("failed to point BPF socket at %s"),
                   1003:             ifr->ifr_name));
                   1004:     saved_errno = errno;
                   1005:     close(bpf_fd);
                   1006:     errno = saved_errno;
                   1007:     return (errno);
                   1008:   }
                   1009: 
                   1010:   /* get the BPF read buffer size: */
                   1011:   if (ioctl(bpf_fd, BIOCGBLEN, &packet_buffer_size) < 0) {
                   1012:     tme_log(&element->tme_element_log_handle, 1, errno,
                   1013:            (&element->tme_element_log_handle,
                   1014:             _("failed to read the buffer size for %s"),
                   1015:             dev_bpf_filename));
                   1016:     _TME_BPF_RAW_OPEN_ERROR(close(bpf_fd));
                   1017:     return (errno);
                   1018:   }
                   1019:   tme_log(&element->tme_element_log_handle, 1, errno,
                   1020:          (&element->tme_element_log_handle,
                   1021:           _("buffer size for %s is %u"),
                   1022:           dev_bpf_filename, packet_buffer_size));
                   1023: 
                   1024:   /* set the interface into promiscuous mode: */
                   1025:   if (ioctl(bpf_fd, BIOCPROMISC) < 0) {
                   1026:     tme_log(&element->tme_element_log_handle, 1, errno,
                   1027:            (&element->tme_element_log_handle,
                   1028:             _("failed to set promiscuous mode on %s"),
                   1029:             dev_bpf_filename));
                   1030:     _TME_BPF_RAW_OPEN_ERROR(close(bpf_fd));
                   1031:     return (errno);
                   1032:   }
                   1033:   
                   1034:   /* start our data structure: */
                   1035:   bpf = tme_new0(struct tme_bsd_bpf, 1);
                   1036:   bpf->tme_bsd_bpf_element = element;
                   1037:   bpf->tme_bsd_bpf_fd = bpf_fd;
                   1038:   bpf->tme_bsd_bpf_buffer_size = packet_buffer_size;
                   1039:   bpf->tme_bsd_bpf_buffer = tme_new(tme_uint8_t, packet_buffer_size);
1.1.1.3 ! root     1040:   bpf->tme_bsd_bpf_delay_time = delay_time;
1.1       root     1041: 
                   1042:   /* start the threads: */
                   1043:   tme_mutex_init(&bpf->tme_bsd_bpf_mutex);
1.1.1.3 ! root     1044:   tme_cond_init(&bpf->tme_bsd_bpf_cond_reader);
1.1       root     1045:   tme_thread_create((tme_thread_t) _tme_bsd_bpf_th_reader, bpf);
                   1046: 
                   1047:   /* fill the element: */
                   1048:   element->tme_element_private = bpf;
                   1049:   element->tme_element_connections_new = _tme_bsd_bpf_connections_new;
                   1050: 
                   1051:   return (TME_OK);
                   1052: #undef _TME_BPF_RAW_OPEN_ERROR
                   1053: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.