pcap-septel.c 9.2 KB

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