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