blob: cc8ff6723b8859cf7cbe991f122d24d8ae83e4c6 [file] [log] [blame]
Holger Freyther3cf00fb2009-06-08 10:33:06 +00001/* isdnsync.c
2 *
3 * Author Andreas Eversberg <jolly@eversberg.eu>
4 *
5 * All rights reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01008 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
Holger Freyther3cf00fb2009-06-08 10:33:06 +000010 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010015 * GNU Affero General Public License for more details.
Holger Freyther3cf00fb2009-06-08 10:33:06 +000016 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010017 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Holger Freyther3cf00fb2009-06-08 10:33:06 +000019 *
20 */
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <unistd.h>
25#include <sys/ioctl.h>
Holger Freyther3cf00fb2009-06-08 10:33:06 +000026#include <sys/stat.h>
27#include <fcntl.h>
28#include <errno.h>
29#include <sys/socket.h>
30#include "mISDNif.h"
31#define MISDN_OLD_AF_COMPATIBILITY
32#define AF_COMPATIBILITY_FUNC
33#include "compat_af_isdn.h"
34
35int card = 0;
36int sock = -1;
37
38int mISDN_open(void)
39{
40 int fd, ret;
41 struct mISDN_devinfo devinfo;
42 struct sockaddr_mISDN l2addr;
43
44 fd = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
45 if (fd < 0) {
46 fprintf(stderr, "could not open socket (%s)\n", strerror(errno));
47 return fd;
48 }
49 devinfo.id = card;
50 ret = ioctl(fd, IMGETDEVINFO, &devinfo);
51 if (ret < 0) {
52 fprintf(stderr,"could not send IOCTL IMGETCOUNT (%s)\n", strerror(errno));
53 close(fd);
54 return ret;
55 }
56 close(fd);
57 if (!(devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
58 && !(devinfo.Dprotocols & (1 << ISDN_P_TE_E1))) {
59 fprintf(stderr,"Interface does not support TE mode (%s)\n", strerror(errno));
Holger Freyther3cf00fb2009-06-08 10:33:06 +000060 return ret;
61 }
62 fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_LAPD_TE);
63 if (fd < 0) {
64 fprintf(stderr,"could not open ISDN_P_LAPD_TE socket (%s)\n", strerror(errno));
65 return fd;
66 }
67 l2addr.family = AF_ISDN;
68 l2addr.dev = card;
69 l2addr.channel = 0;
70 l2addr.sapi = 0;
71 l2addr.tei = 0;
72 ret = bind(fd, (struct sockaddr *)&l2addr, sizeof(l2addr));
73 if (ret < 0) {
74 fprintf(stderr,"could not bind socket for card %d (%s)\n", card, strerror(errno));
75 close(fd);
76 return ret;
77 }
78 sock = fd;
79
80 return sock;
81}
82
83
84void mISDN_handle(void)
85{
86 int ret;
87 fd_set rfd;
88 struct timeval tv;
89 struct sockaddr_mISDN addr;
90 socklen_t alen;
91 unsigned char buffer[2048];
92 struct mISDNhead *hh = (struct mISDNhead *)buffer;
93 int l1 = 0, l2 = 0, tei = 0;
94
95 while(1) {
96again:
97 FD_ZERO(&rfd);
98 FD_SET(sock, &rfd);
99 tv.tv_sec = 2;
100 tv.tv_usec = 0;
101 ret = select(sock+1, &rfd, NULL, NULL, &tv);
102 if (ret < 0) {
103 if (errno == EINTR)
104 continue;
105 fprintf(stderr, "%s aborted: %s\n", __FUNCTION__, strerror(errno));
106 break;
107 }
108 if (FD_ISSET(sock, &rfd)) {
109 alen = sizeof(addr);
110 ret = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *) &addr, &alen);
111 if (ret < 0) {
112 fprintf(stderr, "%s read socket error %s\n", __FUNCTION__, strerror(errno));
113 } else if (ret < MISDN_HEADER_LEN) {
114 fprintf(stderr, "%s read socket shor frame\n", __FUNCTION__);
115 } else {
116 switch(hh->prim) {
117 case MPH_ACTIVATE_IND:
118 case PH_ACTIVATE_IND:
119 if (!l1) {
120 printf("PH_ACTIVATE\n");
121 printf("*** Sync available from interface :-)\n");
122 l1 = 1;
123 }
124 goto again;
125 break;
126 case MPH_DEACTIVATE_IND:
127 case PH_DEACTIVATE_IND:
128 if (l1) {
129 printf("PH_DEACTIVATE\n");
130 printf("*** Lost sync on interface :-(\n");
131 l1 = 0;
132 }
133 goto again;
134 break;
135 case DL_ESTABLISH_IND:
136 case DL_ESTABLISH_CNF:
137 printf("DL_ESTABLISH\n");
138 l2 = 1;
139 goto again;
140 break;
141 case DL_RELEASE_IND:
142 case DL_RELEASE_CNF:
143 printf("DL_RELEASE\n");
144 l2 = 0;
145 goto again;
146 break;
147 case DL_INFORMATION_IND:
148 printf("DL_INFORMATION (tei %d sapi %d)\n", addr.tei, addr.sapi);
149 tei = 1;
150 break;
151 default:
152// printf("prim %x\n", hh->prim);
153 goto again;
154 }
155 }
156 }
157 if (tei && !l2) {
158 hh->prim = DL_ESTABLISH_REQ;
159 printf("-> activating layer 2\n");
160 sendto(sock, buffer, MISDN_HEADER_LEN, 0, (struct sockaddr *) &addr, alen);
161 }
162 }
163}
164
165int main(int argc, char *argv[])
166{
167 int ret;
168
169 if (argc <= 1)
170 {
171 printf("Usage: %s <card>\n\n", argv[0]);
172 printf("Opens given card number in TE-mode PTP and tries to keep layer 2 established.\n");
173 printf("This keeps layer 1 activated to retrieve a steady sync signal from network.\n");
174 return(0);
175 }
176
177 card = atoi(argv[1]);
178
179 init_af_isdn();
180
181 if ((ret = mISDN_open() < 0))
182 return(ret);
183
184 mISDN_handle();
185
186 close(sock);
187
188 return 0;
189}