Exemplo n.º 1
0
/* Initializes pcap capture settings and returns a pcap handle on success, NULL on error */
pcap_t *capture_init(char *capture_source) {
    pcap_t *handle = NULL;
    char errbuf[PCAP_ERRBUF_SIZE] = {0};

#ifdef __APPLE__
    // must disassociate from any current AP.  This is the only way.
    pid_t pid = fork();
    if (!pid) {
        char* argv[] = {"/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport", "-z", NULL};
        execve("/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport", argv, NULL);
    }
    int status;
    waitpid(pid, &status, 0);


    handle = pcap_create(capture_source, errbuf);
    if (handle) {
        pcap_set_snaplen(handle, BUFSIZ);
        pcap_set_timeout(handle, 50);
        pcap_set_rfmon(handle, 1);
        pcap_set_promisc(handle, 1);
        int status = pcap_activate(handle);
        if (status)
            cprintf(CRITICAL, "pcap_activate status %d\n", status);
    }
#else
    handle = pcap_open_live(capture_source, BUFSIZ, 1, 0, errbuf);
#endif
    if (!handle) {
        handle = pcap_open_offline(capture_source, errbuf);
    }

    return handle;
}
Exemplo n.º 2
0
pcap_t *
pcap_open_live_extended(const char *source, int snaplen, int promisc, int to_ms, int rfmon, char *errbuf)
{
    pcap_t *p;
    int status;
    
    p = pcap_create(source, errbuf);
    if (p == NULL)
        return (NULL);
    status = pcap_set_snaplen(p, snaplen);
    if (status < 0)
        goto fail;
    status = pcap_set_promisc(p, promisc);
    if (status < 0)
        goto fail;
    status = pcap_set_timeout(p, to_ms);
    if (status < 0)
        goto fail;
    if(pcap_can_set_rfmon(p) == 1) {
        status = pcap_set_rfmon(p, rfmon);
        if (status < 0)
            goto fail;
    }
    status = pcap_activate(p);
    if (status < 0)
        goto fail;
    return (p);
    
fail:
    snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, pcap_geterr(p));
    pcap_close(p);
    return (NULL);
}
Exemplo n.º 3
0
void capture(char *dev) {
  pcap_t *pcap;
  char errbuf[PCAP_ERRBUF_SIZE];
  struct pcap_pkthdr header;	/* The header that pcap gives us */
  const u_char *packet;		/* The actual packet */

  if(NULL == dev) {
    dev = pcap_lookupdev(errbuf);
    if (dev == NULL) {
      fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
      exit(1);
    }
  }

  pcap = pcap_create(dev, errbuf);
  pcap_set_rfmon(pcap, 1);
  pcap_set_promisc(pcap, 1);
  pcap_set_buffer_size(pcap, 1 * 1024 * 1024);
  pcap_set_timeout(pcap, 1);
  pcap_set_snaplen(pcap, 16384);
  pcap_activate(pcap);    
  if(DLT_IEEE802_11_RADIO == pcap_datalink(pcap)) {
    pcap_loop(pcap, 0, got_packet, 0);
  } else {
    fprintf(stderr, "Could not initialize a IEEE802_11_RADIO packet capture for interface %s\n", dev);
  }
}
Exemplo n.º 4
0
/*
 * Class:     disy_jnipcap_Pcap
 * Method:    setRfmon
 * Signature: (JI)I
 */
JNIEXPORT jint JNICALL
Java_disy_jnipcap_Pcap_setRfmon (JNIEnv *env, jclass jcls, jlong jptr, jint jmon)
{
	pcap_t *p = (pcap_t *) jptr;
	if (p == NULL) return -1;
	return (jint) pcap_set_rfmon (p, (int) jmon);
}
Exemplo n.º 5
0
void Sniffer::set_rfmon(bool rfmon_enabled) {
    #ifndef _WIN32
    if (pcap_can_set_rfmon(get_pcap_handle()) == 1) {
        if (pcap_set_rfmon(get_pcap_handle(), rfmon_enabled)) {
            throw pcap_error(pcap_geterr(get_pcap_handle()));
        }
    }
    #endif
}
Exemplo n.º 6
0
int myPcapCatchAndAnaly() {
    int status=0;
    int header_type;
    char errbuf[PCAP_ERRBUF_SIZE];
    /* openwrt && linux */
    char *dev=(char *)"wlan0";
    /* mac os */
    //test
    // char* dev=(char *)"en0";
    handle=pcap_create(dev,errbuf); //为抓取器打开一个句柄

    if (handle == NULL)  {
        fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
        return 0;
    }

    // 由于在该路由器测试时,发现在该openwrt系统上不支持libpcap设置monitor模式,在激活的时候会产生错误
    // 将采用手动设置并检测网卡是否为monitor模式

    // if(pcap_can_set_rfmon(handle)) {
    //      //查看是否能设置为监控模式
    //     printf("Device %s can be opened in monitor mode\n",dev);
    // }
    // else {
    //     printf("Device %s can't be opened in monitor mode!!!\n",dev);
    // }

    // 若是mac os系统,则可以支持
    // test
    if(pcap_set_rfmon(handle,1)!=0) {
        fprintf(stderr, "Device %s couldn't be opened in monitor mode\n", dev);
        return 0;
    } else {
        printf("Device %s has been opened in monitor mode\n", dev);
    }

    pcap_set_promisc(handle,0);   //不设置混杂模式
    pcap_set_snaplen(handle,65535);   //设置最大捕获包的长度
    status=pcap_activate(handle);   //激活

    if(status!=0) {
        pcap_perror(handle,(char*)"pcap error: ");
        return 0;
    }

    header_type=pcap_datalink(handle);  //返回链路层的类型
    if(header_type!=DLT_IEEE802_11_RADIO) {
        printf("Error: incorrect header type - %d\n",header_type);
        return 0;
    }

    int id = 0;
    pcap_loop(handle, -1, getPacket, (u_char*)&id);

    return 1;
}
Exemplo n.º 7
0
static void prep_pcap_handle(pcap_t *handle) {
    int err;

    err = pcap_set_rfmon(handle, options.rfmon);
    if(err)
        die(0, "DEBUG: pcap handle should not be activated at %s:%d", __FILE__, __LINE__);

    err = pcap_set_promisc(handle, options.promisc);
    if(err)
        die(0, "DEBUG: pcap handle should not be activated at %s:%d", __FILE__, __LINE__);

    err = pcap_set_snaplen(handle, options.snaplen);
    if(err)
        die(0, "DEBUG: pcap handle should not be activated at %s:%d", __FILE__, __LINE__);

    err = pcap_set_timeout(handle, options.read_timeout);
    if(err)
        die(0, "DEBUG: pcap handle should not be activated at %s:%d", __FILE__, __LINE__);

    if(options.buffer_size > 0) {
        err = pcap_set_buffer_size(handle, options.buffer_size);
        if(err)
            die(0, "DEBUG: pcap handle should not be activated at %s:%d", __FILE__, __LINE__);
    }

    if(options.tstamp_type != PCAP_ERROR) {
        err = pcap_set_tstamp_type(handle, options.tstamp_type);
        if(err == PCAP_ERROR_ACTIVATED)
            die(0, "DEBUG: pcap handle should not be activated at %s:%d", __FILE__, __LINE__);
        else if(err == PCAP_ERROR_CANTSET_TSTAMP_TYPE)
            die(0, "pcap_set_tstamp_type(): Device does not support setting the timestamp");
        else if(err == PCAP_WARNING_TSTAMP_TYPE_NOTSUP)
            plog(0, "pcap_set_tstamp_type(): Device does not support specified tstamp type");
    }

    if(options.tstamp_nano) {
        err = pcap_set_tstamp_precision(handle, PCAP_TSTAMP_PRECISION_NANO);
        if(err == PCAP_ERROR_ACTIVATED)
            die(0, "DEBUG: pcap handle should not be activated at %s:%d", __FILE__, __LINE__);
        else if(err == PCAP_ERROR_TSTAMP_PRECISION_NOTSUP)
            die(0, "pcap_set_tstamp_precision(): Device does not support nanosecond precision");
    }

    if(options.linktype != PCAP_ERROR) {
        err = pcap_set_datalink(handle, options.linktype);
        if(err)
            die(0, "pcap_set_datalink(): %s", pcap_geterr(handle));
    }
}
Exemplo n.º 8
0
    static int
