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