1 /*
2 * pcap-septel.c: Packet capture interface for Intel/Septel card.
3 *
4 * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY
5 * (+961 3 485243)
6 */
7
8 #include <config.h>
9
10 #include <sys/param.h>
11
12 #include <stdlib.h>
13 #include <string.h>
14 #include <errno.h>
15
16 #include "pcap-int.h"
17
18 #include <netinet/in.h>
19 #include <sys/mman.h>
20 #include <sys/socket.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 #include <msg.h>
25 #include <ss7_inc.h>
26 #include <sysgct.h>
27 #include <pack.h>
28 #include <system.h>
29
30 #include "pcap-septel.h"
31
32 static int septel_stats(pcap_t *p, struct pcap_stat *ps);
33 static int septel_getnonblock(pcap_t *p);
34 static int septel_setnonblock(pcap_t *p, int nonblock);
35
36 /*
37 * Private data for capturing on Septel devices.
38 */
39 struct pcap_septel {
40 struct pcap_stat stat;
41 }
42
43 /*
44 * Read at most max_packets from the capture queue and call the callback
45 * for each of them. Returns the number of packets handled, -1 if an
46 * error occurred, or -2 if we were told to break out of the loop.
47 */
septel_read(pcap_t * p,int cnt,pcap_handler callback,u_char * user)48 static int septel_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
49
50 struct pcap_septel *ps = p->priv;
51 HDR *h;
52 MSG *m;
53 int processed = 0 ;
54 int t = 0 ;
55
56 /* identifier for the message queue of the module(upe) from which we are capturing
57 * packets.These IDs are defined in system.txt . By default it is set to 0x2d
58 * so change it to 0xdd for technical reason and therefore the module id for upe becomes:
59 * LOCAL 0xdd * upe - Example user part task */
60 unsigned int id = 0xdd;
61
62 /* process the packets */
63 do {
64
65 unsigned short packet_len = 0;
66 int caplen = 0;
67 int counter = 0;
68 struct pcap_pkthdr pcap_header;
69 u_char *dp ;
70
71 /*
72 * Has "pcap_breakloop()" been called?
73 */
74 loop:
75 if (p->break_loop) {
76 /*
77 * Yes - clear the flag that indicates that
78 * it has, and return -2 to indicate that
79 * we were told to break out of the loop.
80 */
81 p->break_loop = 0;
82 return -2;
83 }
84
85 /*repeat until a packet is read
86 *a NULL message means :
87 * when no packet is in queue or all packets in queue already read */
88 do {
89 /* receive packet in non-blocking mode
90 * GCT_grab is defined in the septel library software */
91 h = GCT_grab(id);
92
93 m = (MSG*)h;
94 /* a counter is added here to avoid an infinite loop
95 * that will cause our capture program GUI to freeze while waiting
96 * for a packet*/
97 counter++ ;
98
99 }
100 while ((m == NULL)&& (counter< 100)) ;
101
102 if (m != NULL) {
103
104 t = h->type ;
105
106 /* catch only messages with type = 0xcf00 or 0x8f01 corresponding to ss7 messages*/
107 /* XXX = why not use API_MSG_TX_REQ for 0xcf00 and API_MSG_RX_IND
108 * for 0x8f01? */
109 if ((t != 0xcf00) && (t != 0x8f01)) {
110 relm(h);
111 goto loop ;
112 }
113
114 /* XXX - is API_MSG_RX_IND for an MTP2 or MTP3 message? */
115 dp = get_param(m);/* get pointer to MSG parameter area (m->param) */
116 packet_len = m->len;
117 caplen = p->snapshot ;
118
119
120 if (caplen > packet_len) {
121
122 caplen = packet_len;
123 }
124 /* Run the packet filter if there is one. */
125 if ((p->fcode.bf_insns == NULL) || pcapint_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
126
127
128 /* get a time stamp , consisting of :
129 *
130 * pcap_header.ts.tv_sec:
131 * ----------------------
132 * a UNIX format time-in-seconds when he packet was captured,
133 * i.e. the number of seconds since Epoch time (January 1,1970, 00:00:00 GMT)
134 *
135 * pcap_header.ts.tv_usec :
136 * ------------------------
137 * the number of microseconds since that second
138 * when the packet was captured
139 */
140
141 (void)gettimeofday(&pcap_header.ts, NULL);
142
143 /* Fill in our own header data */
144 pcap_header.caplen = caplen;
145 pcap_header.len = packet_len;
146
147 /* Count the packet. */
148 ps->stat.ps_recv++;
149
150 /* Call the user supplied callback function */
151 callback(user, &pcap_header, dp);
152
153 processed++ ;
154
155 }
156 /* after being processed the packet must be
157 *released in order to receive another one */
158 relm(h);
159 }else
160 processed++;
161
162 }
163 while (processed < cnt) ;
164
165 return processed ;
166 }
167
168
169 static int
septel_inject(pcap_t * handle,const void * buf _U_,int size _U_)170 septel_inject(pcap_t *handle, const void *buf _U_, int size _U_)
171 {
172 pcapint_strlcpy(handle->errbuf, "Sending packets isn't supported on Septel cards",
173 PCAP_ERRBUF_SIZE);
174 return (-1);
175 }
176
177 /*
178 * Activate a handle for a live capture from the given Septel device. Always pass a NULL device
179 * The promisc flag is ignored because Septel cards have built-in tracing.
180 * The timeout is also ignored as it is not supported in hardware.
181 *
182 * See also pcap(3).
183 */
septel_activate(pcap_t * handle)184 static pcap_t *septel_activate(pcap_t* handle) {
185 /* Initialize some components of the pcap structure. */
186 handle->linktype = DLT_MTP2;
187
188 /*
189 * Turn a negative snapshot value (invalid), a snapshot value of
190 * 0 (unspecified), or a value bigger than the normal maximum
191 * value, into the maximum allowed value.
192 *
193 * If some application really *needs* a bigger snapshot
194 * length, we should just increase MAXIMUM_SNAPLEN.
195 */
196 if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
197 handle->snapshot = MAXIMUM_SNAPLEN;
198
199 handle->bufsize = 0;
200
201 /*
202 * "select()" and "poll()" don't work on Septel queues
203 */
204 handle->selectable_fd = -1;
205
206 handle->read_op = septel_read;
207 handle->inject_op = septel_inject;
208 handle->setfilter_op = pcapint_install_bpf_program;
209 handle->set_datalink_op = NULL; /* can't change data link type */
210 handle->getnonblock_op = septel_getnonblock;
211 handle->setnonblock_op = septel_setnonblock;
212 handle->stats_op = septel_stats;
213
214 return 0;
215 }
216
septel_create(const char * device,char * ebuf,int * is_ours)217 pcap_t *septel_create(const char *device, char *ebuf, int *is_ours) {
218 const char *cp;
219 pcap_t *p;
220
221 /* Does this look like the Septel device? */
222 cp = strrchr(device, '/');
223 if (cp == NULL)
224 cp = device;
225 if (strcmp(cp, "septel") != 0) {
226 /* Nope, it's not "septel" */
227 *is_ours = 0;
228 return NULL;
229 }
230
231 /* OK, it's probably ours. */
232 *is_ours = 1;
233
234 p = PCAP_CREATE_COMMON(ebuf, struct pcap_septel);
235 if (p == NULL)
236 return NULL;
237
238 p->activate_op = septel_activate;
239 /*
240 * Set these up front, so that, even if our client tries
241 * to set non-blocking mode before we're activated, or
242 * query the state of non-blocking mode, they get an error,
243 * rather than having the non-blocking mode option set
244 * for use later.
245 */
246 p->getnonblock_op = septel_getnonblock;
247 p->setnonblock_op = septel_setnonblock;
248 return p;
249 }
250
septel_stats(pcap_t * p,struct pcap_stat * ps)251 static int septel_stats(pcap_t *p, struct pcap_stat *ps) {
252 struct pcap_septel *handlep = p->priv;
253 /*handlep->stat.ps_recv = 0;*/
254 /*handlep->stat.ps_drop = 0;*/
255
256 *ps = handlep->stat;
257
258 return 0;
259 }
260
261
262 int
septel_findalldevs(pcap_if_list_t * devlistp,char * errbuf)263 septel_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
264 {
265 /*
266 * XXX - do the notions of "up", "running", or "connected" apply here?
267 */
268 if (pcapint_add_dev(devlistp,"septel",0,"Intel/Septel device",errbuf) == NULL)
269 return -1;
270 return 0;
271 }
272
273
274 /*
275 * We don't support non-blocking mode. I'm not sure what we'd
276 * do to support it and, given that we don't support select()/
277 * poll()/epoll_wait()/kevent() etc., it probably doesn't
278 * matter.
279 */
280 static int
septel_getnonblock(pcap_t * p)281 septel_getnonblock(pcap_t *p)
282 {
283 fprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices");
284 return (-1);
285 }
286
287 static int
septel_setnonblock(pcap_t * p,int nonblock _U_)288 septel_setnonblock(pcap_t *p, int nonblock _U_)
289 {
290 fprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices");
291 return (-1);
292 }
293
294 #ifdef SEPTEL_ONLY
295 /*
296 * This libpcap build supports only Septel cards, not regular network
297 * interfaces.
298 */
299
300 /*
301 * There are no regular interfaces, just Septel interfaces.
302 */
303 int
pcapint_platform_finddevs(pcap_if_list_t * devlistp,char * errbuf)304 pcapint_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
305 {
306 return (0);
307 }
308
309 /*
310 * Attempts to open a regular interface fail.
311 */
312 pcap_t *
pcapint_create_interface(const char * device,char * errbuf)313 pcapint_create_interface(const char *device, char *errbuf)
314 {
315 snprintf(errbuf, PCAP_ERRBUF_SIZE,
316 "This version of libpcap only supports Septel cards");
317 return (NULL);
318 }
319
320 /*
321 * Libpcap version string.
322 */
323 const char *
pcap_lib_version(void)324 pcap_lib_version(void)
325 {
326 return (PCAP_VERSION_STRING " (Septel-only)");
327 }
328 #endif
329