epcap_open(EPCAP_STATE *ep)
{
    char errbuf[PCAP_ERRBUF_SIZE];

    if (ep->file) {
        PCAP_ERRBUF(ep->p = pcap_open_offline(ep->file, errbuf));
    } else {
        if (ep->dev == NULL)
            PCAP_ERRBUF(ep->dev = pcap_lookupdev(errbuf));

#ifdef HAVE_PCAP_CREATE
        PCAP_ERRBUF(ep->p = pcap_create(ep->dev, errbuf));
        (void)pcap_set_snaplen(ep->p, ep->snaplen);
        (void)pcap_set_promisc(ep->p, ep->opt & EPCAP_OPT_PROMISC);
        (void)pcap_set_timeout(ep->p, ep->timeout);
        if (ep->bufsz > 0)
            (void)pcap_set_buffer_size(ep->p, ep->bufsz);
        switch (pcap_activate(ep->p)) {
            case 0:
                break;
            case PCAP_WARNING:
            case PCAP_ERROR:
            case PCAP_WARNING_PROMISC_NOTSUP:
            case PCAP_ERROR_NO_SUCH_DEVICE:
            case PCAP_ERROR_PERM_DENIED:
                pcap_perror(ep->p, "pcap_activate: ");
                exit(EXIT_FAILURE);
            default:
                exit(EXIT_FAILURE);
        }
#else
        PCAP_ERRBUF(ep->p = pcap_open_live(ep->dev, ep->snaplen,
                    ep->opt & EPCAP_OPT_PROMISC, ep->timeout, errbuf));
#endif

        /* monitor mode */
#ifdef PCAP_ERROR_RFMON_NOTSUP
        if (pcap_can_set_rfmon(ep->p) == 1)
            (void)pcap_set_rfmon(ep->p, ep->opt & EPCAP_OPT_RFMON);
#endif
    }

    ep->datalink = pcap_datalink(ep->p);

    return 0;
}
Exemplo n.º 9
0
int
epcap_open(EPCAP_STATE *ep)
{
    char errbuf[PCAP_ERRBUF_SIZE];

    if (ep->file) {
        PCAP_ERRBUF(ep->p = pcap_open_offline(ep->file, errbuf));
    } else {
        if (ep->dev == NULL)
            PCAP_ERRBUF(ep->dev = pcap_lookupdev(errbuf));

        PCAP_ERRBUF(ep->p = pcap_open_live(ep->dev, ep->snaplen, ep->promisc, ep->timeout, errbuf));

        /* monitor mode */
        if (pcap_can_set_rfmon(ep->p) == 1)
            (void)pcap_set_rfmon(ep->p, ep->rfmon);
    }

    return (0);
}
Exemplo n.º 10
0
/**
 *  Set up pcap listener for the given interfaces and protocols.
 *  @return a properly configured pcap_t* object for listening for the given protocols - NULL on error
 *  @see pcap_protocols
 */
