1335640Shselasky/* 2335640Shselasky * pcap-septel.c: Packet capture interface for Intel/Septel card. 3335640Shselasky * 4335640Shselasky * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY 5335640Shselasky * (+961 3 485243) 6335640Shselasky */ 7335640Shselasky 8335640Shselasky#ifdef HAVE_CONFIG_H 9335640Shselasky#include <config.h> 10335640Shselasky#endif 11335640Shselasky 12335640Shselasky#include <sys/param.h> 13335640Shselasky 14335640Shselasky#include <stdlib.h> 15335640Shselasky#include <string.h> 16335640Shselasky#include <errno.h> 17335640Shselasky 18335640Shselasky#include "pcap-int.h" 19335640Shselasky 20335640Shselasky#include <ctype.h> 21335640Shselasky#include <netinet/in.h> 22335640Shselasky#include <sys/mman.h> 23335640Shselasky#include <sys/socket.h> 24335640Shselasky#include <sys/types.h> 25335640Shselasky#include <unistd.h> 26335640Shselasky 27335640Shselasky#include <msg.h> 28335640Shselasky#include <ss7_inc.h> 29335640Shselasky#include <sysgct.h> 30335640Shselasky#include <pack.h> 31335640Shselasky#include <system.h> 32335640Shselasky 33335640Shselasky#include "pcap-septel.h" 34335640Shselasky 35335640Shselaskystatic int septel_setfilter(pcap_t *p, struct bpf_program *fp); 36335640Shselaskystatic int septel_stats(pcap_t *p, struct pcap_stat *ps); 37335640Shselaskystatic int septel_getnonblock(pcap_t *p); 38335640Shselaskystatic int septel_setnonblock(pcap_t *p, int nonblock); 39335640Shselasky 40335640Shselasky/* 41335640Shselasky * Private data for capturing on Septel devices. 42335640Shselasky */ 43335640Shselaskystruct pcap_septel { 44335640Shselasky struct pcap_stat stat; 45335640Shselasky} 46335640Shselasky 47335640Shselasky/* 48335640Shselasky * Read at most max_packets from the capture queue and call the callback 49335640Shselasky * for each of them. Returns the number of packets handled, -1 if an 50335640Shselasky * error occured, or -2 if we were told to break out of the loop. 51335640Shselasky */ 52335640Shselaskystatic int septel_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { 53335640Shselasky 54335640Shselasky struct pcap_septel *ps = p->priv; 55335640Shselasky HDR *h; 56335640Shselasky MSG *m; 57335640Shselasky int processed = 0 ; 58335640Shselasky int t = 0 ; 59335640Shselasky 60335640Shselasky /* identifier for the message queue of the module(upe) from which we are capturing 61335640Shselasky * packets.These IDs are defined in system.txt . By default it is set to 0x2d 62335640Shselasky * so change it to 0xdd for technical reason and therefore the module id for upe becomes: 63335640Shselasky * LOCAL 0xdd * upe - Example user part task */ 64335640Shselasky unsigned int id = 0xdd; 65335640Shselasky 66335640Shselasky /* process the packets */ 67335640Shselasky do { 68335640Shselasky 69335640Shselasky unsigned short packet_len = 0; 70335640Shselasky int caplen = 0; 71335640Shselasky int counter = 0; 72335640Shselasky struct pcap_pkthdr pcap_header; 73335640Shselasky u_char *dp ; 74335640Shselasky 75335640Shselasky /* 76335640Shselasky * Has "pcap_breakloop()" been called? 77335640Shselasky */ 78335640Shselaskyloop: 79335640Shselasky if (p->break_loop) { 80335640Shselasky /* 81335640Shselasky * Yes - clear the flag that indicates that 82335640Shselasky * it has, and return -2 to indicate that 83335640Shselasky * we were told to break out of the loop. 84335640Shselasky */ 85335640Shselasky p->break_loop = 0; 86335640Shselasky return -2; 87335640Shselasky } 88335640Shselasky 89335640Shselasky /*repeat until a packet is read 90335640Shselasky *a NULL message means : 91335640Shselasky * when no packet is in queue or all packets in queue already read */ 92335640Shselasky do { 93335640Shselasky /* receive packet in non-blocking mode 94335640Shselasky * GCT_grab is defined in the septel library software */ 95335640Shselasky h = GCT_grab(id); 96335640Shselasky 97335640Shselasky m = (MSG*)h; 98335640Shselasky /* a couter is added here to avoid an infinite loop 99335640Shselasky * that will cause our capture program GUI to freeze while waiting 100335640Shselasky * for a packet*/ 101335640Shselasky counter++ ; 102335640Shselasky 103335640Shselasky } 104335640Shselasky while ((m == NULL)&& (counter< 100)) ; 105335640Shselasky 106335640Shselasky if (m != NULL) { 107335640Shselasky 108335640Shselasky t = h->type ; 109335640Shselasky 110335640Shselasky /* catch only messages with type = 0xcf00 or 0x8f01 corrsponding to ss7 messages*/ 111335640Shselasky /* XXX = why not use API_MSG_TX_REQ for 0xcf00 and API_MSG_RX_IND 112335640Shselasky * for 0x8f01? */ 113335640Shselasky if ((t != 0xcf00) && (t != 0x8f01)) { 114335640Shselasky relm(h); 115335640Shselasky goto loop ; 116335640Shselasky } 117335640Shselasky 118335640Shselasky /* XXX - is API_MSG_RX_IND for an MTP2 or MTP3 message? */ 119335640Shselasky dp = get_param(m);/* get pointer to MSG parameter area (m->param) */ 120335640Shselasky packet_len = m->len; 121335640Shselasky caplen = p->snapshot ; 122335640Shselasky 123335640Shselasky 124335640Shselasky if (caplen > packet_len) { 125335640Shselasky 126335640Shselasky caplen = packet_len; 127335640Shselasky } 128335640Shselasky /* Run the packet filter if there is one. */ 129335640Shselasky if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) { 130335640Shselasky 131335640Shselasky 132335640Shselasky /* get a time stamp , consisting of : 133335640Shselasky * 134335640Shselasky * pcap_header.ts.tv_sec: 135335640Shselasky * ---------------------- 136335640Shselasky * a UNIX format time-in-seconds when he packet was captured, 137335640Shselasky * i.e. the number of seconds since Epoch time (January 1,1970, 00:00:00 GMT) 138335640Shselasky * 139335640Shselasky * pcap_header.ts.tv_usec : 140335640Shselasky * ------------------------ 141335640Shselasky * the number of microseconds since that second 142335640Shselasky * when the packet was captured 143335640Shselasky */ 144335640Shselasky 145335640Shselasky (void)gettimeofday(&pcap_header.ts, NULL); 146335640Shselasky 147335640Shselasky /* Fill in our own header data */ 148335640Shselasky pcap_header.caplen = caplen; 149335640Shselasky pcap_header.len = packet_len; 150335640Shselasky 151335640Shselasky /* Count the packet. */ 152335640Shselasky ps->stat.ps_recv++; 153335640Shselasky 154335640Shselasky /* Call the user supplied callback function */ 155335640Shselasky callback(user, &pcap_header, dp); 156335640Shselasky 157335640Shselasky processed++ ; 158335640Shselasky 159335640Shselasky } 160335640Shselasky /* after being processed the packet must be 161335640Shselasky *released in order to receive another one */ 162335640Shselasky relm(h); 163335640Shselasky }else 164335640Shselasky processed++; 165335640Shselasky 166335640Shselasky } 167335640Shselasky while (processed < cnt) ; 168335640Shselasky 169335640Shselasky return processed ; 170335640Shselasky} 171335640Shselasky 172335640Shselasky 173335640Shselaskystatic int 174335640Shselaskyseptel_inject(pcap_t *handle, const void *buf _U_, size_t size _U_) 175335640Shselasky{ 176356341Scy pcap_strlcpy(handle->errbuf, "Sending packets isn't supported on Septel cards", 177335640Shselasky PCAP_ERRBUF_SIZE); 178335640Shselasky return (-1); 179335640Shselasky} 180335640Shselasky 181335640Shselasky/* 182335640Shselasky * Activate a handle for a live capture from the given Septel device. Always pass a NULL device 183335640Shselasky * The promisc flag is ignored because Septel cards have built-in tracing. 184335640Shselasky * The timeout is also ignored as it is not supported in hardware. 185335640Shselasky * 186335640Shselasky * See also pcap(3). 187335640Shselasky */ 188335640Shselaskystatic pcap_t *septel_activate(pcap_t* handle) { 189335640Shselasky /* Initialize some components of the pcap structure. */ 190335640Shselasky handle->linktype = DLT_MTP2; 191335640Shselasky 192335640Shselasky /* 193335640Shselasky * Turn a negative snapshot value (invalid), a snapshot value of 194335640Shselasky * 0 (unspecified), or a value bigger than the normal maximum 195335640Shselasky * value, into the maximum allowed value. 196335640Shselasky * 197335640Shselasky * If some application really *needs* a bigger snapshot 198335640Shselasky * length, we should just increase MAXIMUM_SNAPLEN. 199335640Shselasky */ 200335640Shselasky if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN) 201335640Shselasky handle->snapshot = MAXIMUM_SNAPLEN; 202335640Shselasky 203335640Shselasky handle->bufsize = 0; 204335640Shselasky 205335640Shselasky /* 206335640Shselasky * "select()" and "poll()" don't work on Septel queues 207335640Shselasky */ 208335640Shselasky handle->selectable_fd = -1; 209335640Shselasky 210335640Shselasky handle->read_op = septel_read; 211335640Shselasky handle->inject_op = septel_inject; 212335640Shselasky handle->setfilter_op = septel_setfilter; 213335640Shselasky handle->set_datalink_op = NULL; /* can't change data link type */ 214335640Shselasky handle->getnonblock_op = septel_getnonblock; 215335640Shselasky handle->setnonblock_op = septel_setnonblock; 216335640Shselasky handle->stats_op = septel_stats; 217335640Shselasky 218335640Shselasky return 0; 219335640Shselasky} 220335640Shselasky 221335640Shselaskypcap_t *septel_create(const char *device, char *ebuf, int *is_ours) { 222335640Shselasky const char *cp; 223335640Shselasky pcap_t *p; 224335640Shselasky 225335640Shselasky /* Does this look like the Septel device? */ 226335640Shselasky cp = strrchr(device, '/'); 227335640Shselasky if (cp == NULL) 228335640Shselasky cp = device; 229335640Shselasky if (strcmp(cp, "septel") != 0) { 230335640Shselasky /* Nope, it's not "septel" */ 231335640Shselasky *is_ours = 0; 232335640Shselasky return NULL; 233335640Shselasky } 234335640Shselasky 235335640Shselasky /* OK, it's probably ours. */ 236335640Shselasky *is_ours = 1; 237335640Shselasky 238335640Shselasky p = pcap_create_common(ebuf, sizeof (struct pcap_septel)); 239335640Shselasky if (p == NULL) 240335640Shselasky return NULL; 241335640Shselasky 242335640Shselasky p->activate_op = septel_activate; 243335640Shselasky /* 244335640Shselasky * Set these up front, so that, even if our client tries 245335640Shselasky * to set non-blocking mode before we're activated, or 246335640Shselasky * query the state of non-blocking mode, they get an error, 247335640Shselasky * rather than having the non-blocking mode option set 248335640Shselasky * for use later. 249335640Shselasky */ 250335640Shselasky p->getnonblock_op = septel_getnonblock; 251335640Shselasky p->setnonblock_op = septel_setnonblock; 252335640Shselasky return p; 253335640Shselasky} 254335640Shselasky 255335640Shselaskystatic int septel_stats(pcap_t *p, struct pcap_stat *ps) { 256335640Shselasky struct pcap_septel *handlep = p->priv; 257335640Shselasky /*handlep->stat.ps_recv = 0;*/ 258335640Shselasky /*handlep->stat.ps_drop = 0;*/ 259335640Shselasky 260335640Shselasky *ps = handlep->stat; 261335640Shselasky 262335640Shselasky return 0; 263335640Shselasky} 264335640Shselasky 265335640Shselasky 266335640Shselaskyint 267335640Shselaskyseptel_findalldevs(pcap_if_list_t *devlistp, char *errbuf) 268335640Shselasky{ 269335640Shselasky /* 270335640Shselasky * XXX - do the notions of "up", "running", or "connected" apply here? 271335640Shselasky */ 272335640Shselasky if (add_dev(devlistp,"septel",0,"Intel/Septel device",errbuf) == NULL) 273335640Shselasky return -1; 274335640Shselasky return 0; 275335640Shselasky} 276335640Shselasky 277335640Shselasky 278335640Shselasky/* 279335640Shselasky * Installs the given bpf filter program in the given pcap structure. There is 280335640Shselasky * no attempt to store the filter in kernel memory as that is not supported 281335640Shselasky * with Septel cards. 282335640Shselasky */ 283335640Shselaskystatic int septel_setfilter(pcap_t *p, struct bpf_program *fp) { 284335640Shselasky if (!p) 285335640Shselasky return -1; 286335640Shselasky if (!fp) { 287335640Shselasky strncpy(p->errbuf, "setfilter: No filter specified", 288335640Shselasky sizeof(p->errbuf)); 289335640Shselasky return -1; 290335640Shselasky } 291335640Shselasky 292335640Shselasky /* Make our private copy of the filter */ 293335640Shselasky 294335640Shselasky if (install_bpf_program(p, fp) < 0) 295335640Shselasky return -1; 296335640Shselasky 297335640Shselasky return (0); 298335640Shselasky} 299335640Shselasky 300335640Shselasky/* 301335640Shselasky * We don't support non-blocking mode. I'm not sure what we'd 302335640Shselasky * do to support it and, given that we don't support select()/ 303335640Shselasky * poll()/epoll_wait()/kevent() etc., it probably doesn't 304335640Shselasky * matter. 305335640Shselasky */ 306335640Shselaskystatic int 307335640Shselaskyseptel_getnonblock(pcap_t *p) 308335640Shselasky{ 309335640Shselasky fprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices"); 310335640Shselasky return (-1); 311335640Shselasky} 312335640Shselasky 313335640Shselaskystatic int 314335640Shselaskyseptel_setnonblock(pcap_t *p, int nonblock _U_) 315335640Shselasky{ 316335640Shselasky fprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices"); 317335640Shselasky return (-1); 318335640Shselasky} 319335640Shselasky 320335640Shselasky#ifdef SEPTEL_ONLY 321335640Shselasky/* 322335640Shselasky * This libpcap build supports only Septel cards, not regular network 323335640Shselasky * interfaces. 324335640Shselasky */ 325335640Shselasky 326335640Shselasky/* 327335640Shselasky * There are no regular interfaces, just Septel interfaces. 328335640Shselasky */ 329335640Shselaskyint 330335640Shselaskypcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf) 331335640Shselasky{ 332335640Shselasky return (0); 333335640Shselasky} 334335640Shselasky 335335640Shselasky/* 336335640Shselasky * Attempts to open a regular interface fail. 337335640Shselasky */ 338335640Shselaskypcap_t * 339335640Shselaskypcap_create_interface(const char *device, char *errbuf) 340335640Shselasky{ 341335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 342335640Shselasky "This version of libpcap only supports Septel cards"); 343335640Shselasky return (NULL); 344335640Shselasky} 345335640Shselasky 346335640Shselasky/* 347335640Shselasky * Libpcap version string. 348335640Shselasky */ 349335640Shselaskyconst char * 350335640Shselaskypcap_lib_version(void) 351335640Shselasky{ 352335640Shselasky return (PCAP_VERSION_STRING " (Septel-only)"); 353335640Shselasky} 354335640Shselasky#endif 355