|
|
|
|
@ -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;
|
|
|
|
|
|