1 /* 2 * pcap-septel.c: Packet capture interface for Intel/Septel card. 3 * 4 * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY 5 * (+961 3 485243) 6 */ 7 8 #ifdef HAVE_CONFIG_H 9 #include <config.h> 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 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 26 #include <msg.h> 27 #include <ss7_inc.h> 28 #include <sysgct.h> 29 #include <pack.h> 30 #include <system.h> 31 32 #include "pcap-septel.h" 33 34 static int septel_stats(pcap_t *p, struct pcap_stat *ps); 35 static int septel_getnonblock(pcap_t *p); 36 static int septel_setnonblock(pcap_t *p, int nonblock); 37 38 /* 39 * Private data for capturing on Septel devices. 40 */ 41 struct pcap_septel { 42 struct pcap_stat stat; 43 } 44 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 48 * error occurred, or -2 if we were told to break out of the loop. 49 */ 50 static int septel_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { 51 52 struct pcap_septel *ps = p->priv; 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 counter 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 corresponding 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. */ 127 if ((p->fcode.bf_insns == NULL) || pcap_filter(p->fcode.bf_insns, dp, packet_len, caplen)) { 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. */ 150 ps->stat.ps_recv++; 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 172 septel_inject(pcap_t *handle, const void *buf _U_, int size _U_) 173 { 174 pcap_strlcpy(handle->errbuf, "Sending packets isn't supported on Septel cards", 175 PCAP_ERRBUF_SIZE); 176 return (-1); 177 } 178 179 /* 180 * Activate a handle for a live capture from the given Septel device. Always pass a NULL device 181 * The promisc flag is ignored because Septel cards have built-in tracing. 182 * The timeout is also ignored as it is not supported in hardware. 183 * 184 * See also pcap(3). 185 */ 186 static pcap_t *septel_activate(pcap_t* handle) { 187 /* Initialize some components of the pcap structure. */ 188 handle->linktype = DLT_MTP2; 189 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 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; 210 handle->setfilter_op = install_bpf_program; 211 handle->set_datalink_op = NULL; /* can't change data link type */ 212 handle->getnonblock_op = septel_getnonblock; 213 handle->setnonblock_op = septel_setnonblock; 214 handle->stats_op = septel_stats; 215 216 return 0; 217 } 218 219 pcap_t *septel_create(const char *device, char *ebuf, int *is_ours) { 220 const char *cp; 221 pcap_t *p; 222 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 236 p = PCAP_CREATE_COMMON(ebuf, struct pcap_septel); 237 if (p == NULL) 238 return NULL; 239 240 p->activate_op = septel_activate; 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; 250 return p; 251 } 252 253 static int septel_stats(pcap_t *p, struct pcap_stat *ps) { 254 struct pcap_septel *handlep = p->priv; 255 /*handlep->stat.ps_recv = 0;*/ 256 /*handlep->stat.ps_drop = 0;*/ 257 258 *ps = handlep->stat; 259 260 return 0; 261 } 262 263 264 int 265 septel_findalldevs(pcap_if_list_t *devlistp, char *errbuf) 266 { 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; 273 } 274 275 276 /* 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 } 288 289 static int 290 septel_setnonblock(pcap_t *p, int nonblock _U_) 291 { 292 fprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices"); 293 return (-1); 294 } 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 306 pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf) 307 { 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 { 317 snprintf(errbuf, PCAP_ERRBUF_SIZE, 318 "This version of libpcap only supports Septel cards"); 319 return (NULL); 320 } 321 322 /* 323 * Libpcap version string. 324 */ 325 const char * 326 pcap_lib_version(void) 327 { 328 return (PCAP_VERSION_STRING " (Septel-only)"); 329 } 330 #endif 331