int main(int argc, char* argv[]) { int dummy; char cmd; double counter; dummy = (argc == INT_MAX - 1) ? argv[argc-1][0] : 1; if (argc == 3) { cmd = argv[1][1]; counter = strtod(argv[2], NULL); if (counter < 0 || counter > UINT32_MAX) counter = 1; } else { cmd = 'j'; counter = 1; usage(argv[0]); } if (!bpf_validate(insns, sizeof(insns) / sizeof(insns[0]))) errx(EXIT_FAILURE, "Not valid bpf program"); switch (cmd) { case 'j': test_bpfjit(counter, test_pkt, sizeof(test_pkt), dummy); break; case 'b': test_bpf_filter(counter, dummy); break; case 'c': test_c(counter, test_pkt, sizeof(test_pkt), dummy); } return EXIT_SUCCESS; }
int main(int argc, char *argv[]){ struct bpf_insn ins_buffer[N]; klee_make_symbolic(ins_buffer, N * sizeof(ins_buffer[0]), "lol"); return bpf_validate(ins_buffer, N); }
/* * Make a copy of a BPF program and put it in the "fcode" member of * a "pcap_t". * * If we fail to allocate memory for the copy, fill in the "errbuf" * member of the "pcap_t" with an error message, and return -1; * otherwise, return 0. */ int install_bpf_program(pcap_t *p, struct bpf_program *fp) { size_t prog_size; /* * Validate the program. */ if (!bpf_validate(fp->bf_insns, fp->bf_len)) { snprintf(p->errbuf, sizeof(p->errbuf), "BPF program is not valid"); return (-1); } /* * Free up any already installed program. */ pcap_freecode(&p->fcode); prog_size = sizeof(*fp->bf_insns) * fp->bf_len; p->fcode.bf_len = fp->bf_len; p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size); if (p->fcode.bf_insns == NULL) { snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); return (-1); } memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size); return (0); }
int bsf_filter(bsf_t *bsf_desc, in_addr_t clt_ip, in_port_t clt_port, in_addr_t svr_ip, in_port_t svr_port) { unsigned char dummy_packet[BSF_SNAP_LEN]; populate_packet(dummy_packet, clt_ip, clt_port, svr_ip, svr_port); //validate the bpf program if (bsf_desc->flags && BSF_FLAG_VALIDATE == BSF_FLAG_VALIDATE) { //validate the BPF: if (bpf_validate(bsf_desc->bpf_prog->bf_insns, bsf_desc->bpf_prog->bf_len) == 0) { //validation failed return BSF_RESULT_ERROR; } } if (bpf_filter(bsf_desc->bpf_prog->bf_insns, dummy_packet, BSF_SNAP_LEN, BSF_SNAP_LEN) == BSF_SNAP_LEN) { return BSF_RESULT_PASS; } else { return BSF_RESULT_FAIL; } }
int daemon_unpackapplyfilter(pcap_t *fp, unsigned int *nread, int *plen, char *errbuf) { struct rpcap_filter filter; struct rpcap_filterbpf_insn insn; struct bpf_insn *bf_insn; struct bpf_program bf_prog; unsigned int i; if ( ( *nread+= sock_recv(fp->rmt_sockctrl, (char *) &filter, sizeof(struct rpcap_filter), errbuf)) == -1) { // to avoid blocking on the sock_discard() *plen= *nread; return -1; } bf_prog.bf_len= ntohl(filter.nitems); if (ntohs(filter.filtertype) != RPCAP_UPDATEFILTER_BPF) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "Only BPF/NPF filters are currently supported"); return -1; } bf_insn= (struct bpf_insn *) malloc ( sizeof(struct bpf_insn) * bf_prog.bf_len); if (bf_insn == NULL) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); return -1; } bf_prog.bf_insns= bf_insn; for (i= 0; i < bf_prog.bf_len; i++) { if ( ( *nread+= sock_recv(fp->rmt_sockctrl, (char *) &insn, sizeof(struct rpcap_filterbpf_insn), errbuf)) == -1) return -1; bf_insn->code= ntohs(insn.code); bf_insn->jf= insn.jf; bf_insn->jt= insn.jt; bf_insn->k= ntohl(insn.k); bf_insn++; } if (bpf_validate(bf_prog.bf_insns, bf_prog.bf_len) == 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "The filter contains bogus instructions"); return -1; } if (pcap_setfilter(fp, &bf_prog) ) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "RPCAP error: %s", fp->errbuf); return -1; } return 0; }
void bpf_parse_rules(char *rulefile, struct sock_fprog *bpf) { int ret; char buff[256]; struct sock_filter sf_single = { 0x06, 0, 0, 0xFFFFFFFF }; FILE *fp; if (rulefile == NULL) { bpf->len = 1; bpf->filter = xmalloc(sizeof(sf_single)); fmemcpy(&bpf->filter[0], &sf_single, sizeof(sf_single)); return; } fp = fopen(rulefile, "r"); if (!fp) panic("Cannot read BPF rule file!\n"); fmemset(buff, 0, sizeof(buff)); while (fgets(buff, sizeof(buff), fp) != NULL) { buff[sizeof(buff) - 1] = 0; if (buff[0] != '{') { fmemset(buff, 0, sizeof(buff)); continue; } fmemset(&sf_single, 0, sizeof(sf_single)); ret = sscanf(buff, "{ 0x%x, %u, %u, 0x%08x },", (unsigned int *) &sf_single.code, (unsigned int *) &sf_single.jt, (unsigned int *) &sf_single.jf, (unsigned int *) &sf_single.k); if (ret != 4) panic("BPF syntax error!\n"); bpf->len++; bpf->filter = xrealloc(bpf->filter, 1, bpf->len * sizeof(sf_single)); fmemcpy(&bpf->filter[bpf->len - 1], &sf_single, sizeof(sf_single)); fmemset(buff, 0, sizeof(buff)); } fclose(fp); if (bpf_validate(bpf) == 0) panic("This is not a valid BPF program!\n"); }
/* * Set d's packet filter program to fp. If this file already has a filter, * free it and replace it. Returns EINVAL for bogus requests. */ int bpf_setf(struct bpf_d *d, struct bpf_program *fp, int wf) { struct bpf_insn *fcode, *old; u_int flen, size; int s; old = wf ? d->bd_wfilter : d->bd_rfilter; if (fp->bf_insns == 0) { if (fp->bf_len != 0) return (EINVAL); s = splnet(); if (wf) d->bd_wfilter = 0; else d->bd_rfilter = 0; bpf_reset_d(d); splx(s); if (old != 0) free((caddr_t)old, M_DEVBUF); return (0); } flen = fp->bf_len; if (flen > BPF_MAXINSNS) return (EINVAL); size = flen * sizeof(*fp->bf_insns); fcode = (struct bpf_insn *)malloc(size, M_DEVBUF, M_WAITOK); if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 && bpf_validate(fcode, (int)flen)) { s = splnet(); if (wf) d->bd_wfilter = fcode; else d->bd_rfilter = fcode; bpf_reset_d(d); splx(s); if (old != 0) free((caddr_t)old, M_DEVBUF); return (0); } free((caddr_t)fcode, M_DEVBUF); return (EINVAL); }
/* * Set d's packet filter program to fp. If this file already has a filter, * free it and replace it. Returns EINVAL for bogus requests. */ static int bpf_setf(struct bpf_d *d, u_int bf_len, user_addr_t bf_insns) { struct bpf_insn *fcode, *old; u_int flen, size; old = d->bd_filter; if (bf_insns == USER_ADDR_NULL) { if (bf_len != 0) return (EINVAL); d->bd_filter = NULL; reset_d(d); if (old != 0) FREE((caddr_t)old, M_DEVBUF); return (0); } flen = bf_len; if (flen > BPF_MAXINSNS) return (EINVAL); size = flen * sizeof(struct bpf_insn); fcode = (struct bpf_insn *) _MALLOC(size, M_DEVBUF, M_WAIT); #ifdef __APPLE__ if (fcode == NULL) return (ENOBUFS); #endif if (copyin(bf_insns, (caddr_t)fcode, size) == 0 && bpf_validate(fcode, (int)flen)) { d->bd_filter = fcode; reset_d(d); if (old != 0) FREE((caddr_t)old, M_DEVBUF); return (0); } FREE((caddr_t)fcode, M_DEVBUF); return (EINVAL); }
/* * Ioctl routine for generic ppp devices. */ int pppioctl(struct ppp_softc *sc, u_long cmd, caddr_t data, int flag, struct ucred *cred) { int error, flags, mru, npx; u_int nb; struct ppp_option_data *odp; struct compressor **cp; struct npioctl *npi; time_t t; #ifdef PPP_FILTER struct bpf_program *bp, *nbp; struct bpf_insn *newcode, *oldcode; int newcodelen; #endif /* PPP_FILTER */ #ifdef PPP_COMPRESS u_char ccp_option[CCP_MAX_OPTION_LENGTH]; #endif switch (cmd) { case FIONREAD: *(int *)data = sc->sc_inq.ifq_len; break; case PPPIOCGUNIT: *(int *)data = sc->sc_if.if_dunit; break; case PPPIOCGFLAGS: *(u_int *)data = sc->sc_flags; break; case PPPIOCSFLAGS: if ((error = priv_check_cred(cred, PRIV_ROOT, 0)) != 0) return (error); flags = *(int *)data & SC_MASK; crit_enter(); #ifdef PPP_COMPRESS if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN)) ppp_ccp_closed(sc); #endif sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags; crit_exit(); break; case PPPIOCSMRU: if ((error = priv_check_cred(cred, PRIV_ROOT, 0)) != 0) return (error); mru = *(int *)data; if (mru >= PPP_MRU && mru <= PPP_MAXMRU) sc->sc_mru = mru; break; case PPPIOCGMRU: *(int *)data = sc->sc_mru; break; #ifdef VJC case PPPIOCSMAXCID: if ((error = priv_check_cred(cred, PRIV_ROOT, 0)) != 0) return (error); if (sc->sc_comp) { crit_enter(); sl_compress_init(sc->sc_comp, *(int *)data); crit_exit(); } break; #endif case PPPIOCXFERUNIT: if ((error = priv_check_cred(cred, PRIV_ROOT, 0)) != 0) return (error); sc->sc_xfer = curthread; break; #ifdef PPP_COMPRESS case PPPIOCSCOMPRESS: if ((error = priv_check_cred(cred, PRIV_ROOT, 0)) != 0) return (error); odp = (struct ppp_option_data *) data; nb = odp->length; if (nb > sizeof(ccp_option)) nb = sizeof(ccp_option); if ((error = copyin(odp->ptr, ccp_option, nb)) != 0) return (error); if (ccp_option[1] < 2) /* preliminary check on the length byte */ return (EINVAL); for (cp = ppp_compressors; *cp != NULL; ++cp) if ((*cp)->compress_proto == ccp_option[0]) { /* * Found a handler for the protocol - try to allocate * a compressor or decompressor. */ error = 0; if (odp->transmit) { crit_enter(); if (sc->sc_xc_state != NULL) (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); sc->sc_xcomp = *cp; sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb); if (sc->sc_xc_state == NULL) { if (sc->sc_flags & SC_DEBUG) kprintf("%s: comp_alloc failed\n", sc->sc_if.if_xname); error = ENOBUFS; } sc->sc_flags &= ~SC_COMP_RUN; crit_exit(); } else { crit_enter(); if (sc->sc_rc_state != NULL) (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); sc->sc_rcomp = *cp; sc->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb); if (sc->sc_rc_state == NULL) { if (sc->sc_flags & SC_DEBUG) kprintf("%s: decomp_alloc failed\n", sc->sc_if.if_xname); error = ENOBUFS; } sc->sc_flags &= ~SC_DECOMP_RUN; crit_exit(); } return (error); } if (sc->sc_flags & SC_DEBUG) kprintf("%s: no compressor for [%x %x %x], %x\n", sc->sc_if.if_xname, ccp_option[0], ccp_option[1], ccp_option[2], nb); return (EINVAL); /* no handler found */ #endif /* PPP_COMPRESS */ case PPPIOCGNPMODE: case PPPIOCSNPMODE: npi = (struct npioctl *) data; switch (npi->protocol) { case PPP_IP: npx = NP_IP; break; default: return EINVAL; } if (cmd == PPPIOCGNPMODE) { npi->mode = sc->sc_npmode[npx]; } else { if ((error = priv_check_cred(cred, PRIV_ROOT, 0)) != 0) return (error); if (npi->mode != sc->sc_npmode[npx]) { crit_enter(); sc->sc_npmode[npx] = npi->mode; if (npi->mode != NPMODE_QUEUE) { ppp_requeue(sc); (*sc->sc_start)(sc); } crit_exit(); } } break; case PPPIOCGIDLE: crit_enter(); t = time_uptime; ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent; ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv; crit_exit(); break; #ifdef PPP_FILTER case PPPIOCSPASS: case PPPIOCSACTIVE: nbp = (struct bpf_program *) data; if ((unsigned) nbp->bf_len > BPF_MAXINSNS) return EINVAL; newcodelen = nbp->bf_len * sizeof(struct bpf_insn); if (newcodelen != 0) { newcode = kmalloc(newcodelen, M_DEVBUF, M_WAITOK); if ((error = copyin((caddr_t)nbp->bf_insns, (caddr_t)newcode, newcodelen)) != 0) { kfree(newcode, M_DEVBUF); return error; } if (!bpf_validate(newcode, nbp->bf_len)) { kfree(newcode, M_DEVBUF); return EINVAL; } } else newcode = NULL; bp = (cmd == PPPIOCSPASS)? &sc->sc_pass_filt: &sc->sc_active_filt; oldcode = bp->bf_insns; crit_enter(); bp->bf_len = nbp->bf_len; bp->bf_insns = newcode; crit_exit(); if (oldcode != NULL) kfree(oldcode, M_DEVBUF); break; #endif default: return (ENOIOCTL); } return (0); }
/* * There are only two special setsockopt's for SOL_SOCKET with PF_PACKET: * SO_ATTACH_FILTER and SO_DETACH_FILTER. All other setsockopt requests * that are for SOL_SOCKET are passed back to the socket layer for its * generic implementation. * * Both of these setsockopt values are candidates for being handled by the * socket layer itself in future, however this requires understanding how * they would interact with all other sockets. */ static int pfp_setsocket_sockopt(sock_lower_handle_t handle, int option_name, const void *optval, socklen_t optlen) { struct bpf_program prog; struct bpf_insn *fcode; struct pfpsock *ps; int error = 0; int size; ps = (struct pfpsock *)handle; switch (option_name) { case SO_ATTACH_FILTER : #ifdef _LP64 if (optlen == sizeof (struct bpf_program32)) { struct bpf_program32 prog32; bcopy(optval, &prog32, sizeof (prog32)); prog.bf_len = prog32.bf_len; prog.bf_insns = (void *)(uint64_t)prog32.bf_insns; } else #endif if (optlen == sizeof (struct bpf_program)) { bcopy(optval, &prog, sizeof (prog)); } else if (optlen != sizeof (struct bpf_program)) { return (EINVAL); } size = prog.bf_len * sizeof (*prog.bf_insns); fcode = kmem_alloc(size, KM_SLEEP); if (ddi_copyin(prog.bf_insns, fcode, size, 0) != 0) { kmem_free(fcode, size); return (EFAULT); } if (bpf_validate(fcode, (int)prog.bf_len)) { rw_enter(&ps->ps_bpflock, RW_WRITER); pfp_release_bpf(ps); ps->ps_bpf.bf_insns = fcode; ps->ps_bpf.bf_len = size; rw_exit(&ps->ps_bpflock); return (0); } kmem_free(fcode, size); error = EINVAL; break; case SO_DETACH_FILTER : pfp_release_bpf(ps); break; default : /* * If sockfs code receives this error in return from the * getsockopt downcall it handles the option locally, if * it can. This implements SO_RCVBUF, etc. */ error = ENOPROTOOPT; break; } return (error); }
/*! \brief Sets the bpf packet filter. \param pWanAdapter Pointer to a WAN_ADAPTER structure. \param FilterCode Pointer to the BPF filtering code that will be associated with this capture or monitoring instance and that will be executed on every incoming packet. \param Length Length, in bytes, of the BPF filter code. \return This function returns TRUE if the filter is set successfully, FALSE if an error occurs or if the filter program is not accepted after a safeness check. This API performs the check in order to avoid unexpected behavior due to buggy or malicious filters, and it rejects non conformant filters. For more information, see the documentation of PacketSetBpf */ BOOLEAN WanPacketSetBpfFilter(PWAN_ADAPTER pWanAdapter, PUCHAR FilterCode, DWORD Length) { PUCHAR NewFilterCode = NULL; DWORD NumberOfInstructions; DWORD Counter; struct bpf_insn *InitializationCode; struct time_conv TimeConv; if ( Length < 0) return FALSE; EnterCriticalSection(&pWanAdapter->CriticalSection); if (Length > 0) { NumberOfInstructions = Length/sizeof(struct bpf_insn); for(Counter = 0; Counter < NumberOfInstructions && ((struct bpf_insn*)FilterCode)[Counter].code != BPF_SEPARATION ; Counter++); if ( Counter != NumberOfInstructions && NumberOfInstructions != Counter + 1 && ((struct bpf_insn*)FilterCode)[Counter].code == BPF_SEPARATION ) { //we need to initialize the TME InitializationCode = &((struct bpf_insn*)FilterCode)[Counter+1]; //FIXME, just an hack, this structure is never used here. TimeConv.start[0].tv_sec = 0; TimeConv.start[0].tv_usec = 0; if ( bpf_filter_init(InitializationCode, &pWanAdapter->MemEx, &pWanAdapter->Tme, &TimeConv) != INIT_OK ) { LeaveCriticalSection(&pWanAdapter->CriticalSection); return FALSE; } } NumberOfInstructions = Counter; if ( bpf_validate((struct bpf_insn*)FilterCode, Counter, pWanAdapter->MemEx.size) == 0) { //filter not validated //FIXME: the machine has been initialized(?), but the operative code is wrong. //we have to reset the machine! //something like: reallocate the mem_ex, and reset the tme_core LeaveCriticalSection(&pWanAdapter->CriticalSection); return FALSE; } NewFilterCode = (PUCHAR)GlobalAlloc( GMEM_FIXED, Counter * sizeof(struct bpf_insn) ); if (NewFilterCode == NULL) { LeaveCriticalSection(&pWanAdapter->CriticalSection); return FALSE; } RtlCopyMemory(NewFilterCode, FilterCode, Counter * sizeof(struct bpf_insn)); } if ( pWanAdapter->FilterCode != NULL ) GlobalFree(pWanAdapter->FilterCode); pWanAdapter->FilterCode = (struct bpf_insn*)NewFilterCode; //we reset all the ring buffer related counters. pWanAdapter->C = 0; pWanAdapter->P = 0; pWanAdapter->Free = pWanAdapter->Size; pWanAdapter->Accepted = 0; pWanAdapter->Dropped = 0; pWanAdapter->Received = 0; pWanAdapter->Nbytes.QuadPart = 0; pWanAdapter->Npackets.QuadPart = 0; LeaveCriticalSection(&pWanAdapter->CriticalSection); return TRUE; }
BOOL PKT_IOControl (DWORD dwContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut) { BOOL bRet = TRUE; PWCHAR bpf_prog; PNDIS_STRING pstrAName; POPEN_INSTANCE pOpenInst = NULL; PUCHAR pTempBuf; ULONG nValue; // if the context is different then return false if (dwContext != PKT_FILE_HANDLE) { SAFE_SET (pdwActualOut, 0); return FALSE; } // if the code is not to open the adapter then there // should be an open instance of the adapter if (dwCode != PIOC_OPEN_ADAPTER && dwCode != PIOC_GET_MACNAME) { // get the open instance handle pOpenInst = g_pDeviceExtension->pOpenInstance; if (pOpenInst == NULL) { return FALSE; } } switch (dwCode) { // open the adapter message case PIOC_OPEN_ADAPTER: // get the adapter NDIS name pstrAName = PKTGetNDISAdapterName ((PWCHAR)pBufIn, dwLenIn); if (pstrAName == NULL) { return FALSE; } // open the adapter if (! PKTOpenAdapter (pstrAName)) { bRet = FALSE; } break; // close the adapter message case PIOC_CLOSE_ADAPTER: bRet = PKTCloseAdapter (pOpenInst); break; // function to set new bpf filter case PIOC_SETF: // free the previous buffer if selected if (pOpenInst->bpfprogram != NULL) { NdisFreeMemory (pOpenInst->bpfprogram, pOpenInst->bpfprogramlen, 0); pOpenInst->bpfprogram = NULL; pOpenInst->bpfprogramlen = 0; } // get the pointer to the new program bpf_prog = (PWCHAR) pBufIn; // before accepting the program we must check that it's valid // otherwise, a bogus program could easily crash the driver pOpenInst->bpfprogramlen = dwLenIn; if (bpf_validate ((struct bpf_insn*)bpf_prog, pOpenInst->bpfprogramlen/sizeof(struct bpf_insn)) == 0) { pOpenInst->bpfprogramlen = 0; pOpenInst->bpfprogram = NULL; return FALSE; // filter not accepted } // allocate the memory to contain the new filter program*/ if (NdisAllocateMemory(&pOpenInst->bpfprogram, pOpenInst->bpfprogramlen, 0, NDIS_ADDR_M1) == NDIS_STATUS_FAILURE) { pOpenInst->bpfprogramlen = 0; pOpenInst->bpfprogram = NULL; return FALSE; } // copy the program in the new buffer NdisMoveMemory (pOpenInst->bpfprogram, bpf_prog, pOpenInst->bpfprogramlen); // reset the buffer that could contain packets that don't match the filter pOpenInst->Bhead = 0; pOpenInst->Btail = 0; pOpenInst->BLastByte= 0; // return the accepted buffer len SAFE_SET(pdwActualOut, pOpenInst->bpfprogramlen); break; // function to set the internal buffer size case PIOC_SET_BUFFER_SIZE: // get the size to allocate nValue = ((PULONG)pBufIn)[0]; // free the old buffer if (pOpenInst->Buffer != NULL) { NdisFreeMemory (pOpenInst->Buffer, pOpenInst->BufSize, 0); } pOpenInst->Buffer = NULL; // allocate the new buffer if (nValue > 0) { NdisAllocateMemory ((PVOID*)&pTempBuf, nValue, 0, NDIS_ADDR_M1); if (pTempBuf == NULL) { pOpenInst->BufSize = 0; return FALSE; } pOpenInst->Buffer = pTempBuf; } pOpenInst->Bhead = 0; pOpenInst->Btail = 0; pOpenInst->BLastByte= 0; pOpenInst->BufSize = (UINT)nValue; SAFE_SET(pdwActualOut, nValue); break; // for sharing the event from the user case PIOC_EVNAME: if (pBufOut == NULL || dwLenOut < 32) { SAFE_SET(pdwActualOut, 0); bRet = FALSE; } else { wcscpy ((PWCHAR)pBufOut, SH_EVENT_NAME); SAFE_SET (pdwActualOut, wcslen (SH_EVENT_NAME)); } break; // set read timeout function case PIOC_SRTIMEOUT: pOpenInst->TimeOut = ((PULONG)pBufIn)[0]; SAFE_SET(pdwActualOut, pOpenInst->TimeOut); break; // resets the adapter instance case PIOC_RESET: bRet = PKTReset (pOpenInst); break; // requests of different type case PIOC_SETOID: case PIOC_QUERYOID: return PKTRequest (pOpenInst, dwCode, pBufIn, dwLenIn, pBufOut, dwLenOut, pdwActualOut); break; // read packets case PIOC_READ_PACKET: return PKTRead (pOpenInst, pBufOut, dwLenOut, pdwActualOut); break; // write packets case PIOC_WRITE_PACKET: return PKTWrite (pOpenInst, pBufIn, dwLenIn, pdwActualOut); break; // read mac name case PIOC_GET_MACNAME: *pdwActualOut = PKTGetMacNameList ((PWCHAR)pBufOut, dwLenOut); break; // minimum number of bytes to copy case PIOC_SMINTOCOPY: pOpenInst->MinToCopy = ((PULONG)pBufIn)[0]; SAFE_SET(pdwActualOut, 0); break; // unknown function code. set out length to 0 and return true default: bRet = FALSE; SAFE_SET(pdwActualOut, 0); break; } return bRet; }
int main(int argc, char **argv) { char *cp; int op; int dflag; char *infile; int Oflag; long snaplen; int dlt; bpf_u_int32 netmask = PCAP_NETMASK_UNKNOWN; char *cmdbuf; pcap_t *pd; struct bpf_program fcode; #ifdef WIN32 if(wsockinit() != 0) return 1; #endif /* WIN32 */ dflag = 1; infile = NULL; Oflag = 1; snaplen = 68; if ((cp = strrchr(argv[0], '/')) != NULL) program_name = cp + 1; else program_name = argv[0]; opterr = 0; while ((op = getopt(argc, argv, "dF:m:Os:")) != -1) { switch (op) { case 'd': ++dflag; break; case 'F': infile = optarg; break; case 'O': Oflag = 0; break; case 'm': { in_addr_t addr; addr = inet_addr(optarg); if (addr == INADDR_NONE) error("invalid netmask %s", optarg); netmask = addr; break; } case 's': { char *end; snaplen = strtol(optarg, &end, 0); if (optarg == end || *end != '\0' || snaplen < 0 || snaplen > 65535) error("invalid snaplen %s", optarg); else if (snaplen == 0) snaplen = 65535; break; } default: usage(); /* NOTREACHED */ } } if (optind >= argc) { usage(); /* NOTREACHED */ } dlt = pcap_datalink_name_to_val(argv[optind]); if (dlt < 0) error("invalid data link type %s", argv[optind]); if (infile) cmdbuf = read_infile(infile); else cmdbuf = copy_argv(&argv[optind+1]); pd = pcap_open_dead(dlt, snaplen); if (pd == NULL) error("Can't open fake pcap_t"); if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) error("%s", pcap_geterr(pd)); if (!bpf_validate(fcode.bf_insns, fcode.bf_len)) warn("Filter doesn't pass validation"); bpf_dump(&fcode, dflag); pcap_close(pd); exit(0); }
int main(int argc, char **argv) { char *cp; int op; #ifndef BDEBUG int dflag; #endif char *infile; int Oflag; long snaplen; char *p; int dlt; int have_fcode = 0; bpf_u_int32 netmask = PCAP_NETMASK_UNKNOWN; char *cmdbuf; pcap_t *pd; struct bpf_program fcode; #ifdef _WIN32 if (pcap_wsockinit() != 0) return 1; #endif /* _WIN32 */ #ifndef BDEBUG dflag = 1; #else /* if optimizer debugging is enabled, output DOT graph * `dflag=4' is equivalent to -dddd to follow -d/-dd/-ddd * convention in tcpdump command line */ dflag = 4; #endif infile = NULL; Oflag = 1; snaplen = 68; if ((cp = strrchr(argv[0], '/')) != NULL) program_name = cp + 1; else program_name = argv[0]; opterr = 0; while ((op = getopt(argc, argv, "dF:m:Os:")) != -1) { switch (op) { case 'd': ++dflag; break; case 'F': infile = optarg; break; case 'O': Oflag = 0; break; case 'm': { bpf_u_int32 addr; switch (inet_pton(AF_INET, optarg, &addr)) { case 0: error("invalid netmask %s", optarg); break; case -1: error("invalid netmask %s: %s", optarg, pcap_strerror(errno)); break; case 1: netmask = addr; break; } break; } case 's': { char *end; snaplen = strtol(optarg, &end, 0); if (optarg == end || *end != '\0' || snaplen < 0 || snaplen > 65535) error("invalid snaplen %s", optarg); else if (snaplen == 0) snaplen = 65535; break; } default: usage(); /* NOTREACHED */ } } if (optind >= argc) { usage(); /* NOTREACHED */ } dlt = pcap_datalink_name_to_val(argv[optind]); if (dlt < 0) { dlt = (int)strtol(argv[optind], &p, 10); if (p == argv[optind] || *p != '\0') error("invalid data link type %s", argv[optind]); } if (infile) cmdbuf = read_infile(infile); else cmdbuf = copy_argv(&argv[optind+1]); pd = pcap_open_dead(dlt, snaplen); if (pd == NULL) error("Can't open fake pcap_t"); if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) error("%s", pcap_geterr(pd)); have_fcode = 1; if (!bpf_validate(fcode.bf_insns, fcode.bf_len)) warn("Filter doesn't pass validation"); #ifdef BDEBUG if (cmdbuf != NULL) { // replace line feed with space for (cp = cmdbuf; *cp != '\0'; ++cp) { if (*cp == '\r' || *cp == '\n') { *cp = ' '; } } // only show machine code if BDEBUG defined, since dflag > 3 printf("machine codes for filter: %s\n", cmdbuf); } else printf("machine codes for empty filter:\n"); #endif bpf_dump(&fcode, dflag); free(cmdbuf); if (have_fcode) pcap_freecode (&fcode); pcap_close(pd); exit(0); }
/* * There are only two special setsockopt's for SOL_SOCKET with PF_PACKET: * SO_ATTACH_FILTER and SO_DETACH_FILTER. * * Both of these setsockopt values are candidates for being handled by the * socket layer itself in future, however this requires understanding how * they would interact with all other sockets. */ static int pfp_setsocket_sockopt(sock_lower_handle_t handle, int option_name, const void *optval, socklen_t optlen) { struct bpf_program prog; struct bpf_insn *fcode; struct pfpsock *ps; struct sock_proto_props sopp; int error = 0; int size; ps = (struct pfpsock *)handle; switch (option_name) { case SO_ATTACH_FILTER : #ifdef _LP64 if (optlen == sizeof (struct bpf_program32)) { struct bpf_program32 prog32; bcopy(optval, &prog32, sizeof (prog32)); prog.bf_len = prog32.bf_len; prog.bf_insns = (void *)(uint64_t)prog32.bf_insns; } else #endif if (optlen == sizeof (struct bpf_program)) { bcopy(optval, &prog, sizeof (prog)); } else if (optlen != sizeof (struct bpf_program)) { return (EINVAL); } if (prog.bf_len > BPF_MAXINSNS) return (EINVAL); size = prog.bf_len * sizeof (*prog.bf_insns); fcode = kmem_alloc(size, KM_SLEEP); if (ddi_copyin(prog.bf_insns, fcode, size, 0) != 0) { kmem_free(fcode, size); return (EFAULT); } if (bpf_validate(fcode, (int)prog.bf_len)) { rw_enter(&ps->ps_bpflock, RW_WRITER); pfp_release_bpf(ps); ps->ps_bpf.bf_insns = fcode; ps->ps_bpf.bf_len = size; rw_exit(&ps->ps_bpflock); return (0); } kmem_free(fcode, size); error = EINVAL; break; case SO_DETACH_FILTER : pfp_release_bpf(ps); break; case SO_RCVBUF : size = *(int32_t *)optval; if (size > sockmod_pfp_rcvbuf_max || size < 0) return (ENOBUFS); sopp.sopp_flags = SOCKOPT_RCVHIWAT; sopp.sopp_rxhiwat = size; ps->ps_upcalls->su_set_proto_props(ps->ps_upper, &sopp); ps->ps_rcvbuf = size; break; default : error = ENOPROTOOPT; break; } return (error); }
int main(void) { #ifndef BPF_JIT_COMPILER u_int i; #endif u_int ret; int sig; #ifdef BPF_VALIDATE int valid; #endif /* Try to catch all signals */ for (sig = SIGHUP; sig <= SIGUSR2; sig++) signal(sig, sig_handler); #ifdef BPF_VALIDATE valid = bpf_validate(pc, nins); if (valid != 0 && invalid != 0) { if (verbose > 1) printf("Validated invalid instruction(s):\t"); if (verbose > 0) printf("FAILED\n"); return (FAILED); } else if (valid == 0 && invalid == 0) { if (verbose > 1) printf("Invalidated valid instruction(s):\t"); if (verbose > 0) printf("FAILED\n"); return (FAILED); } else if (invalid != 0) { if (verbose > 1) printf("Expected and invalidated:\t"); if (verbose > 0) printf("PASSED\n"); return (PASSED); } #endif #ifdef BPF_JIT_COMPILER ret = bpf_compile_and_filter(); #else for (i = 0; i < BPF_NRUNS; i++) ret = bpf_filter(nins != 0 ? pc : NULL, pkt, wirelen, buflen); #endif if (expect_signal != 0) { if (verbose > 1) printf("Expected signal %d but got none:\t", expect_signal); if (verbose > 0) printf("FAILED\n"); return (FAILED); } if (ret != expect) { if (verbose > 1) printf("Expected 0x%x but got 0x%x:\t", expect, ret); if (verbose > 0) printf("FAILED\n"); return (FAILED); } if (verbose > 1) printf("Expected and got 0x%x:\t", ret); if (verbose > 0) printf("PASSED\n"); return (PASSED); }