⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dhcp-rawnet.c

📁 this is sample about DHCP-agent
💻 C
📖 第 1 页 / 共 2 页
字号:
        icmp_destroy(net->icmp_p);    if(net->udp_p)        udp_destroy(net->udp_p);    if(net->dhcp_p)        dhcp_destroy(net->dhcp_p);    xfree(net);    return;}/* The rawnet up and down routines don't mess with the interface * intentionally. They're meant only to close our packet capturing * and packet writing devices so as to free up system resources. *//* Bring pcap/dnet up and down. * Useful for wait states when * we don't want our packet buffers * to fill up. */void rawnet_down(rawnet_t *net){    if(net->pcap != NULL) {        pcap_close(net->pcap);        net->pcap = NULL;    }    if(net->eth != NULL) {        eth_close(net->eth);        net->eth = NULL;    }    return;}int rawnet_up(rawnet_t *net){    net->pcap = initialize_pcap_device(net->device, net->mtu, net->pcap_filter, net->promiscuous);    if(net->pcap == NULL) {        ERROR_MESSAGE("could not initialize pcap on device: %s", net->device);        return -1;    }    if((net->pcap_fd = pcap_fileno(net->pcap)) < 0) {        ERROR_MESSAGE("could not get pcap descriptor for: %s: %s", net->device,                      pcap_geterr(net->pcap));        rawnet_down(net);        return -1;    }    net->eth = eth_open(net->device);    if(net->eth == NULL) {        ERROR_MESSAGE("could not get ethernet handler on device: %s", net->device);        rawnet_down(net);        return -1;    }    return 0;}void reinitialize_rawnet(rawnet_t *net, int promiscuous){    net->promiscuous = promiscuous;    rawnet_down(net);    rawnet_up(net);    return;}/*  * rawnet get packet: * we already expect a filter to only allow * the following types of packets: * ARP, UDP, and ICMP. *  * Anything else is considered malformed. *  */int rawnet_get_packet(rawnet_t *net, struct timeval *tm){    const unsigned char *packet;    struct pcap_pkthdr pkthdr;    int len;    fd_set read_set;    int retval;    net->type = RAWNET_UNKNOWN;    while(1) {        FD_ZERO(&read_set);        FD_SET(net->pcap_fd, &read_set);        retval = select((net->pcap_fd + 1), &read_set, NULL, NULL, tm);        if(retval == 0)            return RAWNET_TIMEOUT;        if(retval < 0)            return RAWNET_PCAP_ERROR;        packet = pcap_next(net->pcap, &pkthdr);        if(packet == NULL)            continue; /* BPF may return 1 when there really isn't any packet for us.                       * is this because we're notified prior to filtering?                       * pcap only returns NULL on EWOULDBLOCK for bpf -- even though                       * in debugging I *never* get that errno value :| */        else            break;    }    /* Set timestamp. */#if defined(HAVE_BPF_TIMEVAL)    /* This is an ugly hack -- why oh why did OpenBSD insist on     * creating its own bpf_timeval struct with unsigned values     * as opposed to the common UNIX timeval which has signed values.     *     *     * *sigh*     *     * There really isn't any clean way around this apart from grabbing     * our own timestamp instead of using the bpf one. This is inaccurate     * but until OpenBSD fixes their braindamage they'll just have to     * deal with the inaccuracy. Anything else would be too damaging     * to the other UNIX flavors.     */    gettimeofday(&net->tstamp, NULL);#else                           /* HAVE_BPF_TIMEVAL */    net->tstamp = pkthdr.ts;#endif                          /* HAVE_BPF_TIMEVAL */    /* Read ethernet header and switch on type.   *     * Fails if malformed or insufficient length. */    if(eth_read_packet_image(net->ether_p, packet, pkthdr.caplen) < 0)        return RAWNET_MALFORMED_PACKET;    packet += ETH_HDR_LEN;    pkthdr.caplen -= ETH_HDR_LEN;    switch (eth_get_type(net->ether_p)) {    case ETH_TYPE_ARP:        if(arp_read_packet_image(net->arp_p, packet, pkthdr.caplen) < 0)            return RAWNET_MALFORMED_PACKET;        net->type = RAWNET_ARP;        return RAWNET_OK;    case ETH_TYPE_IP:        if(ip_read_packet_image(net->ip_p, packet, pkthdr.caplen) < 0)            return RAWNET_MALFORMED_PACKET;        len = ip_get_hl(net->ip_p);        packet += len;        pkthdr.caplen -= len;        switch (ip_get_proto(net->ip_p)) {        case IP_PROTO_UDP:            if(udp_read_packet_image(net->udp_p, packet, pkthdr.caplen) < 0)                return RAWNET_MALFORMED_PACKET;            /* We assume any UDP packet does contain a DHCP packet.             * So try and grab it here. */            packet += UDP_HDR_LEN;            pkthdr.caplen -= UDP_HDR_LEN;            /* purge dhcp so we get rid of old options. */            dhcp_purge(net->dhcp_p);            if(dhcp_read_packet_image(net->dhcp_p, packet, pkthdr.caplen) < 0)                return RAWNET_MALFORMED_PACKET;            net->type = RAWNET_DHCP;            return RAWNET_OK;        case IP_PROTO_ICMP:            if(icmp_read_packet_image(net->icmp_p, packet, pkthdr.caplen) < 0)                return RAWNET_MALFORMED_PACKET;            net->type = RAWNET_ICMP;            return RAWNET_OK;        default:            break;        }    default:        break;    }    return RAWNET_UNHANDLED;}int rawnet_send_packet(rawnet_t *net){    if(eth_send(net->eth, net->packet_data, net->packet_len) != net->packet_len) {        ERROR_MESSAGE("could not write to device: %s : %s", net->device, strerror(errno));        return -1;    }    return 0;}/* Just update the seconds field. *  * FIXME: mod this so that it hooks * into the rest of the framework. * right now it's error prone. */void rawnet_dhcp_update(rawnet_t *net, time_t seconds){    unsigned char *packet;    uint16_t secs = htons(seconds);    /* FIX ME: we're assuming the ip packet header     * has no options.      */    packet = (net->packet_data + ETH_HDR_LEN + IP_HDR_LEN + UDP_HDR_LEN);    packet += 8; /* to seconds field. */    memcpy(packet, &secs, 2);    ip_checksum((net->packet_data + ETH_HDR_LEN), (net->packet_len - ETH_HDR_LEN));    return;}/*  * We can ask rawnet to validate for us. * Insert checks here to make sure * the packet is as kosher as christmas * (chicken soup). *  */int rawnet_is_valid(rawnet_t *net){    switch (net->type) {    case RAWNET_DHCP:        if(!dhcp_valid_magic_cookie(net->dhcp_p))            break;        else            return 1;    default: /* todo: we need more validation on other packets. */        break;    }    return 0;}/* Generic send and wait for reply: * * Calls update() after timeout. * Calls check() on every packet coming in. * */int rawnet_packet_transact(rawnet_t *net, void *arg, void (*update) (void *arg),                           int (*check) (void *arg), time_t max_timeout){    rtt_t *rtt;    int retval;    unsigned char send_packet = 1;    struct timeval timeout;    /* create rtt mechanism. */    rtt = rtt_create(max_timeout);    /* We loop here and re-send packets if we timeout, or fail a     * check on an incoming packets. */    while(1) {        if(send_packet) {            send_packet = 0;            if(rawnet_send_packet(net) < 0) {                rtt_destroy(rtt);                ERROR_MESSAGE("could not dispatch packet");                return RAWNET_ERROR;            }        }        if(user_interrupt()) {            rtt_destroy(rtt);            return RAWNET_USER_INTERRUPT;        }                    timeout = rtt_get_timeout(rtt);        retval = rawnet_get_packet(net, &timeout);        switch (retval) {        case RAWNET_PCAP_ERROR:            rtt_destroy(rtt);            ERROR_MESSAGE("could not wait for packets on: %s", net->device);            return RAWNET_ERROR;        case RAWNET_TIMEOUT:            rtt_timeout(rtt);            if(!rtt_can_retry(rtt)) {                rtt_destroy(rtt);                return RAWNET_TIMEOUT;            }            if(update) /* update if needed. only called after timeout. */                update(arg);            send_packet = 1;            break;        case RAWNET_OK:            if(!check) /* no check? return 0 anyway (we want                        * any packet it seems). */                return 0;            if(check(arg)) { /* if we have a check                               * then check packet. */                rtt_destroy(rtt);                return RAWNET_OK; /* it's good. let's return. */            }            /* otherwise we should just continue. */            break;        case RAWNET_UNHANDLED:        case RAWNET_MALFORMED_PACKET:            break;        default:            FATAL_MESSAGE                ("rawnet: invalid return from rawnet_get_packet() -- this is a bug report it please");        }    }}/* return datalink type: use pcap for now since it seems to be * giving us the correct datalink FIXME: find out why dnet is * giving us wierd numbers and send in patch. */int rawnet_get_datalink_type(rawnet_t *net){    if(net->pcap == NULL) {        return DLT_NULL; /* we have no datalink. */    }    return pcap_datalink(net->pcap);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -