nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * pcap-septel.c: Packet capture interface for Intel/Septel card. |
||
3 | * |
||
4 | * The functionality of this code attempts to mimic that of pcap-linux as much |
||
5 | * as possible. This code is compiled in several different ways depending on |
||
6 | * whether SEPTEL_ONLY and HAVE_SEPTEL_API are defined. If HAVE_SEPTEL_API is |
||
7 | * not defined it should not get compiled in, otherwise if SEPTEL_ONLY is |
||
8 | * defined then the 'septel_' function calls are renamed to 'pcap_' |
||
9 | * equivalents. If SEPTEL_ONLY is not defined then nothing is altered - the |
||
10 | * septel_ functions will be called as required from their |
||
11 | * pcap-linux/equivalents. |
||
12 | * |
||
13 | * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY |
||
14 | * (+961 3 485243) |
||
15 | */ |
||
16 | |||
17 | #ifdef HAVE_CONFIG_H |
||
18 | #include "config.h" |
||
19 | #endif |
||
20 | |||
21 | #include <sys/param.h> |
||
22 | |||
23 | #include <stdlib.h> |
||
24 | #include <string.h> |
||
25 | #include <errno.h> |
||
26 | |||
27 | #include "pcap-int.h" |
||
28 | |||
29 | #include <ctype.h> |
||
30 | #include <netinet/in.h> |
||
31 | #include <sys/mman.h> |
||
32 | #include <sys/socket.h> |
||
33 | #include <sys/types.h> |
||
34 | #include <unistd.h> |
||
35 | |||
36 | #include <msg.h> |
||
37 | #include <ss7_inc.h> |
||
38 | #include <sysgct.h> |
||
39 | #include <pack.h> |
||
40 | #include <system.h> |
||
41 | |||
42 | #include "pcap-septel.h" |
||
43 | |||
44 | static int septel_setfilter(pcap_t *p, struct bpf_program *fp); |
||
45 | static int septel_stats(pcap_t *p, struct pcap_stat *ps); |
||
46 | static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf); |
||
47 | |||
48 | /* |
||
49 | * Private data for capturing on Septel devices. |
||
50 | */ |
||
51 | struct pcap_septel { |
||
52 | struct pcap_stat stat; |
||
53 | } |
||
54 | |||
55 | /* |
||
56 | * Read at most max_packets from the capture queue and call the callback |
||
57 | * for each of them. Returns the number of packets handled, -1 if an |
||
58 | * error occured, or -2 if we were told to break out of the loop. |
||
59 | */ |
||
60 | static int septel_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { |
||
61 | |||
62 | struct pcap_septel *ps = p->priv; |
||
63 | HDR *h; |
||
64 | MSG *m; |
||
65 | int processed = 0 ; |
||
66 | int t = 0 ; |
||
67 | |||
68 | /* identifier for the message queue of the module(upe) from which we are capturing |
||
69 | * packets.These IDs are defined in system.txt . By default it is set to 0x2d |
||
70 | * so change it to 0xdd for technical reason and therefore the module id for upe becomes: |
||
71 | * LOCAL 0xdd * upe - Example user part task */ |
||
72 | unsigned int id = 0xdd; |
||
73 | |||
74 | /* process the packets */ |
||
75 | do { |
||
76 | |||
77 | unsigned short packet_len = 0; |
||
78 | int caplen = 0; |
||
79 | int counter = 0; |
||
80 | struct pcap_pkthdr pcap_header; |
||
81 | u_char *dp ; |
||
82 | |||
83 | /* |
||
84 | * Has "pcap_breakloop()" been called? |
||
85 | */ |
||
86 | loop: |
||
87 | if (p->break_loop) { |
||
88 | /* |
||
89 | * Yes - clear the flag that indicates that |
||
90 | * it has, and return -2 to indicate that |
||
91 | * we were told to break out of the loop. |
||
92 | */ |
||
93 | p->break_loop = 0; |
||
94 | return -2; |
||
95 | } |
||
96 | |||
97 | /*repeat until a packet is read |
||
98 | *a NULL message means : |
||
99 | * when no packet is in queue or all packets in queue already read */ |
||
100 | do { |
||
101 | /* receive packet in non-blocking mode |
||
102 | * GCT_grab is defined in the septel library software */ |
||
103 | h = GCT_grab(id); |
||
104 | |||
105 | m = (MSG*)h; |
||
106 | /* a couter is added here to avoid an infinite loop |
||
107 | * that will cause our capture program GUI to freeze while waiting |
||
108 | * for a packet*/ |
||
109 | counter++ ; |
||
110 | |||
111 | } |
||
112 | while ((m == NULL)&& (counter< 100)) ; |
||
113 | |||
114 | if (m != NULL) { |
||
115 | |||
116 | t = h->type ; |
||
117 | |||
118 | /* catch only messages with type = 0xcf00 or 0x8f01 corrsponding to ss7 messages*/ |
||
119 | /* XXX = why not use API_MSG_TX_REQ for 0xcf00 and API_MSG_RX_IND |
||
120 | * for 0x8f01? */ |
||
121 | if ((t != 0xcf00) && (t != 0x8f01)) { |
||
122 | relm(h); |
||
123 | goto loop ; |
||
124 | } |
||
125 | |||
126 | /* XXX - is API_MSG_RX_IND for an MTP2 or MTP3 message? */ |
||
127 | dp = get_param(m);/* get pointer to MSG parameter area (m->param) */ |
||
128 | packet_len = m->len; |
||
129 | caplen = p->snapshot ; |
||
130 | |||
131 | |||
132 | if (caplen > packet_len) { |
||
133 | |||
134 | caplen = packet_len; |
||
135 | } |
||
136 | /* Run the packet filter if there is one. */ |
||
137 | if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) { |
||
138 | |||
139 | |||
140 | /* get a time stamp , consisting of : |
||
141 | * |
||
142 | * pcap_header.ts.tv_sec: |
||
143 | * ---------------------- |
||
144 | * a UNIX format time-in-seconds when he packet was captured, |
||
145 | * i.e. the number of seconds since Epoch time (January 1,1970, 00:00:00 GMT) |
||
146 | * |
||
147 | * pcap_header.ts.tv_usec : |
||
148 | * ------------------------ |
||
149 | * the number of microseconds since that second |
||
150 | * when the packet was captured |
||
151 | */ |
||
152 | |||
153 | (void)gettimeofday(&pcap_header.ts, NULL); |
||
154 | |||
155 | /* Fill in our own header data */ |
||
156 | pcap_header.caplen = caplen; |
||
157 | pcap_header.len = packet_len; |
||
158 | |||
159 | /* Count the packet. */ |
||
160 | ps->stat.ps_recv++; |
||
161 | |||
162 | /* Call the user supplied callback function */ |
||
163 | callback(user, &pcap_header, dp); |
||
164 | |||
165 | processed++ ; |
||
166 | |||
167 | } |
||
168 | /* after being processed the packet must be |
||
169 | *released in order to receive another one */ |
||
170 | relm(h); |
||
171 | }else |
||
172 | processed++; |
||
173 | |||
174 | } |
||
175 | while (processed < cnt) ; |
||
176 | |||
177 | return processed ; |
||
178 | } |
||
179 | |||
180 | |||
181 | static int |
||
182 | septel_inject(pcap_t *handle, const void *buf _U_, size_t size _U_) |
||
183 | { |
||
184 | strlcpy(handle->errbuf, "Sending packets isn't supported on Septel cards", |
||
185 | PCAP_ERRBUF_SIZE); |
||
186 | return (-1); |
||
187 | } |
||
188 | |||
189 | /* |
||
190 | * Activate a handle for a live capture from the given Septel device. Always pass a NULL device |
||
191 | * The promisc flag is ignored because Septel cards have built-in tracing. |
||
192 | * The timeout is also ignored as it is not supported in hardware. |
||
193 | * |
||
194 | * See also pcap(3). |
||
195 | */ |
||
196 | static pcap_t *septel_activate(pcap_t* handle) { |
||
197 | /* Initialize some components of the pcap structure. */ |
||
198 | handle->linktype = DLT_MTP2; |
||
199 | |||
200 | handle->bufsize = 0; |
||
201 | |||
202 | /* |
||
203 | * "select()" and "poll()" don't work on Septel queues |
||
204 | */ |
||
205 | handle->selectable_fd = -1; |
||
206 | |||
207 | handle->read_op = septel_read; |
||
208 | handle->inject_op = septel_inject; |
||
209 | handle->setfilter_op = septel_setfilter; |
||
210 | handle->set_datalink_op = NULL; /* can't change data link type */ |
||
211 | handle->getnonblock_op = pcap_getnonblock_fd; |
||
212 | handle->setnonblock_op = septel_setnonblock; |
||
213 | handle->stats_op = septel_stats; |
||
214 | |||
215 | return 0; |
||
216 | } |
||
217 | |||
218 | pcap_t *septel_create(const char *device, char *ebuf, int *is_ours) { |
||
219 | const char *cp; |
||
220 | pcap_t *p; |
||
221 | |||
222 | /* Does this look like the Septel device? */ |
||
223 | cp = strrchr(device, '/'); |
||
224 | if (cp == NULL) |
||
225 | cp = device; |
||
226 | if (strcmp(cp, "septel") != 0) { |
||
227 | /* Nope, it's not "septel" */ |
||
228 | *is_ours = 0; |
||
229 | return NULL; |
||
230 | } |
||
231 | |||
232 | /* OK, it's probably ours. */ |
||
233 | *is_ours = 1; |
||
234 | |||
235 | p = pcap_create_common(device, ebuf, sizeof (struct pcap_septel)); |
||
236 | if (p == NULL) |
||
237 | return NULL; |
||
238 | |||
239 | p->activate_op = septel_activate; |
||
240 | return p; |
||
241 | } |
||
242 | |||
243 | static int septel_stats(pcap_t *p, struct pcap_stat *ps) { |
||
244 | struct pcap_septel *handlep = p->priv; |
||
245 | /*handlep->stat.ps_recv = 0;*/ |
||
246 | /*handlep->stat.ps_drop = 0;*/ |
||
247 | |||
248 | *ps = handlep->stat; |
||
249 | |||
250 | return 0; |
||
251 | } |
||
252 | |||
253 | |||
254 | int |
||
255 | septel_findalldevs(pcap_if_t **devlistp, char *errbuf) |
||
256 | { |
||
257 | return (pcap_add_if(devlistp,"septel",0, |
||
258 | "Intel/Septel device",errbuf)); |
||
259 | } |
||
260 | |||
261 | |||
262 | /* |
||
263 | * Installs the given bpf filter program in the given pcap structure. There is |
||
264 | * no attempt to store the filter in kernel memory as that is not supported |
||
265 | * with Septel cards. |
||
266 | */ |
||
267 | static int septel_setfilter(pcap_t *p, struct bpf_program *fp) { |
||
268 | if (!p) |
||
269 | return -1; |
||
270 | if (!fp) { |
||
271 | strncpy(p->errbuf, "setfilter: No filter specified", |
||
272 | sizeof(p->errbuf)); |
||
273 | return -1; |
||
274 | } |
||
275 | |||
276 | /* Make our private copy of the filter */ |
||
277 | |||
278 | if (install_bpf_program(p, fp) < 0) { |
||
279 | snprintf(p->errbuf, sizeof(p->errbuf), |
||
280 | "malloc: %s", pcap_strerror(errno)); |
||
281 | return -1; |
||
282 | } |
||
283 | |||
284 | return (0); |
||
285 | } |
||
286 | |||
287 | |||
288 | static int |
||
289 | septel_setnonblock(pcap_t *p, int nonblock, char *errbuf) |
||
290 | { |
||
291 | fprintf(errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices"); |
||
292 | return (-1); |
||
293 | } |