1 /* $NetBSD: pcap-septel.c,v 1.1.1.4 2013/12/31 16:57:25 christos Exp $ */ 2 3 /* 4 * pcap-septel.c: Packet capture interface for Intel/Septel card. 5 * 6 * The functionality of this code attempts to mimic that of pcap-linux as much 7 * as possible. This code is compiled in several different ways depending on 8 * whether SEPTEL_ONLY and HAVE_SEPTEL_API are defined. If HAVE_SEPTEL_API is 9 * not defined it should not get compiled in, otherwise if SEPTEL_ONLY is 10 * defined then the 'septel_' function calls are renamed to 'pcap_' 11 * equivalents. If SEPTEL_ONLY is not defined then nothing is altered - the 12 * septel_ functions will be called as required from their 13 * pcap-linux/equivalents. 14 * 15 * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY 16 * (+961 3 485243) 17 */ 18 19 #ifndef lint 20 static const char rcsid[] _U_ = 21 "@(#) Header: /tcpdump/master/libpcap/pcap-septel.c,v 1.4 2008-04-14 20:40:58 guy Exp "; 22 #endif 23 24 #ifdef HAVE_CONFIG_H 25 #include "config.h" 26 #endif 27 28 #include <sys/param.h> 29 30 #include <stdlib.h> 31 #include <string.h> 32 #include <errno.h> 33 34 #include "pcap-int.h" 35 36 #include <ctype.h> 37 #include <netinet/in.h> 38 #include <sys/mman.h> 39 #include <sys/socket.h> 40 #include <sys/types.h> 41 #include <unistd.h> 42 43 #include <msg.h> 44 #include <ss7_inc.h> 45 #include <sysgct.h> 46 #include <pack.h> 47 #include <system.h> 48 49 #include "pcap-septel.h" 50 51 static int septel_setfilter(pcap_t *p, struct bpf_program *fp); 52 static int septel_stats(pcap_t *p, struct pcap_stat *ps); 53 static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf); 54 55 /* 56 * Private data for capturing on Septel devices. 57 */ 58 struct pcap_septel { 59 struct pcap_stat stat; 60 } 61 62 /* 63 * Read at most max_packets from the capture queue and call the callback 64 * for each of them. Returns the number of packets handled, -1 if an 65 * error occured, or -2 if we were told to break out of the loop. 66 */ 67 static int septel_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { 68 69 struct pcap_septel *ps = p->priv; 70 HDR *h; 71 MSG *m; 72 int processed = 0 ; 73 int t = 0 ; 74 75 /* identifier for the message queue of the module(upe) from which we are capturing 76 * packets.These IDs are defined in system.txt . By default it is set to 0x2d 77 * so change it to 0xdd for technical reason and therefore the module id for upe becomes: 78 * LOCAL 0xdd * upe - Example user part task */ 79 unsigned int id = 0xdd; 80 81 /* process the packets */ 82 do { 83 84 unsigned short packet_len = 0; 85 int caplen = 0; 86 int counter = 0; 87 struct pcap_pkthdr pcap_header; 88 u_char *dp ; 89 90 /* 91 * Has "pcap_breakloop()" been called? 92 */ 93 loop: 94 if (p->break_loop) { 95 /* 96 * Yes - clear the flag that indicates that 97 * it has, and return -2 to indicate that 98 * we were told to break out of the loop. 99 */ 100 p->break_loop = 0; 101 return -2; 102 } 103 104 /*repeat until a packet is read 105 *a NULL message means : 106 * when no packet is in queue or all packets in queue already read */ 107 do { 108 /* receive packet in non-blocking mode 109 * GCT_grab is defined in the septel library software */ 110 h = GCT_grab(id); 111 112 m = (MSG*)h; 113 /* a couter is added here to avoid an infinite loop 114 * that will cause our capture program GUI to freeze while waiting 115 * for a packet*/ 116 counter++ ; 117 118 } 119 while ((m == NULL)&& (counter< 100)) ; 120 121 if (m != NULL) { 122 123 t = h->type ; 124 125 /* catch only messages with type = 0xcf00 or 0x8f01 corrsponding to ss7 messages*/ 126 /* XXX = why not use API_MSG_TX_REQ for 0xcf00 and API_MSG_RX_IND 127 * for 0x8f01? */ 128 if ((t != 0xcf00) && (t != 0x8f01)) { 129 relm(h); 130 goto loop ; 131 } 132 133 /* XXX - is API_MSG_RX_IND for an MTP2 or MTP3 message? */ 134 dp = get_param(m);/* get pointer to MSG parameter area (m->param) */ 135 packet_len = m->len; 136 caplen = p->snapshot ; 137 138 139 if (caplen > packet_len) { 140 141 caplen = packet_len; 142 } 143 /* Run the packet filter if there is one. */ 144 if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) { 145 146 147 /* get a time stamp , consisting of : 148 * 149 * pcap_header.ts.tv_sec: 150 * ---------------------- 151 * a UNIX format time-in-seconds when he packet was captured, 152 * i.e. the number of seconds since Epoch time (January 1,1970, 00:00:00 GMT) 153 * 154 * pcap_header.ts.tv_usec : 155 * ------------------------ 156 * the number of microseconds since that second 157 * when the packet was captured 158 */ 159 160 (void)gettimeofday(&pcap_header.ts, NULL); 161 162 /* Fill in our own header data */ 163 pcap_header.caplen = caplen; 164 pcap_header.len = packet_len; 165 166 /* Count the packet. */ 167 ps->stat.ps_recv++; 168 169 /* Call the user supplied callback function */ 170 callback(user, &pcap_header, dp); 171 172 processed++ ; 173 174 } 175 /* after being processed the packet must be 176 *released in order to receive another one */ 177 relm(h); 178 }else 179 processed++; 180 181 } 182 while (processed < cnt) ; 183 184 return processed ; 185 } 186 187 188 static int 189 septel_inject(pcap_t *handle, const void *buf _U_, size_t size _U_) 190 { 191 strlcpy(handle->errbuf, "Sending packets isn't supported on Septel cards", 192 PCAP_ERRBUF_SIZE); 193 return (-1); 194 } 195 196 /* 197 * Activate a handle for a live capture from the given Septel device. Always pass a NULL device 198 * The promisc flag is ignored because Septel cards have built-in tracing. 199 * The timeout is also ignored as it is not supported in hardware. 200 * 201 * See also pcap(3). 202 */ 203 static pcap_t *septel_activate(pcap_t* handle) { 204 /* Initialize some components of the pcap structure. */ 205 handle->linktype = DLT_MTP2; 206 207 handle->bufsize = 0; 208 209 /* 210 * "select()" and "poll()" don't work on Septel queues 211 */ 212 handle->selectable_fd = -1; 213 214 handle->read_op = septel_read; 215 handle->inject_op = septel_inject; 216 handle->setfilter_op = septel_setfilter; 217 handle->set_datalink_op = NULL; /* can't change data link type */ 218 handle->getnonblock_op = pcap_getnonblock_fd; 219 handle->setnonblock_op = septel_setnonblock; 220 handle->stats_op = septel_stats; 221 222 return 0; 223 } 224 225 pcap_t *septel_create(const char *device, char *ebuf, int *is_ours) { 226 const char *cp; 227 pcap_t *p; 228 229 /* Does this look like the Septel device? */ 230 cp = strrchr(device, '/'); 231 if (cp == NULL) 232 cp = device; 233 if (strcmp(cp, "septel") != 0) { 234 /* Nope, it's not "septel" */ 235 *is_ours = 0; 236 return NULL; 237 } 238 239 /* OK, it's probably ours. */ 240 *is_ours = 1; 241 242 p = pcap_create_common(device, ebuf, sizeof (struct pcap_septel)); 243 if (p == NULL) 244 return NULL; 245 246 p->activate_op = septel_activate; 247 return p; 248 } 249 250 static int septel_stats(pcap_t *p, struct pcap_stat *ps) { 251 struct pcap_septel *handlep = p->priv; 252 /*handlep->stat.ps_recv = 0;*/ 253 /*handlep->stat.ps_drop = 0;*/ 254 255 *ps = handlep->stat; 256 257 return 0; 258 } 259 260 261 int 262 septel_findalldevs(pcap_if_t **devlistp, char *errbuf) 263 { 264 unsigned char *p; 265 const char description[512]= "Intel/Septel device"; 266 char name[512]="septel" ; 267 int ret = 0; 268 pcap_add_if(devlistp,name,0,description,errbuf); 269 270 return (ret); 271 } 272 273 274 /* 275 * Installs the given bpf filter program in the given pcap structure. There is 276 * no attempt to store the filter in kernel memory as that is not supported 277 * with Septel cards. 278 */ 279 static int septel_setfilter(pcap_t *p, struct bpf_program *fp) { 280 if (!p) 281 return -1; 282 if (!fp) { 283 strncpy(p->errbuf, "setfilter: No filter specified", 284 sizeof(p->errbuf)); 285 return -1; 286 } 287 288 /* Make our private copy of the filter */ 289 290 if (install_bpf_program(p, fp) < 0) { 291 snprintf(p->errbuf, sizeof(p->errbuf), 292 "malloc: %s", pcap_strerror(errno)); 293 return -1; 294 } 295 296 return (0); 297 } 298 299 300 static int 301 septel_setnonblock(pcap_t *p, int nonblock, char *errbuf) 302 { 303 fprintf(errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices"); 304 return (-1); 305 } 306