From: Eric Leblond Date: Thu, 7 Apr 2016 19:58:48 +0000 (+0200) Subject: af-packet: put ring setup in a separate function X-Git-Tag: suricata-3.1RC1~105 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c7bde9dff66bd9722b7d4e8c80abd4b29fc5571b;p=thirdparty%2Fsuricata.git af-packet: put ring setup in a separate function --- diff --git a/src/source-af-packet.c b/src/source-af-packet.c index 971cba0e7b..95a85a9d25 100644 --- a/src/source-af-packet.c +++ b/src/source-af-packet.c @@ -1592,17 +1592,153 @@ static int AFPComputeRingParamsV3(AFPThreadVars *ptv) return 1; } +static int AFPSetupRing(AFPThreadVars *ptv, char *devname) +{ + int val; + unsigned int len = sizeof(val), i; + unsigned int ring_buflen; + uint8_t * ring_buf; + int order; + int r; + + if (ptv->flags & AFP_TPACKET_V3) { + val = TPACKET_V3; + } else { + val = TPACKET_V2; + } + if (getsockopt(ptv->socket, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) { + if (errno == ENOPROTOOPT) { + if (ptv->flags & AFP_TPACKET_V3) { + SCLogError(SC_ERR_AFP_CREATE, + "Too old kernel giving up (need 3.2 for TPACKET_V3)"); + } else { + SCLogError(SC_ERR_AFP_CREATE, + "Too old kernel giving up (need 2.6.27 at least)"); + } + } + SCLogError(SC_ERR_AFP_CREATE, "Error when retrieving packet header len"); + return AFP_FATAL_ERROR; + } + + if (ptv->flags & AFP_TPACKET_V3) { + val = TPACKET_V3; + } else { + val = TPACKET_V2; + } + if (setsockopt(ptv->socket, SOL_PACKET, PACKET_VERSION, &val, + sizeof(val)) < 0) { + SCLogError(SC_ERR_AFP_CREATE, + "Can't activate TPACKET_V2/TPACKET_V3 on packet socket: %s", + strerror(errno)); + return AFP_FATAL_ERROR; + } + + /* Allocate RX ring */ + if (ptv->flags & AFP_TPACKET_V3) { + if (AFPComputeRingParamsV3(ptv) != 1) { + return AFP_FATAL_ERROR; + } + r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING, + (void *) &ptv->req3, sizeof(ptv->req3)); + if (r < 0) { + SCLogError(SC_ERR_MEM_ALLOC, + "Unable to allocate RX Ring for iface %s: (%d) %s", + devname, + errno, + strerror(errno)); + return AFP_FATAL_ERROR; + } + } else { +#define DEFAULT_ORDER 3 + for (order = DEFAULT_ORDER; order >= 0; order--) { + if (AFPComputeRingParams(ptv, order) != 1) { + SCLogInfo("Ring parameter are incorrect. Please correct the devel"); + return AFP_FATAL_ERROR; + } + + r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING, + (void *) &ptv->req, sizeof(ptv->req)); + + if (r < 0) { + if (errno == ENOMEM) { + SCLogInfo("Memory issue with ring parameters. Retrying."); + continue; + } + SCLogError(SC_ERR_MEM_ALLOC, + "Unable to allocate RX Ring for iface %s: (%d) %s", + devname, + errno, + strerror(errno)); + return AFP_FATAL_ERROR; + } else { + break; + } + } + if (order < 0) { + SCLogError(SC_ERR_MEM_ALLOC, + "Unable to allocate RX Ring for iface %s (order 0 failed)", + devname); + return AFP_FATAL_ERROR; + } + } + + /* Allocate the Ring */ + if (ptv->flags & AFP_TPACKET_V3) { + ring_buflen = ptv->req3.tp_block_nr * ptv->req3.tp_block_size; + } else { + ring_buflen = ptv->req.tp_block_nr * ptv->req.tp_block_size; + } + ring_buf = mmap(0, ring_buflen, PROT_READ|PROT_WRITE, + MAP_SHARED, ptv->socket, 0); + if (ring_buf == MAP_FAILED) { + SCLogError(SC_ERR_MEM_ALLOC, "Unable to mmap"); + goto mmap_err; + } + if (ptv->flags & AFP_TPACKET_V3) { + ptv->ring_v3 = SCMalloc(ptv->req3.tp_block_nr * sizeof(*ptv->ring_v3)); + if (!ptv->ring_v3) { + SCLogError(SC_ERR_MEM_ALLOC, "Unable to malloc ptv ring_v3"); + goto mmap_err; + } + for (i = 0; i < ptv->req3.tp_block_nr; ++i) { + ptv->ring_v3[i].iov_base = ring_buf + (i * ptv->req3.tp_block_size); + ptv->ring_v3[i].iov_len = ptv->req3.tp_block_size; + } + } else { + /* allocate a ring for each frame header pointer*/ + ptv->ring_v2 = SCMalloc(ptv->req.tp_frame_nr * sizeof (union thdr *)); + if (ptv->ring_v2 == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate frame buf"); + goto mmap_err; + } + memset(ptv->ring_v2, 0, ptv->req.tp_frame_nr * sizeof (union thdr *)); + /* fill the header ring with proper frame ptr*/ + ptv->frame_offset = 0; + for (i = 0; i < ptv->req.tp_block_nr; ++i) { + void *base = &ring_buf[i * ptv->req.tp_block_size]; + unsigned int j; + for (j = 0; j < ptv->req.tp_block_size / ptv->req.tp_frame_size; ++j, ++ptv->frame_offset) { + (((union thdr **)ptv->ring_v2)[ptv->frame_offset]) = base; + base += ptv->req.tp_frame_size; + } + } + ptv->frame_offset = 0; + } + + return 0; + +mmap_err: + /* Packet mmap does the cleaning when socket is closed */ + return AFP_FATAL_ERROR; +} + 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 order; - unsigned int i; int if_idx; - unsigned int ring_buflen; - uint8_t * ring_buf; /* open socket */ ptv->socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); @@ -1633,7 +1769,7 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose) SCLogError(SC_ERR_AFP_CREATE, "Couldn't switch iface %s to promiscuous, error %s", devname, strerror(errno)); - goto frame_err; + goto socket_err; } } @@ -1659,7 +1795,7 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose) SCLogError(SC_ERR_AFP_CREATE, "Couldn't set buffer size to %d on iface %s, error %s", ptv->buffer_size, devname, strerror(errno)); - goto frame_err; + goto socket_err; } } @@ -1677,7 +1813,7 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose) } } ret = AFP_RECOVERABLE_ERROR; - goto frame_err; + goto socket_err; } #ifdef HAVE_PACKET_FANOUT @@ -1692,7 +1828,7 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose) SCLogError(SC_ERR_AFP_CREATE, "Coudn't set fanout mode, error %s", strerror(errno)); - goto frame_err; + goto socket_err; } } #endif @@ -1705,7 +1841,7 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose) ptv->iface); } ret = AFP_RECOVERABLE_ERROR; - goto frame_err; + goto socket_err; } if ((if_flags & IFF_UP) == 0) { if (verbose) { @@ -1714,129 +1850,13 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose) ptv->iface); } ret = AFP_RECOVERABLE_ERROR; - goto frame_err; + goto socket_err; } if (ptv->flags & AFP_RING_MODE) { - int val; - unsigned int len = sizeof(val); - - if (ptv->flags & AFP_TPACKET_V3) { - val = TPACKET_V3; - } else { - val = TPACKET_V2; - } - if (getsockopt(ptv->socket, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) { - if (errno == ENOPROTOOPT) { - if (ptv->flags & AFP_TPACKET_V3) { - SCLogError(SC_ERR_AFP_CREATE, - "Too old kernel giving up (need 3.2 for TPACKET_V3)"); - } else { - SCLogError(SC_ERR_AFP_CREATE, - "Too old kernel giving up (need 2.6.27 at least)"); - } - } - SCLogError(SC_ERR_AFP_CREATE, "Error when retrieving packet header len"); - goto socket_err; - } - - if (ptv->flags & AFP_TPACKET_V3) { - val = TPACKET_V3; - } else { - val = TPACKET_V2; - } - if (setsockopt(ptv->socket, SOL_PACKET, PACKET_VERSION, &val, - sizeof(val)) < 0) { - SCLogError(SC_ERR_AFP_CREATE, - "Can't activate TPACKET_V2/TPACKET_V3 on packet socket: %s", - strerror(errno)); - goto socket_err; - } - - /* Allocate RX ring */ - if (ptv->flags & AFP_TPACKET_V3) { - if (AFPComputeRingParamsV3(ptv) != 1) { - SCLogInfo("Ring parameter are incorrect. Please correct the devel"); - goto socket_err; - } - r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING, - (void *) &ptv->req3, sizeof(ptv->req3)); - } else { -#define DEFAULT_ORDER 3 - for (order = DEFAULT_ORDER; order >= 0; order--) { - if (AFPComputeRingParams(ptv, order) != 1) { - SCLogInfo("Ring parameter are incorrect. Please correct the devel"); - goto socket_err; - } - - r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING, - (void *) &ptv->req, sizeof(ptv->req)); - - if (r < 0) { - if (errno == ENOMEM) { - SCLogInfo("Memory issue with ring parameters. Retrying."); - continue; - } - SCLogError(SC_ERR_MEM_ALLOC, - "Unable to allocate RX Ring for iface %s: (%d) %s", - devname, - errno, - strerror(errno)); - goto socket_err; - } else { - break; - } - } - if (order < 0) { - SCLogError(SC_ERR_MEM_ALLOC, - "Unable to allocate RX Ring for iface %s (order 0 failed)", - devname); - goto socket_err; - } - } - - /* Allocate the Ring */ - if (ptv->flags & AFP_TPACKET_V3) { - ring_buflen = ptv->req3.tp_block_nr * ptv->req3.tp_block_size; - } else { - ring_buflen = ptv->req.tp_block_nr * ptv->req.tp_block_size; - } - ring_buf = mmap(0, ring_buflen, PROT_READ|PROT_WRITE, - MAP_SHARED, ptv->socket, 0); - if (ring_buf == MAP_FAILED) { - SCLogError(SC_ERR_MEM_ALLOC, "Unable to mmap"); + ret = AFPSetupRing(ptv, devname); + if (ret != 0) goto socket_err; - } - if (ptv->flags & AFP_TPACKET_V3) { - ptv->ring_v3 = SCMalloc(ptv->req3.tp_block_nr * sizeof(*ptv->ring_v3)); - if (!ptv->ring_v3) { - SCLogError(SC_ERR_MEM_ALLOC, "Unable to malloc ptv ring_v3"); - goto mmap_err; - } - for (i = 0; i < ptv->req3.tp_block_nr; ++i) { - ptv->ring_v3[i].iov_base = ring_buf + (i * ptv->req3.tp_block_size); - ptv->ring_v3[i].iov_len = ptv->req3.tp_block_size; - } - } else { - /* allocate a ring for each frame header pointer*/ - ptv->ring_v2 = SCMalloc(ptv->req.tp_frame_nr * sizeof (union thdr *)); - if (ptv->ring_v2 == NULL) { - SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate frame buf"); - goto mmap_err; - } - memset(ptv->ring_v2, 0, ptv->req.tp_frame_nr * sizeof (union thdr *)); - /* fill the header ring with proper frame ptr*/ - ptv->frame_offset = 0; - for (i = 0; i < ptv->req.tp_block_nr; ++i) { - void *base = &ring_buf[i * ptv->req.tp_block_size]; - unsigned int j; - for (j = 0; j < ptv->req.tp_block_size / ptv->req.tp_frame_size; ++j, ++ptv->frame_offset) { - (((union thdr **)ptv->ring_v2)[ptv->frame_offset]) = base; - base += ptv->req.tp_frame_size; - } - } - ptv->frame_offset = 0; - } } SCLogDebug("Using interface '%s' via socket %d", (char *)devname, ptv->socket); @@ -1868,8 +1888,6 @@ frame_err: if (ptv->ring_v2) SCFree(ptv->ring_v2); } -mmap_err: - /* Packet mmap does the cleaning when socket is closed */ socket_err: close(ptv->socket); ptv->socket = -1;