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