美文网首页
通过研读Suricata入侵检测系统源代码学习SOCK_RAW原

通过研读Suricata入侵检测系统源代码学习SOCK_RAW原

作者: 阿群1986 | 来源:发表于2019-09-30 20:19 被阅读0次

    前言

    Suricata是一套开源入侵检测系统, 其源代码可以通过github在线查看.

    4.0版本中文文档:

    在线英文文档

    关于AF_PACKET原始套接字的用法可以参考下列代码

    static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
    {
        int r;
        int ret = AFP_FATAL_ERROR;
        struct packet_mreq sock_params;
        struct sockaddr_ll bind_address;
        int if_idx;
    
    
        /* open socket */
        ptv->socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
        if (ptv->socket == -1) {
            SCLogError(SC_ERR_AFP_CREATE, "Couldn't create a AF_PACKET socket, error %s", strerror(errno));
            goto error;
        }
    
    
        if_idx = AFPGetIfnumByDev(ptv->socket, devname, verbose);
    
    
        if (if_idx == -1) {
            goto socket_err;
        }
    
    
        /* bind socket */
        memset(&bind_address, 0, sizeof(bind_address));
        bind_address.sll_family = AF_PACKET;
        bind_address.sll_protocol = htons(ETH_P_ALL);
        bind_address.sll_ifindex = if_idx;
        if (bind_address.sll_ifindex == -1) {
            if (verbose)
                SCLogError(SC_ERR_AFP_CREATE, "Couldn't find iface %s", devname);
            ret = AFP_RECOVERABLE_ERROR;
            goto socket_err;
        }
    
    
        int if_flags = AFPGetDevFlags(ptv->socket, ptv->iface);
        if (if_flags == -1) {
            if (verbose) {
                SCLogError(SC_ERR_AFP_READ,
                        "Couldn't get flags for interface '%s'",
                        ptv->iface);
            }
            ret = AFP_RECOVERABLE_ERROR;
            goto socket_err;
        } else if ((if_flags & (IFF_UP | IFF_RUNNING)) == 0) {
            if (verbose) {
                SCLogError(SC_ERR_AFP_READ,
                        "Interface '%s' is down",
                        ptv->iface);
            }
            ret = AFP_RECOVERABLE_ERROR;
            goto socket_err;
        }
    
    
        if (ptv->promisc != 0) {
            /* Force promiscuous mode */
            memset(&sock_params, 0, sizeof(sock_params));
            sock_params.mr_type = PACKET_MR_PROMISC;
            sock_params.mr_ifindex = bind_address.sll_ifindex;
            r = setsockopt(ptv->socket, SOL_PACKET, PACKET_ADD_MEMBERSHIP,(void *)&sock_params, sizeof(sock_params));
            if (r < 0) {
                SCLogError(SC_ERR_AFP_CREATE,
                        "Couldn't switch iface %s to promiscuous, error %s",
                        devname, strerror(errno));
                goto socket_err;
            }
        }
    
    
        if (ptv->checksum_mode == CHECKSUM_VALIDATION_KERNEL) {
            int val = 1;
            if (setsockopt(ptv->socket, SOL_PACKET, PACKET_AUXDATA, &val,
                        sizeof(val)) == -1 && errno != ENOPROTOOPT) {
                SCLogWarning(SC_ERR_NO_AF_PACKET,
                             "'kernel' checksum mode not supported, falling back to full mode.");
                ptv->checksum_mode = CHECKSUM_VALIDATION_ENABLE;
            }
        }
    
    
        /* set socket recv buffer size */
        if (ptv->buffer_size != 0) {
            /*
             * Set the socket buffer size to the specified value.
             */
            SCLogPerf("Setting AF_PACKET socket buffer to %d", ptv->buffer_size);
            if (setsockopt(ptv->socket, SOL_SOCKET, SO_RCVBUF,
                           &ptv->buffer_size,
                           sizeof(ptv->buffer_size)) == -1) {
                SCLogError(SC_ERR_AFP_CREATE,
                        "Couldn't set buffer size to %d on iface %s, error %s",
                        ptv->buffer_size, devname, strerror(errno));
                goto socket_err;
            }
        }
    
    
        r = bind(ptv->socket, (struct sockaddr *)&bind_address, sizeof(bind_address));
        if (r < 0) {
            if (verbose) {
                if (errno == ENETDOWN) {
                    SCLogError(SC_ERR_AFP_CREATE,
                            "Couldn't bind AF_PACKET socket, iface %s is down",
                            devname);
                } else {
                    SCLogError(SC_ERR_AFP_CREATE,
                            "Couldn't bind AF_PACKET socket to iface %s, error %s",
                            devname, strerror(errno));
                }
            }
            ret = AFP_RECOVERABLE_ERROR;
            goto socket_err;
        }
    
    
    
    
    #ifdef HAVE_PACKET_FANOUT
        /* add binded socket to fanout group */
        if (ptv->threads > 1) {
            uint16_t mode = ptv->cluster_type;
            uint16_t id = ptv->cluster_id;
            uint32_t option = (mode << 16) | (id & 0xffff);
            r = setsockopt(ptv->socket, SOL_PACKET, PACKET_FANOUT,(void *)&option, sizeof(option));
            if (r < 0) {
                SCLogError(SC_ERR_AFP_CREATE,
                           "Couldn't set fanout mode, error %s",
                           strerror(errno));
                goto socket_err;
            }
        }
    #endif
    
    
    #ifdef HAVE_PACKET_EBPF
        if (ptv->cluster_type == PACKET_FANOUT_EBPF) {
            r = SockFanoutSeteBPF(ptv);
            if (r < 0) {
                SCLogError(SC_ERR_AFP_CREATE,
                           "Coudn't set EBPF, error %s",
                           strerror(errno));
                goto socket_err;
            }
        }
    #endif
    
    
        if (ptv->flags & AFP_RING_MODE) {
            ret = AFPSetupRing(ptv, devname);
            if (ret != 0)
                goto socket_err;
        }
    
    
        SCLogDebug("Using interface '%s' via socket %d", (char *)devname, ptv->socket);
    
    
        ptv->datalink = AFPGetDevLinktype(ptv->socket, ptv->iface);
        switch (ptv->datalink) {
            case ARPHRD_PPP:
            case ARPHRD_ATM:
                ptv->cooked = 1;
                break;
        }
    
    
        TmEcode rc = AFPSetBPFFilter(ptv);
        if (rc == TM_ECODE_FAILED) {
            ret = AFP_FATAL_ERROR;
            goto socket_err;
        }
    
    
        /* Init is ok */
        AFPSwitchState(ptv, AFP_STATE_UP);
        return 0;
    
    
    socket_err:
        close(ptv->socket);
        ptv->socket = -1;
        if (ptv->flags & AFP_TPACKET_V3) {
            if (ptv->ring.v3) {
                SCFree(ptv->ring.v3);
                ptv->ring.v3 = NULL;
            }
        } else {
            if (ptv->ring.v2) {
                SCFree(ptv->ring.v2);
                ptv->ring.v2 = NULL;
            }
        }
    
    
    error:
        return -ret;
    }
    

    相关文章

      网友评论

          本文标题:通过研读Suricata入侵检测系统源代码学习SOCK_RAW原

          本文链接:https://www.haomeiwen.com/subject/rmuhpctx.html