pcap_t*
create_pcap_listener(const char * dev		///<[in] Device name to listen on
                     ,		     gboolean blocking		///<[in] TRUE if this is a blocking connection
                     ,		     unsigned listenmask	///<[in] Bit mask of protocols to listen for
                     ///< (see @ref pcap_protocols "list of valid bits")
                     ,		     struct bpf_program*prog)	///<[out] Compiled PCAP program
{
    pcap_t*			pcdescr = NULL;
    bpf_u_int32		maskp = 0;
    bpf_u_int32		netp = 0;
    char			errbuf[PCAP_ERRBUF_SIZE];
    char *			expr = NULL;
    int			filterlen = 1;
    unsigned		j;
    int			cnt=0;
    int			rc;
    const char ORWORD [] = " or ";
    gboolean		need_promisc = FALSE;

    BINDDEBUG(pcap_t);
//	setbuf(stdout, NULL);
    setvbuf(stdout, NULL, _IONBF, 0);
    errbuf[0] = '\0';

    // Search the list of valid bits so we can construct the libpcap filter
    // for the given set of protocols on the fly...
    // On this pass we just compute the amount of memory we'll need...
    for (j = 0, cnt = 0; j < DIMOF(filterinfo); ++j) {
        if (listenmask & filterinfo[j].filterbit) {
            ++cnt;
            if (cnt > 1) {
                filterlen += sizeof(ORWORD);
            }
            filterlen += strlen(filterinfo[j].filter);
        }
    }

    if (filterlen < 2) {
        g_warning("Constructed filter is too short - invalid mask argument.");
        return NULL;
    }
    if (NULL == (expr = malloc(filterlen))) {
        g_error("Out of memory!");
        return NULL;
    }
    // Same song, different verse...
    // This time around, we construct the filter
    expr[0] = '\0';
    for (j = 0, cnt = 0; j < DIMOF(filterinfo); ++j) {
        if (listenmask & filterinfo[j].filterbit) {
            ++cnt;
            if (cnt > 1) {
                g_strlcat(expr, ORWORD, filterlen);
            }
            g_strlcat(expr, filterinfo[j].filter, filterlen);
        }
    }
    if (pcap_lookupnet(dev, &netp, &maskp, errbuf) != 0) {
        // This is not a problem for non-IPv4 protocols...
        // It just looks up the ipv4 address - which we mostly don't care about.
        g_info("%s.%d: pcap_lookupnet(\"%s\") failed: [%s]"
               ,	__FUNCTION__, __LINE__, dev, errbuf);
    }

    if (NULL == (pcdescr = pcap_create(dev, errbuf))) {
        g_warning("pcap_create failed: [%s]", errbuf);
        goto oopsie;
    }
    //pcap_set_promisc(pcdescr, FALSE);
    for (j = 0; j < DIMOF(filterinfo); ++j) {
        if (listenmask & filterinfo[j].filterbit) {
            const char * addrstring = filterinfo[j].mcastaddr;
            if (addrstring && !_enable_mcast_address(addrstring, dev, TRUE)) {
                need_promisc = TRUE;
            }
        }
    }
    pcap_set_promisc(pcdescr, need_promisc);
#ifdef HAVE_PCAP_SET_RFMON
    pcap_set_rfmon(pcdescr, FALSE);
#endif
    pcap_setdirection(pcdescr, PCAP_D_IN);
    // Weird bug - returns -3 and doesn't show an error message...
    // And pcap_getnonblock also returns -3... Neither should happen AFAIK...
    errbuf[0] = '\0';
    if ((rc = pcap_setnonblock(pcdescr, !blocking, errbuf)) < 0 && errbuf[0] != '\0') {
        g_warning("pcap_setnonblock(%d) failed: [%s] [rc=%d]", !blocking, errbuf, rc);
        g_warning("Have no idea why this happens - current blocking state is: %d."
                  ,	pcap_getnonblock(pcdescr, errbuf));
    }
    pcap_set_snaplen(pcdescr, 1500);
    /// @todo deal with pcap_set_timeout() call here.
    if (blocking) {
        pcap_set_timeout(pcdescr, 240*1000);
    } else {
        pcap_set_timeout(pcdescr, 1);
    }
    //pcap_set_buffer_size(pcdescr, 1500);

    if (pcap_activate(pcdescr) != 0) {
        g_warning("pcap_activate failed: [%s]", pcap_geterr(pcdescr));
        goto oopsie;
    }
    if (pcap_compile(pcdescr, prog, expr, FALSE, maskp) < 0) {
        g_warning("pcap_compile of [%s] failed: [%s]", expr, pcap_geterr(pcdescr));
        goto oopsie;
    }
    if (pcap_setfilter(pcdescr, prog) < 0) {
        g_warning("pcap_setfilter on [%s] failed: [%s]", expr, pcap_geterr(pcdescr));
        goto oopsie;
    }
    DEBUGMSG1("Compile of [%s] worked!", expr);
    free(expr);
    expr = NULL;
    return(pcdescr);

oopsie:	// Some kind of failure - free things up and return NULL

    g_warning("%s.%d: Could not set up PCAP on %s"
              ,	__FUNCTION__, __LINE__, dev);
    if (expr) {
        free(expr);
        expr = NULL;
    }
    if (pcdescr) {
        close_pcap_listener(pcdescr, dev, listenmask);
        pcdescr = NULL;
    }
    return NULL;
}
Exemplo n.º 11
0
int
main(int argc, char **argv)
{
	register int op;
	register char *cp, *device;
	int dorfmon, dopromisc, snaplen, useactivate, bufsize;
	char ebuf[PCAP_ERRBUF_SIZE];
	pcap_t *pd;
	int status = 0;

	device = NULL;
	dorfmon = 0;
	dopromisc = 0;
	snaplen = MAXIMUM_SNAPLEN;
	bufsize = 0;
	useactivate = 0;
	if ((cp = strrchr(argv[0], '/')) != NULL)
		program_name = cp + 1;
	else
		program_name = argv[0];

	opterr = 0;
	while ((op = getopt(argc, argv, "i:Ips:aB:")) != -1) {
		switch (op) {

		case 'i':
			device = optarg;
			break;

		case 'I':
			dorfmon = 1;
			useactivate = 1;	/* required for rfmon */
			break;

		case 'p':
			dopromisc = 1;
			break;

		case 's': {
			char *end;

			snaplen = strtol(optarg, &end, 0);
			if (optarg == end || *end != '\0'
			    || snaplen < 0 || snaplen > MAXIMUM_SNAPLEN)
				error("invalid snaplen %s", optarg);
			else if (snaplen == 0)
				snaplen = MAXIMUM_SNAPLEN;
			break;
		}

		case 'B':
			bufsize = atoi(optarg)*1024;
			if (bufsize <= 0)
				error("invalid packet buffer size %s", optarg);
			useactivate = 1;	/* required for bufsize */
			break;

		case 'a':
			useactivate = 1;
			break;

		default:
			usage();
			/* NOTREACHED */
		}
	}

	if (useactivate) {
		pd = pcap_create(device, ebuf);
		if (pd == NULL)
			error("%s", ebuf);
		status = pcap_set_snaplen(pd, snaplen);
		if (status != 0)
			error("%s: pcap_set_snaplen failed: %s",
			    device, pcap_statustostr(status));
		if (dopromisc) {
			status = pcap_set_promisc(pd, 1);
			if (status != 0)
				error("%s: pcap_set_promisc failed: %s",
				    device, pcap_statustostr(status));
		}
		if (dorfmon) {
			status = pcap_set_rfmon(pd, 1);
			if (status != 0)
				error("%s: pcap_set_rfmon failed: %s",
				    device, pcap_statustostr(status));
		}
		status = pcap_set_timeout(pd, 1000);
		if (status != 0)
			error("%s: pcap_set_timeout failed: %s",
			    device, pcap_statustostr(status));
		if (bufsize != 0) {
			status = pcap_set_buffer_size(pd, bufsize);
			if (status != 0)
				error("%s: pcap_set_buffer_size failed: %s",
				    device, pcap_statustostr(status));
		}
		status = pcap_activate(pd);
		if (status < 0) {
			/*
			 * pcap_activate() failed.
			 */
			error("%s: %s\n(%s)", device,
			    pcap_statustostr(status), pcap_geterr(pd));
		} else if (status > 0) {
			/*
			 * pcap_activate() succeeded, but it's warning us
			 * of a problem it had.
			 */
			warning("%s: %s\n(%s)", device,
			    pcap_statustostr(status), pcap_geterr(pd));
		}
	} else {
		*ebuf = '\0';
		pd = pcap_open_live(device, 65535, 0, 1000, ebuf);
		if (pd == NULL)
			error("%s", ebuf);
		else if (*ebuf)
			warning("%s", ebuf);
	}
	pcap_close(pd);
	exit(status < 0 ? 1 : 0);
}
Exemplo n.º 12
0
int
main (int argc, char *argv[])
{
	char *iface;
	pcap_t *pcap_res;
	int exitno, isrfmon;
	char errbuf[PCAP_ERRBUF_SIZE];

	exitno = EXIT_SUCCESS;
	pcap_res = NULL;

	if ( argc < 2 ){
		fprintf (stdout, "Usage: %s <INTERFACE>\n\nCheck if an INTERFACE supports a monitor mode (rfmon).\n", argv[0]);
		exitno = 2;
		goto cleanup;
	}

	iface = argv[1];

	pcap_res = pcap_create (iface, errbuf);

	if ( pcap_res == NULL ){
		fprintf (stderr, "%s: cannot open interface for a packet capture: %s\n", argv[0], errbuf);
		exitno = 2;
		goto cleanup;
	}

	isrfmon = pcap_can_set_rfmon (pcap_res);

	if ( isrfmon == 0 ){
		fprintf (stderr, "not supported\n");
		exitno = 1;
		goto cleanup;
	} else if ( isrfmon == 1 ){
		// Attempt to activate a packet capture	
		// ...
	} else {
		fprintf (stderr, "%s: cannot obtain information about rfmon support: %s\n", argv[0], pcap_geterr (pcap_res));
		exitno = 2;
		goto cleanup;
	}

	isrfmon = pcap_set_rfmon (pcap_res, 1);

	if ( isrfmon != 0 ){
		fprintf (stderr, "%s: cannot set an interface to monitor mode: %s\n", argv[0], pcap_geterr (pcap_res));
		exitno = 2;
		goto cleanup;
	}

	isrfmon = pcap_activate (pcap_res);

	if ( isrfmon == PCAP_ERROR_RFMON_NOTSUP ){
		fprintf (stderr, "not supported\n");
		exitno = 1;
	} else if ( isrfmon == 0 ){
		fprintf (stderr, "supported\n");
		exitno = 0;
	} else {
		fprintf (stderr, "%s: cannot activate a packet capture: %s\n", argv[0], pcap_geterr (pcap_res));
		exitno = 2;
	}

cleanup:
	if ( pcap_res != NULL )
		pcap_close (pcap_res);

	return exitno;
}
Exemplo n.º 13
0
    static ERL_NIF_TERM
nif_pcap_open_live(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    ErlNifBinary device = {0};
    int snaplen = 0;
    int promisc = 0;
    int to_ms = 0;
    int buffer_size = 0;
    int rfmon = 0;
    char errbuf[PCAP_ERRBUF_SIZE] = {0};

    EWPCAP_STATE *ep = NULL;
    ERL_NIF_TERM res = {0};
    ERL_NIF_TERM ref = {0};


    if (!enif_inspect_iolist_as_binary(env, argv[0], &device))
        return enif_make_badarg(env);

    if (!enif_get_int(env, argv[1], &snaplen))
        return enif_make_badarg(env);

    if (!enif_get_int(env, argv[2], &promisc))
        return enif_make_badarg(env);

    if (!enif_get_int(env, argv[3], &to_ms))
        return enif_make_badarg(env);

    if (!enif_get_int(env, argv[4], &buffer_size))
        return enif_make_badarg(env);

    if (!enif_get_int(env, argv[5], &rfmon))
        return enif_make_badarg(env);

    /* NULL terminate the device name */
    if (device.size > 0) {
        if (!enif_realloc_binary(&device, device.size+1))
            return enif_make_tuple2(env, atom_error, atom_enomem);

        device.data[device.size-1] = '\0';
    }

    ep = enif_alloc_resource(EWPCAP_RESOURCE, sizeof(EWPCAP_STATE));

    if (ep == NULL)
        return enif_make_tuple2(env, atom_error, atom_enomem);

    /* "any" is a Linux only virtual dev */
    ep->p = pcap_create((device.size == 0 ? "any" : (char *)device.data),
            errbuf);

    if (ep->p == NULL)
        return enif_make_tuple2(env,
                atom_error,
                enif_make_string(env, errbuf, ERL_NIF_LATIN1));

    /* Set the snaplen */
    (void)pcap_set_snaplen(ep->p, snaplen);

    /* Set promiscuous mode */
    (void)pcap_set_promisc(ep->p, promisc);

    /* Set timeout */
    (void)pcap_set_timeout(ep->p, to_ms);

    /* Set buffer size */
    if (buffer_size > 0)
        (void)pcap_set_buffer_size(ep->p, buffer_size);

    /* Set monitor mode */
    if (pcap_can_set_rfmon(ep->p) == 1)
        (void)pcap_set_rfmon(ep->p, rfmon);

    /* Return failure on error and warnings */
    if (pcap_activate(ep->p) != 0) {
        pcap_close(ep->p);
        return enif_make_tuple2(env,
                atom_error,
                enif_make_string(env, pcap_geterr(ep->p), ERL_NIF_LATIN1));
    }

    ep->datalink = pcap_datalink(ep->p);
    (void)enif_self(env, &ep->pid);

    ep->term_env = enif_alloc_env();
    if (ep->term_env == NULL) {
        pcap_close(ep->p);
        return enif_make_tuple2(env, atom_error, atom_enomem);
    }

    ep->ref = enif_make_ref(ep->term_env);
    ref = enif_make_copy(env, ep->ref);

    res = enif_make_resource(env, ep);
    enif_release_resource(ep);

    return enif_make_tuple2(env,
            atom_ok,
            enif_make_tuple3(env,
                atom_ewpcap_resource,
                ref,
                res));
}
Exemplo n.º 14
0
static ulink_recv_t *ulink_recv_open(const char *netdev)
{
	int err;
    ulink_recv_t *t = NULL;

    if (getenv("debug") != NULL)
    {
        debug = 1;
    }
    
    t = (ulink_recv_t *)malloc(sizeof(ulink_recv_t));
    memset(t, 0, sizeof(ulink_recv_t));

    /* init the pcap */
    {
        char errbuf[PCAP_ERRBUF_SIZE];
        t->pcap_handle = pcap_create(netdev, errbuf);
        if (NULL == t->pcap_handle)
        {
            LOG_("pcap_open_live failed. %s", errbuf);
            free(t);
            return NULL;
        }

        err = pcap_set_snaplen(t->pcap_handle, 128);
        if (err)
        {
            LOG_("pcap_set_snaplen failed: %s", pcap_statustostr(err));
            pcap_close(t->pcap_handle);
            free(t);
            return NULL;
        }

        err = pcap_set_rfmon(t->pcap_handle, 1);
        if (err)
        {
            LOG_("pcap_set_rfmon failed: %s", pcap_statustostr(err));
            pcap_close(t->pcap_handle);
            free(t);
            return NULL;
        }


        err = pcap_set_timeout(t->pcap_handle, CHANNEL_SCAN_TIME);
        if (err)
        {
            LOG_("pcap_set_timeout failed: %s", pcap_statustostr(err));
            pcap_close(t->pcap_handle);
            free(t);
            return NULL;
        }

        err = pcap_activate(t->pcap_handle);
        if (err)
        {
            LOG_("pcap_activate failed: %s", pcap_statustostr(err));
            pcap_close(t->pcap_handle);
            free(t);
            return NULL;
        }

        /* filter */
        err = pcap_compile(t->pcap_handle, &t->bpf, "ether multicast and type data subtype qos-data or subtype data", 1, 0);
        if (err)
        {
            LOG_("pcap_compile failed: %s", pcap_geterr(t->pcap_handle));
            pcap_close(t->pcap_handle);
            free(t);
            return NULL;
        }


        err = pcap_setfilter(t->pcap_handle, &t->bpf);
        if (err)
        {
            LOG_("pcap_setfilter failed: %s", pcap_statustostr(err));
            pcap_freecode(&t->bpf);
            pcap_close(t->pcap_handle);
            free(t);
            return NULL;
        }

    }
    
	return t;
}
Exemplo n.º 15
0
int
main (int argc, char *argv[])
{
	struct pollfd *poll_fd;
	struct config etherpoke_conf;
	struct config_filter *filter_iter;
	struct session_data *pcap_session;
	struct option_data opt;
	char conf_errbuff[CONF_ERRBUF_SIZE];
	char pcap_errbuff[PCAP_ERRBUF_SIZE];
	struct pathname path_config;
	struct sigaction sa;
#ifdef DBG_AVG_LOOP_SPEED
	clock_t clock_start;
	double clock_avg;
#endif
	pid_t pid;
	int i, c, j, rval, syslog_flags, opt_index, filter_cnt, sock, poll_len;
	struct option opt_long[] = {
		{ "", no_argument, NULL, '4' },
		{ "", no_argument, NULL, '6' },
		{ "hostname", required_argument, NULL, 't' },
		{ "daemon", no_argument, NULL, 'd' },
		{ "accept-max", required_argument, NULL, 'm' },
		{ "verbose", no_argument, NULL, 'V' },
		{ "help", no_argument, NULL, 'h' },
		{ "version", no_argument, NULL, 'v' },
		{ NULL, 0, NULL, 0 }
	};

	sock = -1;
	poll_fd = NULL;
	pcap_session = NULL;
	exitno = EXIT_SUCCESS;
	syslog_flags = LOG_PID | LOG_PERROR;
#ifdef DBG_AVG_LOOP_SPEED
	clock_avg = 0;
#endif

	memset (&opt, 0, sizeof (struct option_data));

	opt.accept_max = ACCEPT_MAX;
	opt.ip_version = AF_UNSPEC;

	memset (&path_config, 0, sizeof (struct pathname));
	memset (&etherpoke_conf, 0, sizeof (struct config));

	while ( (c = getopt_long (argc, argv, "46t:dm:Vhv", opt_long, &opt_index)) != -1 ){
		switch ( c ){
			case 'd':
				opt.daemon = 1;
				break;

			case 't':
				rval = hostformat_parse (optarg, opt.hostname, opt.port);

				if ( rval == -1 || strlen (opt.hostname) == 0 || strlen (opt.port) == 0 ){
					fprintf (stderr, "%s: invalid hostname format (expects HOSTNAME:PORT)\n", argv[0]);
					exitno = EXIT_FAILURE;
					goto cleanup;
				}

				opt.tcp_event = 1;
				break;

			case '4':
				opt.ip_version = AF_INET;
				break;

			case '6':
				opt.ip_version = AF_INET6;
				break;

			case 'm':
				rval = sscanf (optarg, "%u", &(opt.accept_max));

				if ( rval < 1 || opt.accept_max == 0 ){
					fprintf (stderr, "%s: invalid number for maximum connections\n", argv[0]);
					exitno = EXIT_FAILURE;
					goto cleanup;
				}
				break;

			case 'V':
				opt.verbose = 1;
				break;

			case 'h':
				etherpoke_help (argv[0]);
				exitno = EXIT_SUCCESS;
				goto cleanup;

			case 'v':
				etherpoke_version (argv[0]);
				exitno = EXIT_SUCCESS;
				goto cleanup;

			default:
				etherpoke_help (argv[0]);
				exitno = EXIT_FAILURE;
				goto cleanup;
		}
	}

	// Check if there are some non-option arguments, these are treated as paths
	// to configuration files.
	if ( (argc - optind) == 0 ){
		fprintf (stderr, "%s: configuration file not specified. Use '--help' to see usage information.\n", argv[0]);
		exitno = EXIT_FAILURE;
		goto cleanup;
	}

	// Change working directory to match the dirname of the config file.
	rval = path_split (argv[optind], &path_config);

	if ( rval != 0 ){
		fprintf (stderr, "%s: cannot split path to configuration file.\n", argv[0]);
		exitno = EXIT_FAILURE;
		goto cleanup;
	}

	rval = chdir (path_config.dir);

	if ( rval == -1 ){
		fprintf (stderr, "%s: cannot set working directory to '%s': %s\n", argv[0], path_config.dir, strerror (errno));
		exitno = EXIT_FAILURE;
		goto cleanup;
	}

	//
	// Load configuration file
	//
	filter_cnt = config_load (&etherpoke_conf, path_config.base, conf_errbuff);

	if ( filter_cnt == -1 ){
		fprintf (stderr, "%s: cannot load configuration file '%s': %s\n", argv[0], argv[optind], conf_errbuff);
		exitno = EXIT_FAILURE;
		goto cleanup;
	} else	if ( filter_cnt == 0 ){
		fprintf (stderr, "%s: nothing to do, no filters defined.\n", argv[0]);
		exitno = EXIT_FAILURE;
		goto cleanup;
	}

	// Allocate enough memory for filters (+1 means that we are also allocating
	// space for listening socket).
	// NOTE: always allocate space for listening socket here, to move this
	// allocation inside the block below (where listening socket is actually
	// allocated) is not a good idea as more complex condition would have to be
	// used inside the main loop.
	poll_len = filter_cnt + 1;

	if ( opt.tcp_event ){
		struct addrinfo *host_addr, addr_hint;
		int opt_val;

		// Increase poll size to accommodate socket descriptors for clients.
		poll_len += opt.accept_max;
		host_addr = NULL;

		memset (&addr_hint, 0, sizeof (struct addrinfo));

		// Setup addrinfo hints
		addr_hint.ai_family = opt.ip_version;
		addr_hint.ai_socktype = SOCK_STREAM;
		addr_hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV;

		rval = getaddrinfo (opt.hostname, opt.port, &addr_hint, &host_addr);

		if ( rval != 0 ){
			fprintf (stderr, "%s: hostname resolve failed: %s\n", argv[0], gai_strerror (rval));
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		sock = socket (host_addr->ai_family, host_addr->ai_socktype | SOCK_NONBLOCK, host_addr->ai_protocol);

		if ( sock == -1 ){
			freeaddrinfo (host_addr);
			fprintf (stderr, "%s: cannot create socket: %s\n", argv[0], strerror (errno));
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		opt_val = 1;

		if ( setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof (opt_val)) == -1 ){
			freeaddrinfo (host_addr);
			fprintf (stderr, "%s: cannot set socket options: %s\n", argv[0], strerror (errno));
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		rval = bind (sock, (struct sockaddr*) host_addr->ai_addr, host_addr->ai_addrlen);

		if ( rval == -1 ){
			freeaddrinfo (host_addr);
			fprintf (stderr, "%s: cannot bind to address: %s\n", argv[0], strerror (errno));
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		rval = listen (sock, LISTEN_QUEUE_LEN);

		if ( rval == -1 ){
			freeaddrinfo (host_addr);
			fprintf (stderr, "%s: %s\n", argv[0], strerror (errno));
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		freeaddrinfo (host_addr);
	}

	pcap_session = (struct session_data*) calloc (filter_cnt, sizeof (struct session_data));

	if ( pcap_session == NULL ){
		fprintf (stderr, "%s: cannot allocate memory: %s\n", argv[0], strerror (errno));
		exitno = EXIT_FAILURE;
		goto cleanup;
	}

	for ( i = 0, filter_iter = etherpoke_conf.head; filter_iter != NULL; i++, filter_iter = filter_iter->next ){
		int link_type;

		session_data_init (&(pcap_session[i]));

		pcap_session[i].timeout = filter_iter->session_timeout;
		pcap_session[i].evt_mask = filter_iter->notify;

		pcap_session[i].filter_name = strdup (filter_iter->name);

		if ( pcap_session[i].filter_name == NULL ){
			fprintf (stderr, "%s: cannot allocate memory: %s\n", argv[0], strerror (errno));
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		if ( filter_iter->notify & NOTIFY_EXEC ){

			if ( filter_iter->session_begin != NULL ){
				rval = wordexp (filter_iter->session_begin, &(pcap_session[i].evt_cmd_beg), WORDEXP_FLAGS);

				if ( rval != 0 )
					goto filter_error;
			}

			if ( filter_iter->session_error != NULL ){
				rval = wordexp (filter_iter->session_error, &(pcap_session[i].evt_cmd_err), WORDEXP_FLAGS);

				if ( rval != 0 )
					goto filter_error;
			}

			if ( filter_iter->session_end != NULL ){
				rval = wordexp (filter_iter->session_end, &(pcap_session[i].evt_cmd_end), WORDEXP_FLAGS);

				if ( rval != 0 )
					goto filter_error;
			}

filter_error:
			switch ( rval ){
				case WRDE_SYNTAX:
					fprintf (stderr, "%s: invalid event hook in '%s': syntax error\n", argv[0], filter_iter->name);
					exitno = EXIT_FAILURE;
					goto cleanup;

				case WRDE_BADCHAR:
					fprintf (stderr, "%s: invalid event hook in '%s': bad character\n", argv[0], filter_iter->name);
					exitno = EXIT_FAILURE;
					goto cleanup;

				case WRDE_BADVAL:
					fprintf (stderr, "%s: invalid event hook in '%s': referencing undefined variable\n", argv[0], filter_iter->name);
					exitno = EXIT_FAILURE;
					goto cleanup;

				case WRDE_NOSPACE:
					fprintf (stderr, "%s: cannot expand event hook string in '%s': out of memory\n", argv[0], filter_iter->name);
					exitno = EXIT_FAILURE;
					goto cleanup;
			}
		}

		pcap_session[i].handle = pcap_create (filter_iter->interface, pcap_errbuff);

		if ( pcap_session[i].handle == NULL ){
			fprintf (stderr, "%s: cannot start packet capture: %s\n", argv[0], pcap_errbuff);
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		rval = pcap_set_rfmon (pcap_session[i].handle, filter_iter->rfmon);

		if ( rval != 0 ){
			fprintf (stderr, "%s: cannot enable monitor mode on interface '%s': %s\n", argv[0], filter_iter->interface, pcap_geterr (pcap_session[i].handle));
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		rval = pcap_set_promisc (pcap_session[i].handle, !(filter_iter->rfmon));

		if ( rval != 0 ){
			fprintf (stderr, "%s: cannot enable promiscuous mode on interface '%s'\n", argv[0], filter_iter->interface);
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		rval = pcap_set_timeout (pcap_session[i].handle, SELECT_TIMEOUT_MS);

		if ( rval != 0 ){
			fprintf (stderr, "%s: cannot set read timeout on interface '%s': %s\n", argv[0], filter_iter->interface, pcap_geterr (pcap_session[i].handle));
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		rval = pcap_setnonblock (pcap_session[i].handle, 1, pcap_errbuff);

		if ( rval == -1 ){
			fprintf (stderr, "%s: cannot set nonblock mode on packet capture resource: %s\n", argv[0], pcap_errbuff);
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		rval = pcap_activate (pcap_session[i].handle);

		if ( rval != 0 ){
			fprintf (stderr, "%s: cannot activate packet capture on interface '%s': %s\n", argv[0], filter_iter->interface, pcap_geterr (pcap_session[i].handle));
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		// Set link-layer type from configuration file.
		if ( filter_iter->link_type != NULL ){
			link_type = pcap_datalink_name_to_val (filter_iter->link_type);

			if ( link_type == -1 ){
				fprintf (stderr, "%s: cannot convert link-layer type '%s': unknown link-layer type name\n", argv[0], filter_iter->link_type);
				exitno = EXIT_FAILURE;
				goto cleanup;
			}
		} else {
			// If no link-layer type is specified in the configuration file,
			// use default value. At this point I am sticking with DLTs used by
			// wireshark on hardware I have available. Different values may
			// apply to different hardware/driver, therefore more research time
			// should be put into finding 'best' values.
			// More information: http://www.tcpdump.org/linktypes.html
			if ( filter_iter->rfmon ){
				link_type = DLT_IEEE802_11_RADIO;
			} else {
				link_type = DLT_EN10MB;
			}
		}

		rval = pcap_set_datalink (pcap_session[i].handle, link_type);

		if ( rval == -1 ){
			fprintf (stderr, "%s: cannot set data-link type: %s\n", argv[0], pcap_geterr (pcap_session[i].handle));
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		if ( filter_iter->match != NULL ){
			struct bpf_program bpf_prog;

			rval = pcap_compile (pcap_session[i].handle, &bpf_prog, filter_iter->match, 0, PCAP_NETMASK_UNKNOWN);

			if ( rval == -1 ){
				fprintf (stderr, "%s: cannot compile the filter '%s' match rule: %s\n", argv[0], filter_iter->name, pcap_geterr (pcap_session[i].handle));
				exitno = EXIT_FAILURE;
				goto cleanup;
			}

			rval = pcap_setfilter (pcap_session[i].handle, &bpf_prog);

			if ( rval == -1 ){
				fprintf (stderr, "%s: cannot apply the filter '%s' on interface '%s': %s\n", argv[0], filter_iter->name, filter_iter->interface, pcap_geterr (pcap_session[i].handle));
				exitno = EXIT_FAILURE;
				goto cleanup;
			}

			pcap_freecode (&bpf_prog);
		}

		pcap_session[i].fd = pcap_get_selectable_fd (pcap_session[i].handle);

		if ( pcap_session[i].fd == -1 ){
			fprintf (stderr, "%s: cannot obtain file descriptor for packet capture interface '%s'\n", argv[0], filter_iter->interface);
			exitno = EXIT_FAILURE;
			goto cleanup;
		}
	}

	// We no longer need data stored in config structure. All neccessary data
	// were moved into session_data structure.
	config_unload (&etherpoke_conf);

	poll_fd = (struct pollfd*) malloc (sizeof (struct pollfd) * poll_len);

	if ( poll_fd == NULL ){
		fprintf (stderr, "%s: cannot allocate memory: %s\n", argv[0], strerror (errno));
		exitno = EXIT_FAILURE;
		goto cleanup;
	}

	// Populate poll structure...
	for ( i = 0; i < poll_len; i++ ){
		// ... with pcap file descriptors...
		if ( i < filter_cnt )
			poll_fd[i].fd = pcap_session[i].fd;
		// ... listening socket...
		else if ( i == filter_cnt )
			poll_fd[i].fd = sock;
		// ... invalid file descriptors (will be ignored by poll(2)), in space reserved for client sockets...
		else
			poll_fd[i].fd = -1;

		poll_fd[i].events = POLLIN | POLLERR;
		poll_fd[i].revents = 0;
	}

	//
	// Setup signal handler
	//
	sa.sa_handler = etherpoke_sigdie;
	sigemptyset (&(sa.sa_mask));
	sa.sa_flags = 0;

	rval = 0;
	rval &= sigaction (SIGINT, &sa, NULL);
	rval &= sigaction (SIGQUIT, &sa, NULL);
	rval &= sigaction (SIGTERM, &sa, NULL);

	sa.sa_handler = SIG_IGN;
	sigemptyset (&(sa.sa_mask));
	sa.sa_flags = 0;

	rval &= sigaction (SIGCHLD, &sa, NULL);

	if ( rval != 0 ){
		fprintf (stderr, "%s: cannot setup signal handler: %s\n", argv[0], strerror (errno));
		exitno = EXIT_FAILURE;
		goto cleanup;
	}

	//
	// Daemonize the process if the flag was set
	//
	if ( opt.daemon == 1 ){
		pid = fork ();

		if ( pid > 0 ){
			exitno = EXIT_SUCCESS;
			goto cleanup;
		} else if ( pid == -1 ){
			fprintf (stderr, "%s: cannot daemonize the process (fork failed).\n", argv[0]);
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		if ( setsid () == -1 ){
			fprintf (stderr, "%s: cannot daemonize the process (setsid failed).\n", argv[0]);
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

		umask (0);

		freopen ("/dev/null", "r", stdin);
		freopen ("/dev/null", "w", stdout);
		freopen ("/dev/null", "w", stderr);
		syslog_flags = LOG_PID;
	}

	openlog ("etherpoke", syslog_flags, LOG_DAEMON);

	syslog (LOG_INFO, "Etherpoke started (loaded filters: %u)", filter_cnt);

	if ( opt.tcp_event )
		syslog (LOG_INFO, "Event notifications available via %s:%s (ACCEPT_MAX: %u)", opt.hostname, opt.port, opt.accept_max);

	//
	// Main loop
	//
	main_loop = 1;

	while ( main_loop ){
		const u_char *pkt_data;
		struct pcap_pkthdr *pkt_header;
		time_t current_time;

		errno = 0;
		rval = poll (poll_fd, poll_len, SELECT_TIMEOUT_MS);

		if ( rval == -1 ){
			if ( errno == EINTR )
				continue;

			syslog (LOG_ERR, "poll(2) failed: %s", strerror (errno));
			exitno = EXIT_FAILURE;
			goto cleanup;
		}

#ifdef DBG_AVG_LOOP_SPEED
		clock_start = clock ();
#endif

		// Accept incoming connection
		if ( poll_fd[filter_cnt].revents & POLLIN ){
			int sock_new;

			sock_new = accept (sock, NULL, NULL);

			if ( sock_new == -1 ){
				syslog (LOG_ERR, "cannot accept new connection: %s", strerror (errno));
				exitno = EXIT_FAILURE;
				goto cleanup;
			}

			// Find unused place in the poll array
			for ( j = (filter_cnt + 1); j < poll_len; j++ ){
				if ( poll_fd[j].fd == -1 ){
					poll_fd[j].fd = sock_new;
					sock_new = -1;
					break;
				}
			}

			if ( sock_new != -1 ){
				if ( opt.verbose )
					syslog (LOG_INFO, "Client refused: too many concurrent connections");
				close (sock_new);
			} else {
				if ( opt.verbose )
					syslog (LOG_INFO, "Client connected...");
			}
		}

		// Take care of incoming client data.  At this point only shutdown and
		// close is handled, no other input is expected from the clients.
		for ( i = (filter_cnt + 1); i < poll_len; i++ ){
			if ( poll_fd[i].revents & POLLIN ){
				char nok[128];

				errno = 0;
				rval = recv (poll_fd[i].fd, nok, sizeof (nok), MSG_DONTWAIT);

				if ( rval <= 0 && (errno != EAGAIN && errno != EWOULDBLOCK) ){
					if ( opt.verbose )
						syslog (LOG_INFO, "Client disconnected...");
					close (poll_fd[i].fd);
					poll_fd[i].fd = -1;
				}
			}
		}

		time (&current_time);

		// Handle changes on pcap file descriptors
		for ( i = 0; i < filter_cnt; i++ ){
			wordexp_t *cmd_exp;
			const char *evt_str;

			// Handle incoming packet
			if ( (poll_fd[i].revents & POLLIN) || (poll_fd[i].revents & POLLERR) ){
				rval = pcap_next_ex (pcap_session[i].handle, &pkt_header, &pkt_data);

				if ( rval == 1 ){
					if ( pcap_session[i].evt.ts == 0 )
						pcap_session[i].evt.type = SE_BEG;

					pcap_session[i].evt.ts = pkt_header->ts.tv_sec;
				} else if ( rval < 0 ){
					pcap_session[i].evt.type = SE_ERR;
				}
			}

			if ( (pcap_session[i].evt.ts > 0)
					&& (difftime (current_time, pcap_session[i].evt.ts) >= pcap_session[i].timeout) ){
				pcap_session[i].evt.type = SE_END;
			}

			switch ( pcap_session[i].evt.type ){
				case SE_NUL:
					// There was no change on this file descriptor, skip to
					// another one. 'continue' may seem a bit confusing here,
					// but it applies to a loop above. Not sure how other
					// compilers will behave (other than gcc).
					continue;

				case SE_BEG:
					evt_str = "BEG";
					cmd_exp = &(pcap_session[i].evt_cmd_beg);
					pcap_session[i].evt.type = SE_NUL;
					break;

				case SE_END:
					cmd_exp = &(pcap_session[i].evt_cmd_end);
					evt_str = "END";
					pcap_session[i].evt.type = SE_NUL;
					pcap_session[i].evt.ts = 0;
					break;

				case SE_ERR:
					evt_str = "ERR";
					cmd_exp = &(pcap_session[i].evt_cmd_err);
					pcap_session[i].evt.type = SE_NUL;
					pcap_session[i].evt.ts = 0;
					break;

				default:
					// Undefined state... What to do, other than die?
					syslog (LOG_ERR, "undefined event type");
					exitno = EXIT_FAILURE;
					goto cleanup;
			}

			if ( opt.verbose )
				syslog (LOG_INFO, "%s:%s", pcap_session[i].filter_name, evt_str);

			// Send socket notification
			if ( pcap_session[i].evt_mask & NOTIFY_SOCK ){
				char msg[CONF_FILTER_NAME_MAXLEN + 5];

				snprintf (msg, sizeof (msg), "%s:%s", pcap_session[i].filter_name, evt_str);

				for ( j = (filter_cnt + 1); j < poll_len; j++ ){
					if ( poll_fd[j].fd == -1 )
						continue;

					errno = 0;
					rval = send (poll_fd[j].fd, msg, strlen (msg) + 1, MSG_NOSIGNAL | MSG_DONTWAIT);

					if ( rval == -1 && (errno != EAGAIN && errno != EWOULDBLOCK) ){
						syslog (LOG_WARNING, "failed to send notification: %s", strerror (errno));
						close (poll_fd[j].fd);
						poll_fd[j].fd = -1;
					}
				}
			}

			// Execute an event hook
			if ( pcap_session[i].evt_mask & NOTIFY_EXEC ){

				// Expansion was not made...
				if ( cmd_exp->we_wordc == 0 )
					continue;

				pid = fork ();

				if ( pid == -1 ){
					syslog (LOG_ERR, "cannot fork the process: %s", strerror (errno));
					exitno = EXIT_FAILURE;
					goto cleanup;
				}

				// Parent process, carry on...
				if ( pid > 0 )
					continue;

				errno = 0;
				execv (cmd_exp->we_wordv[0], cmd_exp->we_wordv);

				// This code gets executed only if execv(3) fails. Wrapping
				// this code in a condition is unneccessary.
				syslog (LOG_WARNING, "cannot execute event hook in '%s': %s", pcap_session[i].filter_name, strerror (errno));

				exitno = EXIT_FAILURE;
				goto cleanup;
			}
		}

#ifdef DBG_AVG_LOOP_SPEED
		clock_avg = (clock_avg + (clock () - clock_start)) / 2;

		syslog (LOG_DEBUG, "Average loop speed: %lf", (double) (clock_avg / CLOCKS_PER_SEC));
#endif
	}

	syslog (LOG_INFO, "Etherpoke shutdown (signal %u)", exitno);

cleanup:
	closelog ();

	if ( pcap_session != NULL ){
		for ( i = 0; i < filter_cnt; i++ )
			session_data_free (&(pcap_session[i]));
		free (pcap_session);
	}

	if ( poll_fd != NULL )
		free (poll_fd);

	if ( sock != -1 )
		close (sock);

	config_unload (&etherpoke_conf);

	path_free (&path_config);

	return exitno;
}
Exemplo n.º 16
0
inline void set_monitor_mode(pcap_t *source, const bool flag) {
  if (pcap_set_rfmon(source, flag) != 0) {
    throw already_activated_error{source};
  }
}
Exemplo n.º 17
0
int
main(int argc, char **argv)
{
	char *cp, *device;
	int op;
	int dorfmon, useactivate;
	char ebuf[PCAP_ERRBUF_SIZE];
	char *infile;
	char *cmdbuf;
	pcap_t *pd;
	int status = 0;
	int pcap_fd;
#if defined(USE_BPF)
	struct bpf_program bad_fcode;
	struct bpf_insn uninitialized[INSN_COUNT];
#elif defined(USE_SOCKET_FILTERS)
	struct sock_fprog bad_fcode;
	struct sock_filter uninitialized[INSN_COUNT];
#endif
	struct bpf_program fcode;

	device = NULL;
	dorfmon = 0;
	useactivate = 0;
	infile = NULL;

	if ((cp = strrchr(argv[0], '/')) != NULL)
		program_name = cp + 1;
	else
		program_name = argv[0];

	opterr = 0;
	while ((op = getopt(argc, argv, "aF:i:I")) != -1) {
		switch (op) {

		case 'a':
			useactivate = 1;
			break;

		case 'F':
			infile = optarg;
			break;

		case 'i':
			device = optarg;
			break;

		case 'I':
			dorfmon = 1;
			useactivate = 1;	/* required for rfmon */
			break;

		default:
			usage();
			/* NOTREACHED */
		}
	}

	if (device == NULL) {
		/*
		 * No interface specified; get whatever pcap_lookupdev()
		 * finds.
		 */
		device = pcap_lookupdev(ebuf);
		if (device == NULL) {
			error("couldn't find interface to use: %s",
			    ebuf);
		}
	}

	if (infile != NULL) {
		/*
		 * Filter specified with "-F" and a file containing
		 * a filter.
		 */
		cmdbuf = read_infile(infile);
	} else {
		if (optind < argc) {
			/*
			 * Filter specified with arguments on the
			 * command line.
			 */
			cmdbuf = copy_argv(&argv[optind+1]);
		} else {
			/*
			 * No filter specified; use an empty string, which
			 * compiles to an "accept all" filter.
			 */
			cmdbuf = "";
		}
	}

	if (useactivate) {
		pd = pcap_create(device, ebuf);
		if (pd == NULL)
			error("%s: pcap_create() failed: %s", device, ebuf);
		status = pcap_set_snaplen(pd, 65535);
		if (status != 0)
			error("%s: pcap_set_snaplen failed: %s",
			    device, pcap_statustostr(status));
		status = pcap_set_promisc(pd, 1);
		if (status != 0)
			error("%s: pcap_set_promisc failed: %s",
			    device, pcap_statustostr(status));
		if (dorfmon) {
			status = pcap_set_rfmon(pd, 1);
			if (status != 0)
				error("%s: pcap_set_rfmon failed: %s",
				    device, pcap_statustostr(status));
		}
		status = pcap_set_timeout(pd, 1000);
		if (status != 0)
			error("%s: pcap_set_timeout failed: %s",
			    device, pcap_statustostr(status));
		status = pcap_activate(pd);
		if (status < 0) {
			/*
			 * pcap_activate() failed.
			 */
			error("%s: %s\n(%s)", device,
			    pcap_statustostr(status), pcap_geterr(pd));
		} else if (status > 0) {
			/*
			 * pcap_activate() succeeded, but it's warning us
			 * of a problem it had.
			 */
			warning("%s: %s\n(%s)", device,
			    pcap_statustostr(status), pcap_geterr(pd));
		}
	} else {
		*ebuf = '\0';
		pd = pcap_open_live(device, 65535, 1, 1000, ebuf);
		if (pd == NULL)
			error("%s", ebuf);
		else if (*ebuf)
			warning("%s", ebuf);
	}

	pcap_fd = pcap_fileno(pd);

	/*
	 * Try setting a filter with an uninitialized bpf_program
	 * structure.  This should cause valgrind to report a
	 * problem.
	 *
	 * We don't check for errors, because it could get an
	 * error due to a bad pointer or count.
	 */
#if defined(USE_BPF)
	ioctl(pcap_fd, BIOCSETF, &bad_fcode);
#elif defined(USE_SOCKET_FILTERS)
	setsockopt(pcap_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bad_fcode,
	    sizeof(bad_fcode));
#endif

	/*
	 * Try setting a filter with an initialized bpf_program
	 * structure that points to an uninitialized program.
	 * That should also cause valgrind to report a problem.
	 *
	 * We don't check for errors, because it could get an
	 * error due to a bad pointer or count.
	 */
#if defined(USE_BPF)
	bad_fcode.bf_len = INSN_COUNT;
	bad_fcode.bf_insns = uninitialized;
	ioctl(pcap_fd, BIOCSETF, &bad_fcode);
#elif defined(USE_SOCKET_FILTERS)
	bad_fcode.len = INSN_COUNT;
	bad_fcode.filter = uninitialized;
	setsockopt(pcap_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bad_fcode,
	    sizeof(bad_fcode));
#endif

	/*
	 * Now compile a filter and set the filter with that.
	 * That should *not* cause valgrind to report a
	 * problem.
	 */
	if (pcap_compile(pd, &fcode, cmdbuf, 1, 0) < 0)
		error("can't compile filter: %s", pcap_geterr(pd));
	if (pcap_setfilter(pd, &fcode) < 0)
		error("can't set filter: %s", pcap_geterr(pd));

	pcap_close(pd);
	exit(status < 0 ? 1 : 0);
}
Exemplo n.º 18
0
int main(int argc, char **argv)
{
    /* default values for command line arguments (see also static variables) */
    const char *if_name = PCAPPRINT_DEF_IFNAME;
    int snaplen = PCAPPRINT_DEF_SNAPLEN;
    const char *dlt_name = PCAPPRINT_DEF_DLTNAME;
    int num_pkts = -1;
    const char *pcap_filename = NULL;
    const char *bpf_expr = NULL;
    int rfmon = 0;

    /* process command line options */
    const char *usage = "usage: pcap-print [options]\n";

    int c;
    while ((c = getopt(argc, argv, ":1234ab:c:dfhi:mNqr:s:tVy:")) != -1) {
        switch (c) {
        case '1':
        case '2':
        case '3':
        case '4':
            enabled_layers[c-'0'-1]++;
            break;
        case 'a':
            /* arbitrary "big" number */
            enabled_layers[0] = 100;
            enabled_layers[1] = 100;
            enabled_layers[2] = 100;
            enabled_layers[3] = 100;
            break;
        case 'b':
            bpf_expr = optarg;
            break;
        case 'c':
            num_pkts = atoi(optarg);
            break;
        case 'd':
            tsfmt = TS_CTIME;
            break;
        case 'f':
            print_fcs = 1;
            break;
        case 'h':
            printf(usage);
            printf(
                "    -1  print data-link header (e.g. Ethernet)\n"
                "    -2  print network header (e.g. IP)\n"
                "    -3  print transport header (e.g. TCP)\n"
                "    -4  print application header (e.g. HTTP)\n"
                "    -a  print ALL headers, with maximum verbosity\n"
                "    -b  specify a BPF filter\n"
                "    -c  print only first N packets\n"
                "    -d  print absolute timestamp in date format\n"
                "    -f  print FCS for MAC headers\n"
                "    -h  print usage information and quit\n"
                "    -i  network interface on which to capture packets"
                " (default: %s)\n"
                "    -m  set rfmon mode on interface\n"
                "    -N  number packets as they are printed\n"
                "    -q  suppress printing of packet-parsing errors\n"
                "    -r  read from pcap file instead of live capture\n"
                "    -s  capture size in bytes (default: %d)\n"
                "    -t  print absolute timestamp\n"
                "    -V  print pcap version and quit\n"
                "    -y  datalink type for capturing interface (default: %s)\n",
                PCAPPRINT_DEF_IFNAME, PCAPPRINT_DEF_SNAPLEN, PCAPPRINT_DEF_DLTNAME);
            exit(0);
            break;
        case 'i':
            if_name = optarg;
            break;
        case 'm':
            rfmon = 1;
            break;
        case 'N':
            use_numbering = 1;
            break;
        case 'q':
            quiet = 1;
            break;
        case 'r':
            pcap_filename = optarg;
            break;
        case 's':
            snaplen = (int)strtol(optarg, (char **)NULL, 10);
            break;
        case 't':
            tsfmt = TS_ABS;
            break;
        case 'V':
            printf("%s\n", pcap_lib_version());
            exit(0);
            break;
        case 'y':
            dlt_name = optarg;
            break;
        case ':':
            errx(1, "option -%c requires an operand", optopt);
            break;
        case '?':
            errx(1, "unrecognized option: -%c", optopt);
            break;
        default:
            /* unhandled option indicates programming error */
            assert(0);
        }
    }

    /* if no layers we specified, use defaults (hard-coded) */
    if (! (enabled_layers[0] || enabled_layers[1] || enabled_layers[2] ||
            enabled_layers[3])) {
        enabled_layers[1] = 1;
        enabled_layers[2] = 1;
    }

    /* create pcap handle (either from file or from live capture) */
    char ebuf[PCAP_ERRBUF_SIZE];
    *ebuf = '\0';

    /* used only if a BPF program (filter) is specified */
    bpf_u_int32 netnum = 0, netmask = 0;

    if (pcap_filename != NULL) {
        /* "capture" from file */
        if (strcmp(if_name, PCAPPRINT_DEF_IFNAME) != 0)
            warnx("warning: -i option ignored when -f option is present");

        if (snaplen != PCAPPRINT_DEF_SNAPLEN)
            warnx("warning: -s option ignored when -f option is present");

        if (strcmp(dlt_name, PCAPPRINT_DEF_DLTNAME) != 0)
            warnx("warning: -y option ignored when -f option is present");

        pcap_h = pcap_open_offline(pcap_filename, ebuf);
        if (pcap_h == NULL)
            errx(1, "pcap_open_offline: %s", ebuf);
        else if (*ebuf)
            warnx("pcap_open_offline: %s", ebuf);

        /* read dlt from file */
        dlt = pcap_datalink(pcap_h);
    } else {
        /* live capture */
        dlt = pcap_datalink_name_to_val(dlt_name);
        if (dlt < 0)
            err(1, "invalid data link type %s", dlt_name);

        pcap_h = pcap_create(if_name, ebuf);
        if (pcap_h == NULL)
            errx(1, "pcap_create: %s", ebuf);

        if (pcap_set_snaplen(pcap_h, snaplen) != 0)
            errx(1, "pcap_set_snaplen: %s", pcap_geterr(pcap_h));

        if (pcap_set_promisc(pcap_h, 1) != 0)
            errx(1, "pcap_set_promisc: %s", pcap_geterr(pcap_h));

        if (rfmon) {
            if (pcap_can_set_rfmon(pcap_h) == 0)
                errx(1, "cannot set rfmon mode on device %s", if_name);

            if (pcap_set_rfmon(pcap_h, 1) != 0)
                errx(1, "pcap_set_rfmon: %s", pcap_geterr(pcap_h));
        }

        if (pcap_set_buffer_size(pcap_h, PCAPPRINT_BPF_BUFSIZE) != 0)
            errx(1, "pcap_set_buffer_size: %s", pcap_geterr(pcap_h));

        if (pcap_set_timeout(pcap_h, PCAPPRINT_READ_TIMEOUT) != 0)
            errx(1, "pcap_set_timeout: %s", pcap_geterr(pcap_h));

        if (pcap_lookupnet(if_name, &netnum, &netmask, ebuf) == -1)
            errx(1, "pcap_lookupnet: %s", ebuf);

        if (pcap_activate(pcap_h) != 0)
            errx(1, "pcap_activate: %s", pcap_geterr(pcap_h));

        /*
         * the following calls must be done AFTER pcap_activate():
         * pcap_setfilter
         * pcap_setdirection
         * pcap_set_datalink
         * pcap_getnonblock
         * pcap_setnonblock
         * pcap_stats
         * all reads/writes
         */

        if (pcap_set_datalink(pcap_h, dlt) == -1)
            errx(1, "pcap_set_datalink: %s", pcap_geterr(pcap_h));

        int r, yes = 1;
        int pcap_fd = pcap_get_selectable_fd(pcap_h);
        if ((r = ioctl(pcap_fd, BIOCIMMEDIATE, &yes)) == -1)
            err(1, "BIOCIMMEDIATE");
        else if (r != 0)
            warnx("BIOCIMMEDIATE returned %d", r);

        /* set up signal handlers */
        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
            signal(SIGINT, signal_handler);
        if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
            signal(SIGTERM, signal_handler);
    }

    /* apply BPF filter (if one was specified) */
    if (bpf_expr != NULL) {
        struct bpf_program bpf;
        if (pcap_compile(pcap_h, &bpf, bpf_expr, 1 /*optimize*/, netmask) == -1)
            errx(1, "pcap_compile: %s", pcap_geterr(pcap_h));

        if (pcap_setfilter(pcap_h, &bpf) == -1)
            errx(1, "pcap_setfilter: %s", pcap_geterr(pcap_h));
    }

    /* start reading packets */
    if (pcap_loop(pcap_h, num_pkts, handle_packet, NULL) == -1)
        errx(1, "pcap_loop: %s", pcap_geterr(pcap_h));

    if (pcap_filename == NULL) { /* if live capture.. */
        printf("%u packets captured\n", pkt_count);
        struct pcap_stat stats;
        if (pcap_stats(pcap_h, &stats) != 0) {
            warnx("pcap_stats: %s", pcap_geterr(pcap_h));
        } else {
            printf("%u packets received by filter\n"
                "%u packets dropped by kernel\n", stats.ps_recv, stats.ps_drop);
        }
    }

    pcap_close(pcap_h);
    return 0;
}