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