📄 bpf.c
字号:
/* bpf.c BPF socket interface code, originally contributed by Archie Cobbs. *//* * Copyright (c) 1996-2000 Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of The Internet Software Consortium nor the names * of its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * This software was contributed to the Internet Software Consortium * by Archie Cobbs, and is now maintained by Ted Lemon in cooperation * with Nominum, Inc. To learn more about the Internet Software * Consortium, see ``http://www.isc.org/''. To learn more about Vixie * Enterprises, see ``http://www.vix.com''. To learn more about * Nominum, Inc., see ``http://www.nominum.com''. * * Patches for FDDI support on Digital Unix were written by Bill * Stapleton, and maintained for a while by Mike Meredith before he * managed to get me to integrate them. */#ifndef lintstatic char copyright[] ="$Id: bpf.c,v 1.48 2001/04/08 21:12:49 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";#endif /* not lint */#include "dhcpd.h"#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) \ || defined (USE_LPF_RECEIVE)# if defined (USE_LPF_RECEIVE)# include <asm/types.h># include <linux/filter.h># define bpf_insn sock_filter /* Linux: dare to be gratuitously different. */# else# include <sys/ioctl.h># include <sys/uio.h># include <net/bpf.h># if defined (NEED_OSF_PFILT_HACKS)# include <net/pfilt.h># endif# endif#include <netinet/in_systm.h>#include "includes/netinet/ip.h"#include "includes/netinet/udp.h"#include "includes/netinet/if_ether.h"#endif/* Reinitializes the specified interface after an address change. This is not required for packet-filter APIs. */#ifdef USE_BPF_SENDvoid if_reinitialize_send (info) struct interface_info *info;{}#endif#ifdef USE_BPF_RECEIVEvoid if_reinitialize_receive (info) struct interface_info *info;{}#endif/* Called by get_interface_list for each interface that's discovered. Opens a packet filter for each interface and adds it to the select mask. */#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)int if_register_bpf (info) struct interface_info *info;{ int sock; char filename[50]; int b; /* Open a BPF device */ for (b = 0; 1; b++) {#ifndef NO_SNPRINTF snprintf(filename, sizeof(filename), BPF_FORMAT, b);#else sprintf(filename, BPF_FORMAT, b);#endif sock = open (filename, O_RDWR, 0); if (sock < 0) { if (errno == EBUSY) { continue; } else { if (!b) log_fatal ("No bpf devices.%s%s%s", " Please read the README", " section for your operating", " system."); log_fatal ("Can't find free bpf: %m"); } } else { break; } } /* Set the BPF device to point at this interface. */ if (ioctl (sock, BIOCSETIF, info -> ifp) < 0) log_fatal ("Can't attach interface %s to bpf device %s: %m", info -> name, filename); return sock;}#endif /* USE_BPF_SEND || USE_BPF_RECEIVE */#ifdef USE_BPF_SENDvoid if_register_send (info) struct interface_info *info;{ /* If we're using the bpf API for sending and receiving, we don't need to register this interface twice. */#ifndef USE_BPF_RECEIVE info -> wfdesc = if_register_bpf (info, interface);#else info -> wfdesc = info -> rfdesc;#endif if (!quiet_interface_discovery) log_info ("Sending on BPF/%s/%s%s%s", info -> name, print_hw_addr (info -> hw_address.hbuf [0], info -> hw_address.hlen - 1, &info -> hw_address.hbuf [1]), (info -> shared_network ? "/" : ""), (info -> shared_network ? info -> shared_network -> name : ""));}void if_deregister_send (info) struct interface_info *info;{ /* If we're using the bpf API for sending and receiving, we don't need to register this interface twice. */#ifndef USE_BPF_RECEIVE close (info -> wfdesc);#endif info -> wfdesc = -1; if (!quiet_interface_discovery) log_info ("Disabling output on BPF/%s/%s%s%s", info -> name, print_hw_addr (info -> hw_address.hbuf [0], info -> hw_address.hlen - 1, &info -> hw_address.hbuf [1]), (info -> shared_network ? "/" : ""), (info -> shared_network ? info -> shared_network -> name : ""));}#endif /* USE_BPF_SEND */#if defined (USE_BPF_RECEIVE) || defined (USE_LPF_RECEIVE)/* Packet filter program... XXX Changes to the filter program may require changes to the constant offsets used in if_register_send to patch the BPF program! XXX */struct bpf_insn dhcp_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_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_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0), /* Get the IP header length... */ BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14), /* Make sure it's to the right port... */ BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16), BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */ /* If we passed all the tests, ask for the whole packet. */ BPF_STMT(BPF_RET+BPF_K, (u_int)-1), /* Otherwise, drop it. */ BPF_STMT(BPF_RET+BPF_K, 0),};#if defined (DEC_FDDI)struct bpf_insn *bpf_fddi_filter;#endifint dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn);#if defined (HAVE_TR_SUPPORT)struct bpf_insn dhcp_bpf_tr_filter [] = { /* accept all token ring packets due to variable length header */ /* if we want to get clever, insert the program here */ /* If we passed all the tests, ask for the whole packet. */ BPF_STMT(BPF_RET+BPF_K, (u_int)-1), /* Otherwise, drop it. */ BPF_STMT(BPF_RET+BPF_K, 0),};int dhcp_bpf_tr_filter_len = (sizeof dhcp_bpf_tr_filter / sizeof (struct bpf_insn));#endif /* HAVE_TR_SUPPORT */#endif /* USE_LPF_RECEIVE || USE_BPF_RECEIVE */#if defined (USE_BPF_RECEIVE)void if_register_receive (info) struct interface_info *info;{ int flag = 1; struct bpf_version v; u_int32_t addr; struct bpf_program p; u_int32_t bits;#ifdef DEC_FDDI int link_layer;#endif /* DEC_FDDI */ /* Open a BPF device and hang it on this interface... */ info -> rfdesc = if_register_bpf (info); /* Make sure the BPF version is in range... */ if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0) log_fatal ("Can't get BPF version: %m"); if (v.bv_major != BPF_MAJOR_VERSION || v.bv_minor < BPF_MINOR_VERSION) log_fatal ("BPF version mismatch - recompile DHCP!"); /* Set immediate mode so that reads return as soon as a packet comes in, rather than waiting for the input buffer to fill with packets. */ if (ioctl (info -> rfdesc, BIOCIMMEDIATE, &flag) < 0) log_fatal ("Can't set immediate mode on bpf device: %m");#ifdef NEED_OSF_PFILT_HACKS /* Allow the copyall flag to be set... */ if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0) log_fatal ("Can't set ALLOWCOPYALL: %m"); /* Clear all the packet filter mode bits first... */ bits = 0; if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0) log_fatal ("Can't clear pfilt bits: %m"); /* Set the ENBATCH, ENCOPYALL, ENBPFHDR bits... */ bits = ENBATCH | ENCOPYALL | ENBPFHDR; if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0) log_fatal ("Can't set ENBATCH|ENCOPYALL|ENBPFHDR: %m");#endif /* Get the required BPF buffer length from the kernel. */ if (ioctl (info -> rfdesc, BIOCGBLEN, &info -> rbuf_max) < 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -