Revert "Revert "and added files""
[bcm963xx.git] / userapps / opensource / net-snmp / snmplib / snmpAAL5PVCDomain.c
1 #include <net-snmp/net-snmp-config.h>
2
3 #include <stdio.h>
4 #include <sys/types.h>
5 #include <ctype.h>
6 #include <errno.h>
7
8 #if HAVE_STRING_H
9 #include <string.h>
10 #else
11 #include <strings.h>
12 #endif
13 #if HAVE_STDLIB_H
14 #include <stdlib.h>
15 #endif
16 #if HAVE_UNISTD_H
17 #include <unistd.h>
18 #endif
19 #if HAVE_SYS_SOCKET_H
20 #include <sys/socket.h>
21 #endif
22 #include <atm.h>
23
24 #if HAVE_DMALLOC_H
25 #include <dmalloc.h>
26 #endif
27
28 #include <net-snmp/types.h>
29 #include <net-snmp/output_api.h>
30 #include <net-snmp/config_api.h>
31
32 #include <net-snmp/library/snmp_transport.h>
33 #include <net-snmp/library/snmpAAL5PVCDomain.h>
34
35
36 oid netsnmp_AAL5PVCDomain[10] = { ENTERPRISE_MIB, 3, 3, 3 };
37 static netsnmp_tdomain aal5pvcDomain;
38
39
40 /*
41  * Return a string representing the address in data, or else the "far end"
42  * address if data is NULL.  
43  */
44
45 static char *
46 netsnmp_aal5pvc_fmtaddr(netsnmp_transport *t, void *data, int len)
47 {
48     struct sockaddr_atmpvc *to = NULL;
49
50     if (data != NULL && len == sizeof(struct sockaddr_atmpvc)) {
51         to = (struct sockaddr_atmpvc *) data;
52     } else if (t != NULL && t->data != NULL &&
53                t->data_length == sizeof(struct sockaddr_atmpvc)) {
54         to = (struct sockaddr_atmpvc *) t->data;
55     }
56     if (to == NULL) {
57         return strdup("AAL5 PVC: unknown");
58     } else {
59         char tmp[64];
60         sprintf(tmp, "AAL5 PVC: %hd.%hd.%d", to->sap_addr.itf,
61                 to->sap_addr.vpi, to->sap_addr.vci);
62         return strdup(tmp);
63     }
64 }
65
66
67
68 /*
69  * You can write something into opaque that will subsequently get passed back 
70  * to your send function if you like.  For instance, you might want to
71  * remember where a PDU came from, so that you can send a reply there...  
72  */
73
74 static int
75 netsnmp_aal5pvc_recv(netsnmp_transport *t, void *buf, int size,
76                      void **opaque, int *olength)
77 {
78     int rc = -1;
79
80     if (t != NULL && t->sock >= 0) {
81         while (rc < 0) {
82             rc = recv(t->sock, buf, size, 0);
83             if (rc < 0 && errno != EINTR) {
84                 break;
85             }
86         }
87
88         if (rc >= 0) {
89             char *string = netsnmp_aal5pvc_fmtaddr(t, NULL, 0);
90             DEBUGMSGTL(("netsnmp_aal5pvc",
91                         "recv on fd %d got %d bytes (from %s)\n", t->sock,
92                         rc, string));
93             free(string);
94         } else {
95             DEBUGMSGTL(("netsnmp_aal5pvc", "recv on fd %d err %d (\"%s\")\n", 
96                         t->sock, errno, strerror(errno)));
97         }
98         *opaque = NULL;
99         *olength = 0;
100     }
101     return rc;
102 }
103
104
105
106 static int
107 netsnmp_aal5pvc_send(netsnmp_transport *t, void *buf, int size,
108                   void **opaque, int *olength)
109 {
110     int rc = -1;
111     struct sockaddr *to = NULL;
112
113     if (opaque != NULL && *opaque != NULL &&
114         *olength == sizeof(struct sockaddr_atmpvc)) {
115         to = (struct sockaddr *) (*opaque);
116     } else if (t != NULL && t->data != NULL &&
117                t->data_length == sizeof(struct sockaddr_atmpvc)) {
118         to = (struct sockaddr *) (t->data);
119     }
120
121     if (to != NULL && t != NULL && t->sock >= 0) {
122         char *string = netsnmp_aal5pvc_fmtaddr(NULL, (void *)to,
123                                             sizeof(struct sockaddr_atmpvc));
124         DEBUGMSGTL(("netsnmp_aal5pvc","send %d bytes from %p to %s on fd %d\n",
125                     size, buf, string, t->sock));
126         free(string);
127         while (rc < 0) {
128             rc = send(t->sock, buf, size, 0);
129             if (rc < 0 && errno != EINTR) {
130                 break;
131             }
132         }
133     }
134     return rc;
135 }
136
137
138
139 static int
140 netsnmp_aal5pvc_close(netsnmp_transport *t)
141 {
142     int rc = -1;
143
144     if (t->sock >= 0) {
145         DEBUGMSGTL(("netsnmp_aal5pvc", "close fd %d\n", t->sock));
146 #ifndef HAVE_CLOSESOCKET
147         rc = close(t->sock);
148 #else
149         rc = closesocket(t->sock);
150 #endif
151         t->sock = -1;
152     }
153     return rc;
154 }
155
156
157
158 /*
159  * Open an AAL5 PVC transport for SNMP.  Local is TRUE if addr is the local 
160  * NSAP to bind to (i.e. this is a server-type session); otherwise addr is 
161  * the remote NSAP to send things to.  
162  */
163
164 netsnmp_transport *
165 netsnmp_aal5pvc_transport(struct sockaddr_atmpvc *addr, int local)
166 {
167     char           *string = NULL;
168     struct atm_qos  qos;
169     netsnmp_transport *t = NULL;
170
171     if (addr == NULL || addr->sap_family != AF_ATMPVC) {
172         return NULL;
173     }
174
175     t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
176     if (t == NULL) {
177         return NULL;
178     }
179
180     string = netsnmp_aal5pvc_fmtaddr(NULL, (void *) addr,
181                                   sizeof(struct sockaddr_atmpvc));
182     DEBUGMSGTL(("netsnmp_aal5pvc", "open %s %s\n", local ? "local" : "remote",
183                 string));
184     free(string);
185
186     memset(t, 0, sizeof(netsnmp_transport));
187
188     t->domain = netsnmp_AAL5PVCDomain;
189     t->domain_length =
190         sizeof(netsnmp_AAL5PVCDomain) / sizeof(netsnmp_AAL5PVCDomain[0]);
191
192     t->sock = socket(PF_ATMPVC, SOCK_DGRAM, 0);
193     if (t->sock < 0) {
194         DEBUGMSGTL(("netsnmp_aal5pvc","socket failed (%s)\n",strerror(errno)));
195         netsnmp_transport_free(t);
196         return NULL;
197     }
198     DEBUGMSGTL(("netsnmp_aal5pvc", "fd %d opened\n", t->sock));
199
200     /*
201      * Set up the QOS parameters.  
202      */
203
204     memset(&qos, 0, sizeof(struct atm_qos));
205     qos.aal = ATM_AAL5;
206     qos.rxtp.traffic_class = ATM_UBR;
207     qos.rxtp.max_sdu = SNMP_MAX_LEN;    /*  Hmm -- this is a bit small?  */
208     qos.txtp = qos.rxtp;
209
210     if (setsockopt(t->sock, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0) {
211         DEBUGMSGTL(("netsnmp_aal5pvc", "setsockopt failed (%s)\n",
212                     strerror(errno)));
213         netsnmp_aal5pvc_close(t);
214         netsnmp_transport_free(t);
215         return NULL;
216     }
217
218     if (local) {
219         t->local = malloc(8);
220         if (t->local == NULL) {
221             netsnmp_transport_free(t);
222             return NULL;
223         }
224         t->local[0] = (addr->sap_addr.itf & 0xff00) >> 8;
225         t->local[1] = (addr->sap_addr.itf & 0x00ff) >> 0;
226         t->local[2] = (addr->sap_addr.vpi & 0xff00) >> 8;
227         t->local[3] = (addr->sap_addr.vpi & 0x00ff) >> 0;
228         t->local[4] = (addr->sap_addr.vci & 0xff000000) >> 24;
229         t->local[5] = (addr->sap_addr.vci & 0x00ff0000) >> 16;
230         t->local[6] = (addr->sap_addr.vci & 0x0000ff00) >> 8;
231         t->local[7] = (addr->sap_addr.vci & 0x000000ff) >> 0;
232         t->local_length = 8;
233
234         if (bind(t->sock, (struct sockaddr *) addr,
235                  sizeof(struct sockaddr_atmpvc)) < 0) {
236             DEBUGMSGTL(("netsnmp_aal5pvc", "bind failed (%s)\n",
237                         strerror(errno)));
238             netsnmp_aal5pvc_close(t);
239             netsnmp_transport_free(t);
240             return NULL;
241         }
242     } else {
243         t->remote = malloc(8);
244         if (t->remote == NULL) {
245             netsnmp_transport_free(t);
246             return NULL;
247         }
248         t->remote[0] = (addr->sap_addr.itf & 0xff00) >> 8;
249         t->remote[1] = (addr->sap_addr.itf & 0x00ff) >> 0;
250         t->remote[2] = (addr->sap_addr.vpi & 0xff00) >> 8;
251         t->remote[3] = (addr->sap_addr.vpi & 0x00ff) >> 0;
252         t->remote[4] = (addr->sap_addr.vci & 0xff000000) >> 24;
253         t->remote[5] = (addr->sap_addr.vci & 0x00ff0000) >> 16;
254         t->remote[6] = (addr->sap_addr.vci & 0x0000ff00) >> 8;
255         t->remote[7] = (addr->sap_addr.vci & 0x000000ff) >> 0;
256         t->remote_length = 8;
257
258         if (connect(t->sock, (struct sockaddr *) addr,
259                     sizeof(struct sockaddr_atmpvc)) < 0) {
260             DEBUGMSGTL(("netsnmp_aal5pvc", "connect failed (%s)\n",
261                         strerror(errno)));
262             netsnmp_aal5pvc_close(t);
263             netsnmp_transport_free(t);
264             return NULL;
265         }
266     }
267
268     t->data = malloc(sizeof(struct sockaddr_atmpvc));
269     if (t->data == NULL) {
270         netsnmp_transport_free(t);
271         return NULL;
272     }
273     memcpy(t->data, addr, sizeof(struct sockaddr_atmpvc));
274     t->data_length = sizeof(struct sockaddr_atmpvc);
275
276     /*
277      * 16-bit length field in the trailer, no headers.  
278      */
279
280     t->msgMaxSize = 0xffff;
281     t->f_recv     = netsnmp_aal5pvc_recv;
282     t->f_send     = netsnmp_aal5pvc_send;
283     t->f_close    = netsnmp_aal5pvc_close;
284     t->f_accept   = NULL;
285     t->f_fmtaddr  = netsnmp_aal5pvc_fmtaddr;
286
287     return t;
288 }
289
290
291
292 netsnmp_transport *
293 netsnmp_aal5pvc_create_tstring(const char *string, int local)
294 {
295     struct sockaddr_atmpvc addr;
296
297     if (string != NULL) {
298         addr.sap_family = AF_ATMPVC;
299
300         if (sscanf(string, "%hd.%hd.%d", &(addr.sap_addr.itf),
301                    &(addr.sap_addr.vpi), &(addr.sap_addr.vci)) == 3) {
302             return netsnmp_aal5pvc_transport(&addr, local);
303         } else if (sscanf(string, "%hd.%d", &(addr.sap_addr.vpi),
304                           &(addr.sap_addr.vci)) == 2) {
305             addr.sap_addr.itf = 0;
306             return netsnmp_aal5pvc_transport(&addr, local);
307         } else if (sscanf(string, "%d", &(addr.sap_addr.vci)) == 1) {
308             addr.sap_addr.itf = 0;
309             addr.sap_addr.vpi = 0;
310             return netsnmp_aal5pvc_transport(&addr, local);
311         } else {
312             return NULL;
313         }
314     } else {
315         return NULL;
316     }
317 }
318
319
320
321 netsnmp_transport *
322 netsnmp_aal5pvc_create_ostring(const u_char * o, size_t o_len, int local)
323 {
324     struct sockaddr_atmpvc addr;
325
326     if (o_len == 8) {
327         addr.sap_family = AF_ATMPVC;
328         addr.sap_addr.itf = (o[0] << 8) + (o[1] << 0);
329         addr.sap_addr.vpi = (o[2] << 8) + (o[3] << 0);
330         addr.sap_addr.vci =
331             (o[4] << 24) + (o[5] << 16) + (o[6] << 8) + (o[7] << 0);
332         return netsnmp_aal5pvc_transport(&addr, local);
333     }
334
335     return NULL;
336 }
337
338
339
340 void
341 netsnmp_aal5pvc_ctor(void)
342 {
343     aal5pvcDomain.name = netsnmp_AAL5PVCDomain;
344     aal5pvcDomain.name_length = sizeof(netsnmp_AAL5PVCDomain) / sizeof(oid);
345     aal5pvcDomain.prefix = calloc(3, sizeof(char *));
346     aal5pvcDomain.prefix[0] = "aal5pvc";
347     aal5pvcDomain.prefix[1] = "pvc";
348
349     aal5pvcDomain.f_create_from_tstring = netsnmp_aal5pvc_create_tstring;
350     aal5pvcDomain.f_create_from_ostring = netsnmp_aal5pvc_create_ostring;
351
352     netsnmp_tdomain_register(&aal5pvcDomain);
353 }