00001 #include <net-snmp/net-snmp-config.h>
00002
00003 #include <stdio.h>
00004 #include <sys/types.h>
00005 #include <ctype.h>
00006 #include <errno.h>
00007
00008 #if HAVE_STRING_H
00009 #include <string.h>
00010 #else
00011 #include <strings.h>
00012 #endif
00013 #if HAVE_STDLIB_H
00014 #include <stdlib.h>
00015 #endif
00016 #if HAVE_UNISTD_H
00017 #include <unistd.h>
00018 #endif
00019 #if HAVE_SYS_SOCKET_H
00020 #include <sys/socket.h>
00021 #endif
00022 #include <atm.h>
00023
00024 #if HAVE_DMALLOC_H
00025 #include <dmalloc.h>
00026 #endif
00027
00028 #include <net-snmp/types.h>
00029 #include <net-snmp/output_api.h>
00030 #include <net-snmp/config_api.h>
00031
00032 #include <net-snmp/library/snmp_transport.h>
00033 #include <net-snmp/library/snmpAAL5PVCDomain.h>
00034
00035
00036 oid netsnmp_AAL5PVCDomain[10] = { ENTERPRISE_MIB, 3, 3, 3 };
00037 static netsnmp_tdomain aal5pvcDomain;
00038
00039
00040
00041
00042
00043
00044
00045 static char *
00046 netsnmp_aal5pvc_fmtaddr(netsnmp_transport *t, void *data, int len)
00047 {
00048 struct sockaddr_atmpvc *to = NULL;
00049
00050 if (data != NULL && len == sizeof(struct sockaddr_atmpvc)) {
00051 to = (struct sockaddr_atmpvc *) data;
00052 } else if (t != NULL && t->data != NULL &&
00053 t->data_length == sizeof(struct sockaddr_atmpvc)) {
00054 to = (struct sockaddr_atmpvc *) t->data;
00055 }
00056 if (to == NULL) {
00057 return strdup("AAL5 PVC: unknown");
00058 } else {
00059 char tmp[64];
00060 sprintf(tmp, "AAL5 PVC: %hd.%hd.%d", to->sap_addr.itf,
00061 to->sap_addr.vpi, to->sap_addr.vci);
00062 return strdup(tmp);
00063 }
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 static int
00075 netsnmp_aal5pvc_recv(netsnmp_transport *t, void *buf, int size,
00076 void **opaque, int *olength)
00077 {
00078 int rc = -1;
00079
00080 if (t != NULL && t->sock >= 0) {
00081 while (rc < 0) {
00082 rc = recv(t->sock, buf, size, 0);
00083 if (rc < 0 && errno != EINTR) {
00084 break;
00085 }
00086 }
00087
00088 if (rc >= 0) {
00089 char *str = netsnmp_aal5pvc_fmtaddr(t, NULL, 0);
00090 DEBUGMSGTL(("netsnmp_aal5pvc",
00091 "recv on fd %d got %d bytes (from %s)\n", t->sock,
00092 rc, str));
00093 free(str);
00094 } else {
00095 DEBUGMSGTL(("netsnmp_aal5pvc", "recv on fd %d err %d (\"%s\")\n",
00096 t->sock, errno, strerror(errno)));
00097 }
00098 *opaque = NULL;
00099 *olength = 0;
00100 }
00101 return rc;
00102 }
00103
00104
00105
00106 static int
00107 netsnmp_aal5pvc_send(netsnmp_transport *t, void *buf, int size,
00108 void **opaque, int *olength)
00109 {
00110 int rc = -1;
00111 struct sockaddr *to = NULL;
00112
00113 if (opaque != NULL && *opaque != NULL &&
00114 *olength == sizeof(struct sockaddr_atmpvc)) {
00115 to = (struct sockaddr *) (*opaque);
00116 } else if (t != NULL && t->data != NULL &&
00117 t->data_length == sizeof(struct sockaddr_atmpvc)) {
00118 to = (struct sockaddr *) (t->data);
00119 }
00120
00121 if (to != NULL && t != NULL && t->sock >= 0) {
00122 char *str = netsnmp_aal5pvc_fmtaddr(NULL, (void *)to,
00123 sizeof(struct sockaddr_atmpvc));
00124 DEBUGMSGTL(("netsnmp_aal5pvc","send %d bytes from %p to %s on fd %d\n",
00125 size, buf, str, t->sock));
00126 free(str);
00127 while (rc < 0) {
00128 rc = send(t->sock, buf, size, 0);
00129 if (rc < 0 && errno != EINTR) {
00130 break;
00131 }
00132 }
00133 }
00134 return rc;
00135 }
00136
00137
00138
00139 static int
00140 netsnmp_aal5pvc_close(netsnmp_transport *t)
00141 {
00142 int rc = -1;
00143
00144 if (t->sock >= 0) {
00145 DEBUGMSGTL(("netsnmp_aal5pvc", "close fd %d\n", t->sock));
00146 #ifndef HAVE_CLOSESOCKET
00147 rc = close(t->sock);
00148 #else
00149 rc = closesocket(t->sock);
00150 #endif
00151 t->sock = -1;
00152 }
00153 return rc;
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 netsnmp_transport *
00165 netsnmp_aal5pvc_transport(struct sockaddr_atmpvc *addr, int local)
00166 {
00167 char *str = NULL;
00168 struct atm_qos qos;
00169 netsnmp_transport *t = NULL;
00170
00171 if (addr == NULL || addr->sap_family != AF_ATMPVC) {
00172 return NULL;
00173 }
00174
00175 t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
00176 if (t == NULL) {
00177 return NULL;
00178 }
00179
00180 str = netsnmp_aal5pvc_fmtaddr(NULL, (void *) addr,
00181 sizeof(struct sockaddr_atmpvc));
00182 DEBUGMSGTL(("netsnmp_aal5pvc", "open %s %s\n", local ? "local" : "remote",
00183 str));
00184 free(str);
00185
00186 memset(t, 0, sizeof(netsnmp_transport));
00187
00188 t->domain = netsnmp_AAL5PVCDomain;
00189 t->domain_length =
00190 sizeof(netsnmp_AAL5PVCDomain) / sizeof(netsnmp_AAL5PVCDomain[0]);
00191
00192 t->sock = socket(PF_ATMPVC, SOCK_DGRAM, 0);
00193 if (t->sock < 0) {
00194 DEBUGMSGTL(("netsnmp_aal5pvc","socket failed (%s)\n",strerror(errno)));
00195 netsnmp_transport_free(t);
00196 return NULL;
00197 }
00198 DEBUGMSGTL(("netsnmp_aal5pvc", "fd %d opened\n", t->sock));
00199
00200
00201
00202
00203
00204 memset(&qos, 0, sizeof(struct atm_qos));
00205 qos.aal = ATM_AAL5;
00206 qos.rxtp.traffic_class = ATM_UBR;
00207 qos.rxtp.max_sdu = SNMP_MAX_LEN;
00208 qos.txtp = qos.rxtp;
00209
00210 if (setsockopt(t->sock, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0) {
00211 DEBUGMSGTL(("netsnmp_aal5pvc", "setsockopt failed (%s)\n",
00212 strerror(errno)));
00213 netsnmp_aal5pvc_close(t);
00214 netsnmp_transport_free(t);
00215 return NULL;
00216 }
00217
00218 if (local) {
00219 t->local = malloc(8);
00220 if (t->local == NULL) {
00221 netsnmp_transport_free(t);
00222 return NULL;
00223 }
00224 t->local[0] = (addr->sap_addr.itf & 0xff00) >> 8;
00225 t->local[1] = (addr->sap_addr.itf & 0x00ff) >> 0;
00226 t->local[2] = (addr->sap_addr.vpi & 0xff00) >> 8;
00227 t->local[3] = (addr->sap_addr.vpi & 0x00ff) >> 0;
00228 t->local[4] = (addr->sap_addr.vci & 0xff000000) >> 24;
00229 t->local[5] = (addr->sap_addr.vci & 0x00ff0000) >> 16;
00230 t->local[6] = (addr->sap_addr.vci & 0x0000ff00) >> 8;
00231 t->local[7] = (addr->sap_addr.vci & 0x000000ff) >> 0;
00232 t->local_length = 8;
00233
00234 if (bind(t->sock, (struct sockaddr *) addr,
00235 sizeof(struct sockaddr_atmpvc)) < 0) {
00236 DEBUGMSGTL(("netsnmp_aal5pvc", "bind failed (%s)\n",
00237 strerror(errno)));
00238 netsnmp_aal5pvc_close(t);
00239 netsnmp_transport_free(t);
00240 return NULL;
00241 }
00242 } else {
00243 t->remote = malloc(8);
00244 if (t->remote == NULL) {
00245 netsnmp_transport_free(t);
00246 return NULL;
00247 }
00248 t->remote[0] = (addr->sap_addr.itf & 0xff00) >> 8;
00249 t->remote[1] = (addr->sap_addr.itf & 0x00ff) >> 0;
00250 t->remote[2] = (addr->sap_addr.vpi & 0xff00) >> 8;
00251 t->remote[3] = (addr->sap_addr.vpi & 0x00ff) >> 0;
00252 t->remote[4] = (addr->sap_addr.vci & 0xff000000) >> 24;
00253 t->remote[5] = (addr->sap_addr.vci & 0x00ff0000) >> 16;
00254 t->remote[6] = (addr->sap_addr.vci & 0x0000ff00) >> 8;
00255 t->remote[7] = (addr->sap_addr.vci & 0x000000ff) >> 0;
00256 t->remote_length = 8;
00257
00258 if (connect(t->sock, (struct sockaddr *) addr,
00259 sizeof(struct sockaddr_atmpvc)) < 0) {
00260 DEBUGMSGTL(("netsnmp_aal5pvc", "connect failed (%s)\n",
00261 strerror(errno)));
00262 netsnmp_aal5pvc_close(t);
00263 netsnmp_transport_free(t);
00264 return NULL;
00265 }
00266 }
00267
00268 t->data = malloc(sizeof(struct sockaddr_atmpvc));
00269 if (t->data == NULL) {
00270 netsnmp_transport_free(t);
00271 return NULL;
00272 }
00273 memcpy(t->data, addr, sizeof(struct sockaddr_atmpvc));
00274 t->data_length = sizeof(struct sockaddr_atmpvc);
00275
00276
00277
00278
00279
00280 t->msgMaxSize = 0xffff;
00281 t->f_recv = netsnmp_aal5pvc_recv;
00282 t->f_send = netsnmp_aal5pvc_send;
00283 t->f_close = netsnmp_aal5pvc_close;
00284 t->f_accept = NULL;
00285 t->f_fmtaddr = netsnmp_aal5pvc_fmtaddr;
00286
00287 return t;
00288 }
00289
00290
00291
00292 netsnmp_transport *
00293 netsnmp_aal5pvc_create_tstring(const char *str, int local)
00294 {
00295 struct sockaddr_atmpvc addr;
00296
00297 if (str != NULL) {
00298 addr.sap_family = AF_ATMPVC;
00299
00300 if (sscanf(str, "%hd.%hd.%d", &(addr.sap_addr.itf),
00301 &(addr.sap_addr.vpi), &(addr.sap_addr.vci)) == 3) {
00302 return netsnmp_aal5pvc_transport(&addr, local);
00303 } else if (sscanf(str, "%hd.%d", &(addr.sap_addr.vpi),
00304 &(addr.sap_addr.vci)) == 2) {
00305 addr.sap_addr.itf = 0;
00306 return netsnmp_aal5pvc_transport(&addr, local);
00307 } else if (sscanf(str, "%d", &(addr.sap_addr.vci)) == 1) {
00308 addr.sap_addr.itf = 0;
00309 addr.sap_addr.vpi = 0;
00310 return netsnmp_aal5pvc_transport(&addr, local);
00311 } else {
00312 return NULL;
00313 }
00314 } else {
00315 return NULL;
00316 }
00317 }
00318
00319
00320
00321 netsnmp_transport *
00322 netsnmp_aal5pvc_create_ostring(const u_char * o, size_t o_len, int local)
00323 {
00324 struct sockaddr_atmpvc addr;
00325
00326 if (o_len == 8) {
00327 addr.sap_family = AF_ATMPVC;
00328 addr.sap_addr.itf = (o[0] << 8) + (o[1] << 0);
00329 addr.sap_addr.vpi = (o[2] << 8) + (o[3] << 0);
00330 addr.sap_addr.vci =
00331 (o[4] << 24) + (o[5] << 16) + (o[6] << 8) + (o[7] << 0);
00332 return netsnmp_aal5pvc_transport(&addr, local);
00333 }
00334
00335 return NULL;
00336 }
00337
00338
00339
00340 void
00341 netsnmp_aal5pvc_ctor(void)
00342 {
00343 aal5pvcDomain.name = netsnmp_AAL5PVCDomain;
00344 aal5pvcDomain.name_length = sizeof(netsnmp_AAL5PVCDomain) / sizeof(oid);
00345 aal5pvcDomain.prefix = calloc(3, sizeof(char *));
00346 aal5pvcDomain.prefix[0] = "aal5pvc";
00347 aal5pvcDomain.prefix[1] = "pvc";
00348
00349 aal5pvcDomain.f_create_from_tstring = netsnmp_aal5pvc_create_tstring;
00350 aal5pvcDomain.f_create_from_ostring = netsnmp_aal5pvc_create_ostring;
00351
00352 netsnmp_tdomain_register(&aal5pvcDomain);
00353 }