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