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