Return packet mmap size with "dabba capture list"
[dabba.git] / dabbad / capture.c
blob9248e548dffb52152a44de7942bce45b92b9f4a1
1 /* __LICENSE_HEADER_BEGIN__ */
3 /*
4 * Copyright (C) 2009-2012 Emmanuel Roullit <emmanuel.roullit@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
22 /* __LICENSE_HEADER_END__ */
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <assert.h>
30 #include <sys/queue.h>
31 #include <arpa/inet.h>
32 #include <linux/if_ether.h>
34 #include <dabbacore/macros.h>
35 #include <dabbacore/packet_rx.h>
36 #include <dabbacore/pcap.h>
37 #include <dabbad/dabbad.h>
39 struct capture_thread_node {
40 struct packet_rx_thread *pkt_capture;
41 SLIST_ENTRY(capture_thread_node) entry;
44 static SLIST_HEAD(capture_thread_head, capture_thread_node) thread_head;
46 static int capture_msg_is_valid(struct dabba_ipc_msg *msg)
48 struct dabba_capture *capture_msg = msg->msg_body.msg.capture;
50 if (!msg)
51 return 0;
53 if (strlen(capture_msg->dev_name) >= sizeof(capture_msg->dev_name))
54 return 0;
56 if (strlen(capture_msg->pcap_name) >= sizeof(capture_msg->pcap_name))
57 return 0;
59 /* refuse pcap name with '/' to not change directory */
60 if (strchr(capture_msg->pcap_name, '/'))
61 return 0;
63 if (!packet_mmap_frame_size_is_valid(capture_msg->frame_size))
64 return 0;
66 if (!capture_msg->page_order)
67 return 0;
69 return 1;
72 int dabbad_capture_start(struct dabba_ipc_msg *msg)
74 struct packet_rx_thread *pkt_capture;
75 struct capture_thread_node *thread_node;
76 struct dabba_capture *capture_msg = msg->msg_body.msg.capture;
77 int rc, sock;
79 if (!capture_msg_is_valid(msg))
80 return EINVAL;
82 sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
84 if (sock < 0)
85 return errno;
87 pkt_capture = calloc(1, sizeof(*pkt_capture));
88 thread_node = calloc(1, sizeof(*thread_node));
90 if (!pkt_capture || !thread_node) {
91 free(pkt_capture);
92 free(thread_node);
93 close(sock);
94 return ENOMEM;
97 pkt_capture->pcap_fd =
98 pcap_create(msg->msg_body.msg.capture->pcap_name, LINKTYPE_EN10MB);
100 rc = packet_mmap_create(&pkt_capture->pkt_rx, capture_msg->dev_name,
101 sock, PACKET_MMAP_RX, capture_msg->frame_size,
102 capture_msg->page_order, capture_msg->size);
104 if (rc) {
105 free(pkt_capture);
106 close(sock);
107 return rc;
110 /* TODO: Add pthread attribute support */
111 rc = pthread_create(&pkt_capture->thread, NULL, packet_rx, pkt_capture);
113 if (!rc) {
114 thread_node->pkt_capture = pkt_capture;
115 SLIST_INSERT_HEAD(&thread_head, thread_node, entry);
116 } else {
117 packet_mmap_destroy(&pkt_capture->pkt_rx);
118 free(pkt_capture);
119 free(thread_node);
120 close(sock);
123 return rc;
126 int dabbad_capture_list(struct dabba_ipc_msg *msg)
128 struct capture_thread_node *node;
129 struct dabba_capture *capture;
130 size_t a = 0, off = 0, thread_list_size;
132 capture = msg->msg_body.msg.capture;
133 thread_list_size = ARRAY_SIZE(msg->msg_body.msg.capture);
135 SLIST_FOREACH(node, &thread_head, entry) {
136 if (off < msg->msg_body.offset) {
137 off++;
138 continue;
141 if (a >= thread_list_size)
142 break;
144 capture[a].thread_id = node->pkt_capture->thread;
145 capture[a].size =
146 node->pkt_capture->pkt_rx.layout.tp_frame_size *
147 node->pkt_capture->pkt_rx.layout.tp_frame_nr;
148 a++;
151 msg->msg_body.elem_nr = a;
153 return 0;