1 /* For terms of usage/redistribution/modification see the LICENSE file */
2 /* For authors and contributors see the AUTHORS file */
4 #include "iptraf-ng-compat.h"
11 struct capt_data_recvmmsg
{
14 struct mmsghdr
*msgvec
;
16 struct sockaddr_ll
*from
;
18 unsigned int lastslot
;
22 static unsigned int capt_recvmmsg_find_filled_slot(struct capt_data_recvmmsg
*data
)
24 for (unsigned int slot
= data
->lastslot
; slot
< FRAMES
; slot
++)
25 if (data
->msgvec
[slot
].msg_len
!= 0)
31 static unsigned int capt_have_packet_recvmmsg(struct capt
*capt
)
33 struct capt_data_recvmmsg
*data
= capt
->priv
;
35 return capt_recvmmsg_find_filled_slot(data
) != FRAMES
;
38 static int capt_get_packet_recvmmsg(struct capt
*capt
, struct pkt_hdr
*pkt
)
40 struct capt_data_recvmmsg
*data
= capt
->priv
;
43 unsigned int slot
= capt_recvmmsg_find_filled_slot(data
);
45 /* these are set upon return from recvmsg() so clean */
47 for (unsigned int i
= 0; i
< FRAMES
; i
++) {
48 data
->msgvec
[i
].msg_hdr
.msg_controllen
= 0;
49 data
->msgvec
[i
].msg_hdr
.msg_flags
= 0;
50 data
->msgvec
[i
].msg_len
= 0;
53 int received
= recvmmsg(capt
->fd
, data
->msgvec
, FRAMES
, MSG_TRUNC
| MSG_DONTWAIT
, NULL
);
58 pkt
->pkt_len
= data
->msgvec
[slot
].msg_len
;
59 pkt
->pkt_caplen
= data
->msgvec
[slot
].msg_len
;
60 if (pkt
->pkt_caplen
> MAX_PACKET_SIZE
)
61 pkt
->pkt_caplen
= MAX_PACKET_SIZE
;
62 pkt
->pkt_buf
= data
->buf
+ slot
* MAX_PACKET_SIZE
;
63 pkt
->from
= &data
->from
[slot
];
64 pkt
->pkt_payload
= NULL
;
65 pkt
->pkt_protocol
= ntohs(pkt
->from
->sll_protocol
);
72 static int capt_put_packet_recvmmsg(struct capt
*capt
, struct pkt_hdr
*pkt __unused
)
74 struct capt_data_recvmmsg
*data
= capt
->priv
;
76 /* hand out processed slot to kernel */
77 if (data
->slot
< FRAMES
) {
78 data
->msgvec
[data
->slot
].msg_len
= 0;
79 data
->lastslot
= data
->slot
;
86 static void capt_cleanup_recvmmsg(struct capt
*capt
)
88 struct capt_data_recvmmsg
*data
= capt
->priv
;
91 capt
->put_packet
= NULL
;
92 capt
->get_packet
= NULL
;
93 capt
->have_packet
= NULL
;
108 int capt_setup_recvmmsg(struct capt
*capt
)
110 struct capt_data_recvmmsg
*data
;
112 data
= xmallocz(sizeof(struct capt_data_recvmmsg
));
113 data
->buf
= xmallocz(FRAMES
* MAX_PACKET_SIZE
);
114 data
->msgvec
= xmallocz(FRAMES
* sizeof(*data
->msgvec
));
115 data
->iov
= xmallocz(FRAMES
* sizeof(*data
->iov
));
116 data
->from
= xmallocz(FRAMES
* sizeof(*data
->from
));
118 for (unsigned int i
= 0; i
< FRAMES
; i
++) {
119 data
->iov
[i
].iov_len
= MAX_PACKET_SIZE
;
120 data
->iov
[i
].iov_base
= data
->buf
+ i
* MAX_PACKET_SIZE
;
122 data
->msgvec
[i
].msg_hdr
.msg_name
= &data
->from
[i
];
123 data
->msgvec
[i
].msg_hdr
.msg_namelen
= sizeof(data
->from
[i
]);
124 data
->msgvec
[i
].msg_hdr
.msg_iov
= &data
->iov
[i
];
125 data
->msgvec
[i
].msg_hdr
.msg_iovlen
= 1;
126 data
->msgvec
[i
].msg_hdr
.msg_control
= NULL
;
132 capt
->have_packet
= capt_have_packet_recvmmsg
;
133 capt
->get_packet
= capt_get_packet_recvmmsg
;
134 capt
->put_packet
= capt_put_packet_recvmmsg
;
135 capt
->cleanup
= capt_cleanup_recvmmsg
;