blob: b67947683f4ee613d79a5aca53e63a64401cf237 [file] [log] [blame]
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +08001/* OpenBSC Abis input driver for ip.access */
2
3/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
4 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (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
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23#include <stdio.h>
24#include <unistd.h>
25#include <stdlib.h>
26#include <errno.h>
27#include <string.h>
28#include <time.h>
29#include <sys/fcntl.h>
30#include <sys/types.h>
31#include <sys/socket.h>
32#include <sys/ioctl.h>
33#include <arpa/inet.h>
34
35#include <laf0rge1/select.h>
36#include <laf0rge1/msgb.h>
37#include <laf0rge1/talloc.h>
38#include <ipaccess.h>
39
40
41#ifndef ARRAY_SIZE
42#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
43#endif
44
45#define TS1_ALLOC_SIZE 4096
46
47static const u_int8_t pong[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_PONG };
48static const u_int8_t id_ack[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_ACK };
49static const u_int8_t id_req[] = { 0, 17, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_GET,
50 0x01, IPAC_IDTAG_UNIT,
51 0x01, IPAC_IDTAG_MACADDR,
52 0x01, IPAC_IDTAG_LOCATION1,
53 0x01, IPAC_IDTAG_LOCATION2,
54 0x01, IPAC_IDTAG_EQUIPVERS,
55 0x01, IPAC_IDTAG_SWVERSION,
56 0x01, IPAC_IDTAG_UNITNAME,
57 0x01, IPAC_IDTAG_SERNR,
58 };
59
60static const char *idtag_names[] = {
61 [IPAC_IDTAG_SERNR] = "Serial_Number",
62 [IPAC_IDTAG_UNITNAME] = "Unit_Name",
63 [IPAC_IDTAG_LOCATION1] = "Location_1",
64 [IPAC_IDTAG_LOCATION2] = "Location_2",
65 [IPAC_IDTAG_EQUIPVERS] = "Equipment_Version",
66 [IPAC_IDTAG_SWVERSION] = "Software_Version",
67 [IPAC_IDTAG_IPADDR] = "IP_Address",
68 [IPAC_IDTAG_MACADDR] = "MAC_Address",
69 [IPAC_IDTAG_UNIT] = "Unit_ID",
70};
71
72static const char *ipac_idtag_name(int tag)
73{
74 if (tag >= ARRAY_SIZE(idtag_names))
75 return "unknown";
76
77 return idtag_names[tag];
78}
79
80/* send the id ack */
81int ipaccess_send_id_ack(int fd)
82{
83 return write(fd, id_ack, sizeof(id_ack));
84}
85
86int ipaccess_send_id_req(int fd)
87{
88 return write(fd, id_req, sizeof(id_req));
89}
90
91/* base handling of the ip.access protocol */
92int ipaccess_rcvmsg_base(struct msgb *msg,
93 struct bsc_fd *bfd)
94{
95 u_int8_t msg_type = *(msg->l2h);
96 int ret = 0;
97
98 switch (msg_type) {
99 case IPAC_MSGT_PING:
100 ret = write(bfd->fd, pong, sizeof(pong));
101 break;
102 case IPAC_MSGT_PONG:
103 break;
104 case IPAC_MSGT_ID_ACK:
105 ret = ipaccess_send_id_ack(bfd->fd);
106 break;
107 }
108 return 0;
109}
110
111/*
112 * read one ipa message from the socket
113 * return NULL in case of error
114 */
115struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error)
116{
117 struct msgb *msg = msgb_alloc(TS1_ALLOC_SIZE, "Abis/IP");
118 struct ipaccess_head *hh;
119 int len, ret = 0;
120
121 if (!msg) {
122 *error = -ENOMEM;
123 return NULL;
124 }
125
126 /* first read our 3-byte header */
127 hh = (struct ipaccess_head *) msg->data;
128 ret = recv(bfd->fd, msg->data, 3, 0);
129 if (ret < 0) {
130 msgb_free(msg);
131 *error = ret;
132 return NULL;
133 } else if (ret == 0) {
134 msgb_free(msg);
135 *error = ret;
136 return NULL;
137 }
138
139 msgb_put(msg, ret);
140
141 /* then read te length as specified in header */
142 msg->l2h = msg->data + sizeof(*hh);
143 len = ntohs(hh->len);
144 ret = recv(bfd->fd, msg->l2h, len, 0);
145 if (ret < len) {
146 msgb_free(msg);
147 *error = -EIO;
148 return NULL;
149 }
150 msgb_put(msg, ret);
151
152 return msg;
153}
154
155void ipaccess_prepend_header(struct msgb *msg, int proto)
156{
157 struct ipaccess_head *hh;
158
159 /* prepend the ip.access header */
160 hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh));
161 hh->len = htons(msg->len - sizeof(*hh));
162 hh->proto = proto;
163}
164