text: /* dhcp_bpf_filter taken from bpf.c in dhcp-3.1.0
   *
   * Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
   * Copyright (c) 1996-2003 by Internet Software Consortium
   *
   * Permission to use, copy, modify, and distribute this software for any
   * purpose with or without fee is hereby granted, provided that the above
   * copyright notice and this permission notice appear in all copies.
   *
   * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
   * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   *
   *   Internet Systems Consortium, Inc.
   *   950 Charter Street
   *   Redwood City, CA 94063
   *   <info@isc.org>
   *   http://www.isc.org/
   */
  
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <sys/ioctl.h>
  
  #include <net/ethernet.h>
  
  #include <linux/if_packet.h>
  #include <linux/filter.h>
  
  #include <net/if.h>
  
  #include <arpa/inet.h>
  
  #include <errno.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  
  #include <fcntl.h>
  
  #include "caml/memory.h"
  #include "caml/fail.h"
  #include "caml/unixsupport.h"
  #include "caml/signals.h"
  #include "caml/alloc.h"
  #include "caml/custom.h"
  #include "caml/bigarray.h"
  
  #define BOOTPC          68
  #define BPF_WHOLEPACKET 0x0fffffff
  
  #ifndef BPF_ETHCOOK
  # define BPF_ETHCOOK 0
  #endif
  
  static const struct sock_filter bootp_bpf_filter [] = {
    /* Make sure this is an IP packet... */
    BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),
    /* Make sure it's a UDP packet... */
    BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23 + BPF_ETHCOOK),
    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
    /* Make sure this isn't a fragment... */
    BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20 + BPF_ETHCOOK),
    BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
    /* Get the IP header length... */
    BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14 + BPF_ETHCOOK),
    /* Make sure it's to the right port... */
    BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16 + BPF_ETHCOOK),
    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, BOOTPC, 0, 1),
    /* If we passed all the tests, ask for the whole packet. */
    BPF_STMT(BPF_RET + BPF_K, BPF_WHOLEPACKET),
    /* Otherwise, drop it. */
    BPF_STMT(BPF_RET + BPF_K, 0),
  };
  
  /* Filters */
  CAMLprim value bpf_filter(value vunit)
  {
    CAMLparam0();
    CAMLlocal1(vfilter);
    vfilter = caml_alloc_string(sizeof(bootp_bpf_filter));
    memcpy(String_val(vfilter), bootp_bpf_filter, sizeof(bootp_bpf_filter));
    CAMLreturn (vfilter);
  }
  