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 #if HAVE_NETINET_IN_H
00023 #include <netinet/in.h>
00024 #endif
00025
00026 #if HAVE_DMALLOC_H
00027 #include <dmalloc.h>
00028 #endif
00029
00030 #include <net-snmp/types.h>
00031 #include <net-snmp/output_api.h>
00032 #include <net-snmp/config_api.h>
00033
00034 #include <net-snmp/library/snmp_transport.h>
00035 #include <net-snmp/library/snmpIPXDomain.h>
00036
00037 #define SNMP_IPX_DEFAULT_PORT 36879
00038 static netsnmp_tdomain ipxDomain;
00039
00040
00041
00042
00043
00044
00045 static char *
00046 netsnmp_ipx_fmtaddr(netsnmp_transport *t, void *data, int len)
00047 {
00048 struct sockaddr_ipx *to = NULL;
00049
00050 if (data != NULL && len == sizeof(struct sockaddr_ipx)) {
00051 to = (struct sockaddr_ipx *) data;
00052 } else if (t != NULL && t->data != NULL) {
00053 to = (struct sockaddr_ipx *) t->data;
00054 }
00055 if (to == NULL) {
00056 return strdup("IPX: unknown");
00057 } else {
00058 char tmp[64];
00059 sprintf(tmp, "IPX: %08X:%02X%02X%02X%02X%02X%02X/%hu",
00060 ntohl(to->sipx_network), to->sipx_node[0],
00061 to->sipx_node[1], to->sipx_node[2], to->sipx_node[3],
00062 to->sipx_node[4], to->sipx_node[5], ntohs(to->sipx_port));
00063 return strdup(tmp);
00064 }
00065 }
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 static int
00076 netsnmp_ipx_recv(netsnmp_transport *t, void *buf, int size,
00077 void **opaque, int *olength)
00078 {
00079 int rc = -1;
00080 socklen_t fromlen = sizeof(struct sockaddr);
00081 struct sockaddr *from;
00082
00083 if (t != NULL && t->sock >= 0) {
00084 from = (struct sockaddr *)malloc(sizeof(struct sockaddr_ipx));
00085 if (from == NULL) {
00086 *opaque = NULL;
00087 *olength = 0;
00088 return -1;
00089 } else {
00090 memset(from, 0, fromlen);
00091 }
00092
00093 while (rc < 0) {
00094 rc = recvfrom(t->sock, buf, size, 0, from, &fromlen);
00095 if (rc < 0 && errno != EINTR) {
00096 break;
00097 }
00098 }
00099
00100 if (rc >= 0) {
00101 char *str = netsnmp_ipx_fmtaddr(NULL, from, fromlen);
00102 DEBUGMSGTL(("netsnmp_ipx","recvfrom fd %d got %d bytes(from %s)\n",
00103 t->sock, rc, str));
00104 free(str);
00105 } else {
00106 DEBUGMSGTL(("netsnmp_ipx", "recvfrom fd %d err %d (\"%s\")\n",
00107 t->sock, errno, strerror(errno)));
00108 }
00109 *opaque = (void *) from;
00110 *olength = sizeof(struct sockaddr_ipx);
00111 }
00112 return rc;
00113 }
00114
00115
00116
00117 static int
00118 netsnmp_ipx_send(netsnmp_transport *t, void *buf, int size,
00119 void **opaque, int *olength)
00120 {
00121 int rc = -1;
00122 struct sockaddr *to = NULL;
00123
00124 if (opaque != NULL && *opaque != NULL &&
00125 *olength == sizeof(struct sockaddr_ipx)) {
00126 to = (struct sockaddr *) (*opaque);
00127 } else if (t != NULL && t->data != NULL &&
00128 t->data_length == sizeof(struct sockaddr_ipx)) {
00129 to = (struct sockaddr *) (t->data);
00130 }
00131
00132 if (to != NULL && t != NULL && t->sock >= 0) {
00133 char *str = netsnmp_ipx_fmtaddr(NULL, (void *)to,
00134 sizeof(struct sockaddr_ipx));
00135 DEBUGMSGTL(("netsnmp_ipx", "send %d bytes from %p to %s on fd %d\n",
00136 size, buf, str, t->sock));
00137 free(str);
00138 while (rc < 0) {
00139 rc = sendto(t->sock, buf, size, 0, to, sizeof(struct sockaddr));
00140 if (rc < 0 && errno != EINTR) {
00141 break;
00142 }
00143 }
00144 }
00145 return rc;
00146 }
00147
00148
00149
00150 static int
00151 netsnmp_ipx_close(netsnmp_transport *t)
00152 {
00153 int rc = -1;
00154 if (t->sock >= 0) {
00155 #ifndef HAVE_CLOSESOCKET
00156 rc = close(t->sock);
00157 #else
00158 rc = closesocket(t->sock);
00159 #endif
00160 t->sock = -1;
00161 }
00162 return rc;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 netsnmp_transport *
00174 netsnmp_ipx_transport(struct sockaddr_ipx *addr, int local)
00175 {
00176 netsnmp_transport *t = NULL;
00177 int rc = 0;
00178 char *str = NULL;
00179
00180 if (addr == NULL || addr->sipx_family != AF_IPX) {
00181 return NULL;
00182 }
00183
00184 t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
00185 if (t == NULL) {
00186 return NULL;
00187 }
00188
00189 str = netsnmp_ipx_fmtaddr(NULL, (void *)addr,
00190 sizeof(struct sockaddr_ipx));
00191 DEBUGMSGTL(("netsnmp_ipx", "open %s %s\n", local ? "local" : "remote",
00192 str));
00193 free(str);
00194
00195 memset(t, 0, sizeof(netsnmp_transport));
00196
00197 t->domain = netsnmpIPXDomain;
00198 t->domain_length = netsnmpIPXDomain_len;
00199
00200 t->sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
00201 if (t->sock < 0) {
00202 netsnmp_transport_free(t);
00203 return NULL;
00204 }
00205
00206 if (local) {
00207 t->local = (unsigned char*)malloc(12);
00208 if (t->local == NULL) {
00209 netsnmp_transport_free(t);
00210 return NULL;
00211 }
00212 memcpy(&(t->local[00]), (u_char *) & (addr->sipx_network), 4);
00213 memcpy(&(t->local[04]), (u_char *) & (addr->sipx_node), 6);
00214 memcpy(&(t->local[10]), (u_char *) & (addr->sipx_port), 2);
00215 t->local_length = 12;
00216
00217
00218
00219
00220
00221
00222
00223 rc = bind(t->sock, (struct sockaddr *) addr,
00224 sizeof(struct sockaddr));
00225 if (rc != 0) {
00226 netsnmp_ipx_close(t);
00227 netsnmp_transport_free(t);
00228 return NULL;
00229 }
00230 t->data = NULL;
00231 t->data_length = 0;
00232 } else {
00233 t->remote = (unsigned char*)malloc(12);
00234 if (t->remote == NULL) {
00235 netsnmp_transport_free(t);
00236 return NULL;
00237 }
00238 memcpy(&(t->remote[00]), (u_char *) & (addr->sipx_network), 4);
00239 memcpy(&(t->remote[04]), (u_char *) & (addr->sipx_node), 6);
00240 memcpy(&(t->remote[10]), (u_char *) & (addr->sipx_port), 2);
00241 t->remote_length = 12;
00242
00243
00244
00245
00246
00247
00248 t->data = malloc(sizeof(struct sockaddr_ipx));
00249 if (t->data == NULL) {
00250 netsnmp_transport_free(t);
00251 return NULL;
00252 }
00253 memcpy(t->data, addr, sizeof(struct sockaddr_ipx));
00254 t->data_length = sizeof(struct sockaddr_ipx);
00255 }
00256
00257
00258
00259
00260
00261
00262 t->msgMaxSize = 576 - 30;
00263 t->f_recv = netsnmp_ipx_recv;
00264 t->f_send = netsnmp_ipx_send;
00265 t->f_close = netsnmp_ipx_close;
00266 t->f_accept = NULL;
00267 t->f_fmtaddr = netsnmp_ipx_fmtaddr;
00268
00269 return t;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279 int
00280 netsnmp_sockaddr_ipx2(struct sockaddr_ipx *addr, const char *peername,
00281 const char *default_target)
00282 {
00283 char *input = NULL, *def = NULL;
00284 const char *network, *node, *port;
00285 char *tmp;
00286 unsigned long i;
00287
00288 if (addr == NULL) {
00289 return 0;
00290 }
00291 memset(addr, 0, sizeof(struct sockaddr_ipx));
00292
00293 DEBUGMSGTL(("netsnmp_sockaddr_ipx",
00294 "addr %p, peername \"%s\" default_target \"%s\"\n",
00295 addr, peername ? peername : "[NIL]",
00296 default_target ? default_target : "[NIL]"));
00297
00298 addr->sipx_family = AF_IPX;
00299 addr->sipx_type = 4;
00300
00301 network = input = strdup(peername ? peername : "");
00302 tmp = strchr(network, ':');
00303 if (tmp != NULL) {
00304 DEBUGMSGTL(("netsnmp_sockaddr_ipx", "Node identified\n"));
00305 *tmp++ = '\0';
00306 node = tmp;
00307 tmp = strchr(tmp, '/');
00308 } else {
00309 node = NULL;
00310 tmp = strchr(network, '/');
00311 }
00312 if (tmp != NULL) {
00313 DEBUGMSGTL(("netsnmp_sockaddr_ipx", "Port identified\n"));
00314 *tmp++ = '\0';
00315 port = tmp;
00316 } else
00317 port = NULL;
00318
00319 DEBUGMSGTL(("netsnmp_sockaddr_ipx", "Address: %s:%s/%s\n",
00320 network ? network : "[NIL]", node ? node : "[NIL]",
00321 port ? port : "[NIL]"));
00322
00323 def = strdup(default_target ? default_target : "");
00324 if (network == NULL || *network == '\0')
00325 network = def;
00326 tmp = strchr(def, ':');
00327 if (tmp != NULL) {
00328 *tmp++ = '\0';
00329 if (node == NULL || *node == '\0')
00330 node = tmp;
00331 tmp = strchr(tmp, '/');
00332 } else
00333 tmp = strchr(def, '/');
00334 if (tmp != NULL) {
00335 *tmp++ = '\0';
00336 if (port == NULL || *port == '\0')
00337 port = tmp;
00338 }
00339
00340 DEBUGMSGTL(("netsnmp_sockaddr_ipx", "Address: %s:%s/%s\n",
00341 network ? network : "[NIL]", node ? node : "[NIL]",
00342 port ? port : "[NIL]"));
00343
00344 if (network == NULL || *network == '\0')
00345 network = "0";
00346
00347 if (node == NULL || *node == '\0')
00348 node = "000000000000";
00349
00350 if (port == NULL || *port == '\0')
00351 #define val(x) __STRING(x)
00352 port = val(SNMP_IPX_DEFAULT_PORT);
00353 #undef val
00354
00355 DEBUGMSGTL(("netsnmp_sockaddr_ipx", "Address: %s:%s/%s\n",
00356 network ? network : "[NIL]", node ? node : "[NIL]",
00357 port ? port : "[NIL]"));
00358
00359 if(sscanf(network, "%8lx%*c", &i) == 1) {
00360 DEBUGMSGTL(("netsnmp_sockaddr_ipx", "network parsed okay\n"));
00361 addr->sipx_network = htonl(i);
00362 } else {
00363 DEBUGMSGTL(("netsnmp_sockaddr_ipx",
00364 "failed to parse network part of address\n"));
00365 free(def);
00366 free(input);
00367 return 0;
00368 }
00369
00370 if(sscanf(node, "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%*c",
00371 &addr->sipx_node[0], &addr->sipx_node[1],
00372 &addr->sipx_node[2], &addr->sipx_node[3],
00373 &addr->sipx_node[4], &addr->sipx_node[5]) == 6) {
00374 DEBUGMSGTL(("netsnmp_sockaddr_ipx", "node parsed okay\n"));
00375 } else {
00376 DEBUGMSGTL(("netsnmp_sockaddr_ipx",
00377 "failed to parse node part of address\n"));
00378 free(def);
00379 free(input);
00380 return 0;
00381 }
00382
00383 if(sscanf(port, "%lu%*c", &i) == 1) {
00384 DEBUGMSGTL(("netsnmp_sockaddr_ipx", "port parsed okay\n"));
00385 addr->sipx_port = htons(i);
00386 } else {
00387 DEBUGMSGTL(("netsnmp_sockaddr_ipx",
00388 "failed to parse port part of address\n"));
00389 free(def);
00390 free(input);
00391 return 0;
00392 }
00393
00394 free(def);
00395 free(input);
00396 return 1;
00397 }
00398
00399
00400
00401 int
00402 netsnmp_sockaddr_ipx(struct sockaddr_ipx *addr, const char *peername)
00403 {
00404 return netsnmp_sockaddr_ipx2(addr, peername, NULL);
00405 }
00406
00407
00408
00409 netsnmp_transport *
00410 netsnmp_ipx_create_tstring(const char *str, int local,
00411 const char *default_target)
00412 {
00413 struct sockaddr_ipx addr;
00414
00415 if (netsnmp_sockaddr_ipx2(&addr, str, default_target)) {
00416 return netsnmp_ipx_transport(&addr, local);
00417 } else {
00418 return NULL;
00419 }
00420 }
00421
00422
00423
00424 netsnmp_transport *
00425 netsnmp_ipx_create_ostring(const u_char * o, size_t o_len, int local)
00426 {
00427 struct sockaddr_ipx addr;
00428
00429 if (o_len == 12) {
00430 addr.sipx_family = AF_IPX;
00431 memcpy((u_char *) & (addr.sipx_network), &(o[00]), 4);
00432 memcpy((u_char *) & (addr.sipx_node), &(o[04]), 6);
00433 memcpy((u_char *) & (addr.sipx_port), &(o[10]), 2);
00434 return netsnmp_ipx_transport(&addr, local);
00435 }
00436 return NULL;
00437 }
00438
00439
00440
00441 void
00442 netsnmp_ipx_ctor(void)
00443 {
00444 ipxDomain.name = netsnmpIPXDomain;
00445 ipxDomain.name_length = netsnmpIPXDomain_len;
00446 ipxDomain.prefix = (const char**)calloc(2, sizeof(char *));
00447 ipxDomain.prefix[0] = "ipx";
00448
00449 ipxDomain.f_create_from_tstring_new = netsnmp_ipx_create_tstring;
00450 ipxDomain.f_create_from_ostring = netsnmp_ipx_create_ostring;
00451
00452 netsnmp_tdomain_register(&ipxDomain);
00453 }