1 /*
2  * libpri: An implementation of Primary Rate ISDN
3  *
4  * Written by Mark Spencer <markster@digium.com>
5  *
6  * Copyright (C) 2001-2005, Digium, Inc.
7  * All Rights Reserved.
8  */
9 
10 /*
11  * See http://www.asterisk.org for more information about
12  * the Asterisk project. Please do not directly contact
13  * any of the maintainers of this project for assistance;
14  * the project provides a web site, mailing lists and IRC
15  * channels for your use.
16  *
17  * This program is free software, distributed under the terms of
18  * the GNU General Public License Version 2 as published by the
19  * Free Software Foundation. See the LICENSE file included with
20  * this program for more details.
21  *
22  * In addition, when this program is distributed with Asterisk in
23  * any form that would qualify as a 'combined work' or as a
24  * 'derivative work' (but not mere aggregation), you can redistribute
25  * and/or modify the combination under the terms of the license
26  * provided with that copy of Asterisk, instead of the license
27  * terms granted here.
28  */
29 
30 /*
31  * This program tests libpri call reception using a zaptel interface.
32  * Its state machines are setup for RECEIVING CALLS ONLY, so if you
33  * are trying to both place and receive calls you have to a bit more.
34  */
35 
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <stdlib.h>
39 #include <fcntl.h>
40 #include <errno.h>
41 #include <string.h>
42 #include <sys/ioctl.h>
43 #include <sys/select.h>
44 #include <sys/types.h>
45 #include <dahdi/user.h>
46 #include "libpri.h"
47 #include "pri_q921.h"
48 #include "pri_q931.h"
49 
pri_open(char * dev)50 static int pri_open(char *dev)
51 {
52 	int dfd;
53 	struct dahdi_params p;
54 
55 	dfd = open(dev, O_RDWR);
56 	if (dfd < 0) {
57 		fprintf(stderr, "Failed to open dchannel '%s': %s\n", dev, strerror(errno));
58 		return -1;
59 	}
60 	if (ioctl(dfd, DAHDI_GET_PARAMS, &p)) {
61 		fprintf(stderr, "Unable to get parameters on '%s': %s\n", dev, strerror(errno));
62 		return -1;
63 	}
64 	if ((p.sigtype != DAHDI_SIG_HDLCRAW) && (p.sigtype != DAHDI_SIG_HDLCFCS)) {
65 		fprintf(stderr, "%s is in %d signalling, not FCS HDLC or RAW HDLC mode\n", dev, p.sigtype);
66 		return -1;
67 	}
68 	return dfd;
69 }
70 
dump_packet(struct pri * pri,char * buf,int len,int txrx)71 static void dump_packet(struct pri *pri, char *buf, int len, int txrx)
72 {
73 	q921_h *h = (q921_h *)buf;
74 	q921_dump(pri, h, len, PRI_DEBUG_ALL, txrx);
75 	if (!((h->h.data[0] & Q921_FRAMETYPE_MASK) & 0x3)) {
76 		q931_dump(pri, h->h.tei, (q931_h *)(h->i.data), len - 4 - 2 /* FCS */, txrx);
77 	}
78 	fflush(stdout);
79 	fflush(stderr);
80 }
81 
82 
pri_bridge(int d1,int d2)83 static void pri_bridge(int d1, int d2)
84 {
85 	char buf[1024];
86 	fd_set fds;
87 	int max;
88 	int e;
89 	int res;
90 	for(;;) {
91 		FD_ZERO(&fds);
92 		FD_SET(d1, &fds);
93 		FD_SET(d2, &fds);
94 		max = d1;
95 		if (max < d2)
96 			max = d2;
97 		ioctl(d1, DAHDI_GETEVENT, &e);
98 		ioctl(d2, DAHDI_GETEVENT, &e);
99 		res = select(max + 1, &fds, NULL, NULL, NULL);
100 		if (res < 0) {
101 			fprintf(stderr, "Select returned %d: %s\n", res, strerror(errno));
102 			continue;
103 		};
104 		if (FD_ISSET(d1, &fds)) {
105 			/* Copy from d1 to d2 */
106 			res = read(d1, buf, sizeof(buf));
107 			dump_packet((struct pri *)NULL, buf, res, 1);
108 			res = write(d2, buf, res);
109 		}
110 		if (FD_ISSET(d2, &fds)) {
111 			/* Copy from d2 to d1 */
112 			res = read(d2, buf, sizeof(buf));
113 			dump_packet((struct pri *)NULL, buf, res, 0);
114 			res = write(d1, buf, res);
115 		}
116 	}
117 }
118 
my_pri_message(struct pri * pri,char * stuff)119 static void my_pri_message(struct pri *pri, char *stuff)
120 {
121 	fprintf(stdout, "%s", stuff);
122 }
123 
my_pri_error(struct pri * pri,char * stuff)124 static void my_pri_error(struct pri *pri, char *stuff)
125 {
126 	fprintf(stderr, "%s", stuff);
127 }
128 
main(int argc,char * argv[])129 int main(int argc, char *argv[])
130 {
131 	int d1, d2;
132 
133 	if (argc < 3) {
134 		fprintf(stderr, "Usage: pridump <dev1> <dev2>\n");
135 		exit(1);
136 	}
137 
138 	pri_set_message(my_pri_message);
139 	pri_set_error(my_pri_error);
140 
141 	d1 = pri_open(argv[1]);
142 	if (d1 < 0)
143 		exit(1);
144 	d2 = pri_open(argv[2]);
145 	if (d2 < 0)
146 		exit(1);
147 	pri_bridge(d1, d2);
148 	return 0;
149 }
150