blob: d8fca761ba3fb80f6a6b4d8c47f5b3696d0bf445 [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));
60 close(fd);
61 return ret;
62 }
63 fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_LAPD_TE);
64 if (fd < 0) {
65 fprintf(stderr,"could not open ISDN_P_LAPD_TE socket (%s)\n", strerror(errno));
66 return fd;
67 }
68 l2addr.family = AF_ISDN;
69 l2addr.dev = card;
70 l2addr.channel = 0;
71 l2addr.sapi = 0;
72 l2addr.tei = 0;
73 ret = bind(fd, (struct sockaddr *)&l2addr, sizeof(l2addr));
74 if (ret < 0) {
75 fprintf(stderr,"could not bind socket for card %d (%s)\n", card, strerror(errno));
76 close(fd);
77 return ret;
78 }
79 sock = fd;
80
81 return sock;
82}
83
84
85void mISDN_handle(void)
86{
87 int ret;
88 fd_set rfd;
89 struct timeval tv;
90 struct sockaddr_mISDN addr;
91 socklen_t alen;
92 unsigned char buffer[2048];
93 struct mISDNhead *hh = (struct mISDNhead *)buffer;
94 int l1 = 0, l2 = 0, tei = 0;
95
96 while(1) {
97again:
98 FD_ZERO(&rfd);
99 FD_SET(sock, &rfd);
100 tv.tv_sec = 2;
101 tv.tv_usec = 0;
102 ret = select(sock+1, &rfd, NULL, NULL, &tv);
103 if (ret < 0) {
104 if (errno == EINTR)
105 continue;
106 fprintf(stderr, "%s aborted: %s\n", __FUNCTION__, strerror(errno));
107 break;
108 }
109 if (FD_ISSET(sock, &rfd)) {
110 alen = sizeof(addr);
111 ret = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *) &addr, &alen);
112 if (ret < 0) {
113 fprintf(stderr, "%s read socket error %s\n", __FUNCTION__, strerror(errno));
114 } else if (ret < MISDN_HEADER_LEN) {
115 fprintf(stderr, "%s read socket shor frame\n", __FUNCTION__);
116 } else {
117 switch(hh->prim) {
118 case MPH_ACTIVATE_IND:
119 case PH_ACTIVATE_IND:
120 if (!l1) {
121 printf("PH_ACTIVATE\n");
122 printf("*** Sync available from interface :-)\n");
123 l1 = 1;
124 }
125 goto again;
126 break;
127 case MPH_DEACTIVATE_IND:
128 case PH_DEACTIVATE_IND:
129 if (l1) {
130 printf("PH_DEACTIVATE\n");
131 printf("*** Lost sync on interface :-(\n");
132 l1 = 0;
133 }
134 goto again;
135 break;
136 case DL_ESTABLISH_IND:
137 case DL_ESTABLISH_CNF:
138 printf("DL_ESTABLISH\n");
139 l2 = 1;
140 goto again;
141 break;
142 case DL_RELEASE_IND:
143 case DL_RELEASE_CNF:
144 printf("DL_RELEASE\n");
145 l2 = 0;
146 goto again;
147 break;
148 case DL_INFORMATION_IND:
149 printf("DL_INFORMATION (tei %d sapi %d)\n", addr.tei, addr.sapi);
150 tei = 1;
151 break;
152 default:
153// printf("prim %x\n", hh->prim);
154 goto again;
155 }
156 }
157 }
158 if (tei && !l2) {
159 hh->prim = DL_ESTABLISH_REQ;
160 printf("-> activating layer 2\n");
161 sendto(sock, buffer, MISDN_HEADER_LEN, 0, (struct sockaddr *) &addr, alen);
162 }
163 }
164}
165
166int main(int argc, char *argv[])
167{
168 int ret;
169
170 if (argc <= 1)
171 {
172 printf("Usage: %s <card>\n\n", argv[0]);
173 printf("Opens given card number in TE-mode PTP and tries to keep layer 2 established.\n");
174 printf("This keeps layer 1 activated to retrieve a steady sync signal from network.\n");
175 return(0);
176 }
177
178 card = atoi(argv[1]);
179
180 init_af_isdn();
181
182 if ((ret = mISDN_open() < 0))
183 return(ret);
184
185 mISDN_handle();
186
187 close(sock);
188
189 return 0;
190}