/src/net-snmp/snmplib/transports/snmpIPXDomain.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | #include <net-snmp/net-snmp-config.h> | 
| 2 |  |  | 
| 3 |  | #include <net-snmp/library/snmpIPXDomain.h> | 
| 4 |  |  | 
| 5 |  | #include <stdio.h> | 
| 6 |  | #include <sys/types.h> | 
| 7 |  | #include <ctype.h> | 
| 8 |  | #include <errno.h> | 
| 9 |  |  | 
| 10 |  | #ifdef HAVE_STRING_H | 
| 11 |  | #include <string.h> | 
| 12 |  | #else | 
| 13 |  | #include <strings.h> | 
| 14 |  | #endif | 
| 15 |  | #ifdef HAVE_STDLIB_H | 
| 16 |  | #include <stdlib.h> | 
| 17 |  | #endif | 
| 18 |  | #ifdef HAVE_UNISTD_H | 
| 19 |  | #include <unistd.h> | 
| 20 |  | #endif | 
| 21 |  | #ifdef HAVE_SYS_SOCKET_H | 
| 22 |  | #include <sys/socket.h> | 
| 23 |  | #endif | 
| 24 |  | #ifdef HAVE_NETINET_IN_H | 
| 25 |  | #include <netinet/in.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_assert.h> | 
| 33 |  | #include <net-snmp/library/snmp_transport.h> | 
| 34 |  | #include <net-snmp/library/tools.h> | 
| 35 |  |  | 
| 36 |  | #define SNMP_IPX_DEFAULT_PORT 36879   /*  Specified in RFC 1420.  */ | 
| 37 |  | static netsnmp_tdomain ipxDomain; | 
| 38 |  |  | 
| 39 |  | /* | 
| 40 |  |  * Return a string representing the address in data, or else the "far end" | 
| 41 |  |  * address if data is NULL.   | 
| 42 |  |  */ | 
| 43 |  |  | 
| 44 |  | static char * | 
| 45 |  | netsnmp_ipx_fmtaddr(netsnmp_transport *t, const void *data, int len) | 
| 46 | 0 | { | 
| 47 | 0 |     const struct sockaddr_ipx *to = NULL; | 
| 48 |  | 
 | 
| 49 | 0 |     if (data != NULL && len == sizeof(struct sockaddr_ipx)) { | 
| 50 | 0 |         to = (const struct sockaddr_ipx *) data; | 
| 51 | 0 |     } else if (t != NULL && t->data != NULL) { | 
| 52 | 0 |         to = (const struct sockaddr_ipx *) t->data; | 
| 53 | 0 |     } | 
| 54 | 0 |     if (to == NULL) { | 
| 55 | 0 |         return strdup("IPX: unknown"); | 
| 56 | 0 |     } else { | 
| 57 | 0 |         char *tmp; | 
| 58 |  | 
 | 
| 59 | 0 |         if (asprintf(&tmp, "IPX: %08X:%02X%02X%02X%02X%02X%02X/%hu", | 
| 60 | 0 |          ntohl(to->sipx_network), to->sipx_node[0], | 
| 61 | 0 |          to->sipx_node[1], to->sipx_node[2], to->sipx_node[3], | 
| 62 | 0 |          to->sipx_node[4], to->sipx_node[5], ntohs(to->sipx_port)) | 
| 63 | 0 |       < 0) | 
| 64 | 0 |             tmp = NULL; | 
| 65 | 0 |         return tmp; | 
| 66 | 0 |     } | 
| 67 | 0 | } | 
| 68 |  |  | 
| 69 |  | static void netsnmp_ipx_get_taddr(struct netsnmp_transport_s *t, | 
| 70 |  |                                   void **addr, size_t *addr_len) | 
| 71 | 0 | { | 
| 72 | 0 |     struct sockaddr_ipx *sa = t->remote; | 
| 73 |  | 
 | 
| 74 | 0 |     netsnmp_assert(t->remote_length == sizeof(*sa)); | 
| 75 | 0 |     *addr_len = 12; | 
| 76 | 0 |     if ((*addr = malloc(*addr_len))) { | 
| 77 | 0 |         unsigned char *p = *addr; | 
| 78 |  | 
 | 
| 79 | 0 |         memcpy(p + 0,  &sa->sipx_network, 4); | 
| 80 | 0 |         memcpy(p + 4,  &sa->sipx_node,    6); | 
| 81 | 0 |         memcpy(p + 10, &sa->sipx_port,    2); | 
| 82 | 0 |     } | 
| 83 | 0 | } | 
| 84 |  |  | 
| 85 |  | /* | 
| 86 |  |  * You can write something into opaque that will subsequently get passed back  | 
| 87 |  |  * to your send function if you like.  For instance, you might want to | 
| 88 |  |  * remember where a PDU came from, so that you can send a reply there...   | 
| 89 |  |  */ | 
| 90 |  |  | 
| 91 |  | static int | 
| 92 |  | netsnmp_ipx_recv(netsnmp_transport *t, void *buf, int size, | 
| 93 |  |      void **opaque, int *olength) | 
| 94 | 0 | { | 
| 95 | 0 |     int        rc = -1; | 
| 96 | 0 |     socklen_t      fromlen = sizeof(struct sockaddr); | 
| 97 | 0 |     struct sockaddr *from; | 
| 98 |  | 
 | 
| 99 | 0 |     if (t != NULL && t->sock >= 0) { | 
| 100 | 0 |         from = (struct sockaddr *)malloc(sizeof(struct sockaddr_ipx)); | 
| 101 | 0 |         if (from == NULL) { | 
| 102 | 0 |             *opaque = NULL; | 
| 103 | 0 |             *olength = 0; | 
| 104 | 0 |             return -1; | 
| 105 | 0 |         } else { | 
| 106 | 0 |             memset(from, 0, fromlen); | 
| 107 | 0 |         } | 
| 108 |  |  | 
| 109 | 0 |   while (rc < 0) { | 
| 110 | 0 |     rc = recvfrom(t->sock, buf, size, 0, from, &fromlen); | 
| 111 | 0 |     if (rc < 0 && errno != EINTR) { | 
| 112 | 0 |       break; | 
| 113 | 0 |     } | 
| 114 | 0 |   } | 
| 115 |  | 
 | 
| 116 | 0 |         if (rc >= 0) { | 
| 117 | 0 |             DEBUGIF("netsnmp_ipx") { | 
| 118 | 0 |                 char *str = netsnmp_ipx_fmtaddr(NULL, from, fromlen); | 
| 119 | 0 |                 DEBUGMSGTL(("netsnmp_ipx", | 
| 120 | 0 |                             "recvfrom fd %d got %d bytes(from %s)\n", | 
| 121 | 0 |                             t->sock, rc, str)); | 
| 122 | 0 |                 free(str); | 
| 123 | 0 |             } | 
| 124 | 0 |         } else { | 
| 125 | 0 |             DEBUGMSGTL(("netsnmp_ipx", "recvfrom fd %d err %d (\"%s\")\n", | 
| 126 | 0 |                         t->sock, errno, strerror(errno))); | 
| 127 | 0 |         } | 
| 128 | 0 |         *opaque = (void *) from; | 
| 129 | 0 |         *olength = sizeof(struct sockaddr_ipx); | 
| 130 | 0 |     } | 
| 131 | 0 |     return rc; | 
| 132 | 0 | } | 
| 133 |  |  | 
| 134 |  |  | 
| 135 |  |  | 
| 136 |  | static int | 
| 137 |  | netsnmp_ipx_send(netsnmp_transport *t, const void *buf, int size, | 
| 138 |  |      void **opaque, int *olength) | 
| 139 | 0 | { | 
| 140 | 0 |     int rc = -1; | 
| 141 | 0 |     const struct sockaddr *to = NULL; | 
| 142 |  | 
 | 
| 143 | 0 |     if (opaque != NULL && *opaque != NULL && | 
| 144 | 0 |   *olength == sizeof(struct sockaddr_ipx)) { | 
| 145 | 0 |         to = (const struct sockaddr *) (*opaque); | 
| 146 | 0 |     } else if (t != NULL && t->data != NULL && | 
| 147 | 0 |                t->data_length == sizeof(struct sockaddr_ipx)) { | 
| 148 | 0 |         to = (const struct sockaddr *) (t->data); | 
| 149 | 0 |     } | 
| 150 |  | 
 | 
| 151 | 0 |     if (to != NULL && t != NULL && t->sock >= 0) { | 
| 152 | 0 |         DEBUGIF("netsnmp_ipx") { | 
| 153 | 0 |             char *str = netsnmp_ipx_fmtaddr(NULL, to, | 
| 154 | 0 |                                             sizeof(struct sockaddr_ipx)); | 
| 155 | 0 |             DEBUGMSGTL(("netsnmp_ipx", "send %d bytes from %p to %s on fd %d\n", | 
| 156 | 0 |                         size, buf, str, t->sock)); | 
| 157 | 0 |             free(str); | 
| 158 | 0 |         } | 
| 159 | 0 |   while (rc < 0) { | 
| 160 | 0 |       rc = sendto(t->sock, buf, size, 0, to, sizeof(struct sockaddr)); | 
| 161 | 0 |       if (rc < 0 && errno != EINTR) { | 
| 162 | 0 |     break; | 
| 163 | 0 |       } | 
| 164 | 0 |   } | 
| 165 | 0 |     } | 
| 166 | 0 |     return rc; | 
| 167 | 0 | } | 
| 168 |  |  | 
| 169 |  |  | 
| 170 |  |  | 
| 171 |  | static int | 
| 172 |  | netsnmp_ipx_close(netsnmp_transport *t) | 
| 173 | 0 | { | 
| 174 | 0 |     int rc = -1; | 
| 175 | 0 |     if (t->sock >= 0) { | 
| 176 | 0 | #ifndef HAVE_CLOSESOCKET | 
| 177 | 0 |         rc = close(t->sock); | 
| 178 |  | #else | 
| 179 |  |         rc = closesocket(t->sock); | 
| 180 |  | #endif | 
| 181 | 0 |         t->sock = -1; | 
| 182 | 0 |     } | 
| 183 | 0 |     return rc; | 
| 184 | 0 | } | 
| 185 |  |  | 
| 186 |  |  | 
| 187 |  |  | 
| 188 |  | /* | 
| 189 |  |  * Open a IPX-based transport for SNMP.  Local is TRUE if addr is the local | 
| 190 |  |  * address to bind to (i.e. this is a server-type session); otherwise addr is  | 
| 191 |  |  * the remote address to send things to.   | 
| 192 |  |  */ | 
| 193 |  |  | 
| 194 |  | netsnmp_transport * | 
| 195 |  | netsnmp_ipx_transport(const struct sockaddr_ipx *addr, int local) | 
| 196 | 0 | { | 
| 197 | 0 |     netsnmp_transport *t = NULL; | 
| 198 | 0 |     int             rc = 0; | 
| 199 |  | 
 | 
| 200 |  | #ifdef NETSNMP_NO_LISTEN_SUPPORT | 
| 201 |  |     if (local) | 
| 202 |  |         return NULL; | 
| 203 |  | #endif /* NETSNMP_NO_LISTEN_SUPPORT */ | 
| 204 |  | 
 | 
| 205 | 0 |     if (addr == NULL || addr->sipx_family != AF_IPX) { | 
| 206 | 0 |         return NULL; | 
| 207 | 0 |     } | 
| 208 |  |  | 
| 209 | 0 |     t = SNMP_MALLOC_TYPEDEF(netsnmp_transport); | 
| 210 | 0 |     if (t == NULL) { | 
| 211 | 0 |         return NULL; | 
| 212 | 0 |     } | 
| 213 |  |  | 
| 214 | 0 |     DEBUGIF("netsnmp_ipx") { | 
| 215 | 0 |         char *str = netsnmp_ipx_fmtaddr(NULL, addr, | 
| 216 | 0 |                                   sizeof(struct sockaddr_ipx)); | 
| 217 | 0 |         DEBUGMSGTL(("netsnmp_ipx", "open %s %s\n", local ? "local" : "remote", | 
| 218 | 0 |                     str)); | 
| 219 | 0 |         free(str); | 
| 220 | 0 |     } | 
| 221 |  | 
 | 
| 222 | 0 |     t->domain = netsnmpIPXDomain; | 
| 223 | 0 |     t->domain_length = netsnmpIPXDomain_len; | 
| 224 |  | 
 | 
| 225 | 0 |     t->sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX); | 
| 226 | 0 |     if (t->sock < 0) { | 
| 227 | 0 |         netsnmp_transport_free(t); | 
| 228 | 0 |         return NULL; | 
| 229 | 0 |     } | 
| 230 |  |  | 
| 231 | 0 |     if (local) { | 
| 232 | 0 | #ifndef NETSNMP_NO_LISTEN_SUPPORT | 
| 233 | 0 |         t->local_length = sizeof(*addr); | 
| 234 | 0 |         t->local = netsnmp_memdup(addr, sizeof(*addr)); | 
| 235 | 0 |         if (t->local == NULL) { | 
| 236 | 0 |             netsnmp_transport_free(t); | 
| 237 | 0 |             return NULL; | 
| 238 | 0 |         } | 
| 239 |  |  | 
| 240 |  |         /* | 
| 241 |  |          * This session is inteneded as a server, so we must bind on to the | 
| 242 |  |          * given address (which may include a particular network and/or node | 
| 243 |  |          * address, but definitely includes a port number). | 
| 244 |  |          */ | 
| 245 |  |  | 
| 246 | 0 |         rc = bind(t->sock, addr, sizeof(struct sockaddr)); | 
| 247 | 0 |         if (rc != 0) { | 
| 248 | 0 |             netsnmp_ipx_close(t); | 
| 249 | 0 |             netsnmp_transport_free(t); | 
| 250 | 0 |             return NULL; | 
| 251 | 0 |         } | 
| 252 | 0 |         t->data = NULL; | 
| 253 | 0 |         t->data_length = 0; | 
| 254 |  | #else /* NETSNMP_NO_LISTEN_SUPPORT */ | 
| 255 |  |         return NULL; | 
| 256 |  | #endif /* NETSNMP_NO_LISTEN_SUPPORT */ | 
| 257 | 0 |     } else { | 
| 258 | 0 |         t->remote_length = sizeof(*addr); | 
| 259 | 0 |         t->remote = netsnmp_memdup(addr, sizeof(*addr)); | 
| 260 | 0 |         if (t->remote == NULL) { | 
| 261 | 0 |             netsnmp_transport_free(t); | 
| 262 | 0 |             return NULL; | 
| 263 | 0 |         } | 
| 264 |  |  | 
| 265 |  |         /* | 
| 266 |  |          * This is a client session.  Save the address in the | 
| 267 |  |          * transport-specific data pointer for later use by snmp_ipx_send. | 
| 268 |  |          */ | 
| 269 |  |  | 
| 270 | 0 |         t->data = malloc(sizeof(struct sockaddr_ipx)); | 
| 271 | 0 |         if (t->data == NULL) { | 
| 272 | 0 |             netsnmp_transport_free(t); | 
| 273 | 0 |             return NULL; | 
| 274 | 0 |         } | 
| 275 | 0 |         memcpy(t->data, addr, sizeof(struct sockaddr_ipx)); | 
| 276 | 0 |         t->data_length = sizeof(struct sockaddr_ipx); | 
| 277 | 0 |     } | 
| 278 |  |  | 
| 279 |  |     /* | 
| 280 |  |      * Maximum size of an IPX PDU is 576 bytes including a 30-byte header. | 
| 281 |  |      * Ridiculous!   | 
| 282 |  |      */ | 
| 283 |  |  | 
| 284 | 0 |     t->msgMaxSize = 576 - 30; | 
| 285 | 0 |     t->f_recv     = netsnmp_ipx_recv; | 
| 286 | 0 |     t->f_send     = netsnmp_ipx_send; | 
| 287 | 0 |     t->f_close    = netsnmp_ipx_close; | 
| 288 | 0 |     t->f_accept   = NULL; | 
| 289 | 0 |     t->f_fmtaddr  = netsnmp_ipx_fmtaddr; | 
| 290 | 0 |     t->f_get_taddr = netsnmp_ipx_get_taddr; | 
| 291 |  | 
 | 
| 292 | 0 |     return t; | 
| 293 | 0 | } | 
| 294 |  |  | 
| 295 |  |  | 
| 296 |  |  | 
| 297 |  | /* | 
| 298 |  |  * Attempt to parse a string of the form [%08x]:%12x[/%d] where the parts | 
| 299 |  |  * are the network number, the node address and the port in that order.   | 
| 300 |  |  */ | 
| 301 |  |  | 
| 302 |  | int | 
| 303 |  | netsnmp_sockaddr_ipx2(struct sockaddr_ipx *addr, const char *peername, | 
| 304 |  |           const char *default_target) | 
| 305 | 0 | { | 
| 306 | 0 |     char           *input = NULL, *def = NULL; | 
| 307 | 0 |     const char     *network, *node, *port; | 
| 308 | 0 |     char           *tmp; | 
| 309 | 0 |     unsigned long   i; | 
| 310 |  | 
 | 
| 311 | 0 |     if (addr == NULL) { | 
| 312 | 0 |         return 0; | 
| 313 | 0 |     } | 
| 314 | 0 |     memset(addr, 0, sizeof(struct sockaddr_ipx)); | 
| 315 |  | 
 | 
| 316 | 0 |     DEBUGMSGTL(("netsnmp_sockaddr_ipx", | 
| 317 | 0 |     "addr %p, peername \"%s\" default_target \"%s\"\n", | 
| 318 | 0 |                 addr, peername ? peername : "[NIL]", | 
| 319 | 0 |     default_target ? default_target : "[NIL]")); | 
| 320 |  | 
 | 
| 321 | 0 |     addr->sipx_family = AF_IPX; | 
| 322 | 0 |     addr->sipx_type = 4;        /*  Specified in RFC 1420.  */ | 
| 323 |  | 
 | 
| 324 | 0 |     network = input = strdup(peername ? peername : ""); | 
| 325 | 0 |     tmp = strchr(input, ':'); | 
| 326 | 0 |     if (tmp != NULL) { | 
| 327 | 0 |         DEBUGMSGTL(("netsnmp_sockaddr_ipx", "Node identified\n")); | 
| 328 | 0 |         *tmp++ = '\0'; | 
| 329 | 0 |   node = tmp; | 
| 330 | 0 |         tmp = strchr(tmp, '/'); | 
| 331 | 0 |     } else { | 
| 332 | 0 |         node = NULL; | 
| 333 | 0 |         tmp = strchr(input, '/'); | 
| 334 | 0 |     } | 
| 335 | 0 |     if (tmp != NULL) { | 
| 336 | 0 |         DEBUGMSGTL(("netsnmp_sockaddr_ipx", "Port identified\n")); | 
| 337 | 0 |         *tmp++ = '\0'; | 
| 338 | 0 |         port = tmp; | 
| 339 | 0 |     } else | 
| 340 | 0 |         port = NULL; | 
| 341 |  | 
 | 
| 342 | 0 |     DEBUGMSGTL(("netsnmp_sockaddr_ipx", "Address: %s:%s/%s\n", | 
| 343 | 0 |                 network ? network : "[NIL]", node ? node : "[NIL]", | 
| 344 | 0 |                 port ? port : "[NIL]")); | 
| 345 |  | 
 | 
| 346 | 0 |     def = strdup(default_target ? default_target : ""); | 
| 347 | 0 |     if (network == NULL || *network == '\0') | 
| 348 | 0 |         network = def; | 
| 349 | 0 |     tmp = strchr(def, ':'); | 
| 350 | 0 |     if (tmp != NULL) { | 
| 351 | 0 |         *tmp++ = '\0'; | 
| 352 | 0 |   if (node == NULL || *node == '\0') | 
| 353 | 0 |             node = tmp; | 
| 354 | 0 |         tmp = strchr(tmp, '/'); | 
| 355 | 0 |     } else | 
| 356 | 0 |         tmp = strchr(def, '/'); | 
| 357 | 0 |     if (tmp != NULL) { | 
| 358 | 0 |         *tmp++ = '\0'; | 
| 359 | 0 |         if (port == NULL || *port == '\0') | 
| 360 | 0 |             port = tmp; | 
| 361 | 0 |     } | 
| 362 |  | 
 | 
| 363 | 0 |     DEBUGMSGTL(("netsnmp_sockaddr_ipx", "Address: %s:%s/%s\n", | 
| 364 | 0 |                 network ? network : "[NIL]", node ? node : "[NIL]", | 
| 365 | 0 |                 port ? port : "[NIL]")); | 
| 366 |  | 
 | 
| 367 | 0 |     if (network == NULL || *network == '\0') | 
| 368 | 0 |         network = "0"; | 
| 369 |  | 
 | 
| 370 | 0 |     if (node == NULL || *node == '\0') | 
| 371 | 0 |         node = "000000000000"; | 
| 372 |  | 
 | 
| 373 | 0 |     if (port == NULL || *port == '\0') | 
| 374 | 0 | #define val(x) __STRING(x) | 
| 375 | 0 |         port = val(SNMP_IPX_DEFAULT_PORT); | 
| 376 | 0 | #undef val | 
| 377 |  | 
 | 
| 378 | 0 |     DEBUGMSGTL(("netsnmp_sockaddr_ipx", "Address: %s:%s/%s\n", | 
| 379 | 0 |                 network ? network : "[NIL]", node ? node : "[NIL]", | 
| 380 | 0 |                 port ? port : "[NIL]")); | 
| 381 |  | 
 | 
| 382 | 0 |     if(sscanf(network, "%8lx%*c", &i) == 1) { | 
| 383 | 0 |         DEBUGMSGTL(("netsnmp_sockaddr_ipx", "network parsed okay\n")); | 
| 384 | 0 |         addr->sipx_network = htonl(i); | 
| 385 | 0 |     } else { | 
| 386 | 0 |         DEBUGMSGTL(("netsnmp_sockaddr_ipx", | 
| 387 | 0 |                     "failed to parse network part of address\n")); | 
| 388 | 0 |         free(def); | 
| 389 | 0 |         free(input); | 
| 390 | 0 |         return 0; | 
| 391 | 0 |     } | 
| 392 |  |  | 
| 393 | 0 |     if(sscanf(node, "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%*c", | 
| 394 | 0 |               &addr->sipx_node[0], &addr->sipx_node[1], | 
| 395 | 0 |               &addr->sipx_node[2], &addr->sipx_node[3], | 
| 396 | 0 |               &addr->sipx_node[4], &addr->sipx_node[5]) == 6) { | 
| 397 | 0 |         DEBUGMSGTL(("netsnmp_sockaddr_ipx", "node parsed okay\n")); | 
| 398 | 0 |     } else { | 
| 399 | 0 |         DEBUGMSGTL(("netsnmp_sockaddr_ipx", | 
| 400 | 0 |                     "failed to parse node part of address\n")); | 
| 401 | 0 |         free(def); | 
| 402 | 0 |         free(input); | 
| 403 | 0 |         return 0; | 
| 404 | 0 |     } | 
| 405 |  |  | 
| 406 | 0 |     if(sscanf(port, "%lu%*c", &i) == 1) { | 
| 407 | 0 |         DEBUGMSGTL(("netsnmp_sockaddr_ipx", "port parsed okay\n")); | 
| 408 | 0 |         addr->sipx_port = htons(i); | 
| 409 | 0 |     } else { | 
| 410 | 0 |         DEBUGMSGTL(("netsnmp_sockaddr_ipx", | 
| 411 | 0 |                     "failed to parse port part of address\n")); | 
| 412 | 0 |         free(def); | 
| 413 | 0 |         free(input); | 
| 414 | 0 |         return 0; | 
| 415 | 0 |     } | 
| 416 |  |  | 
| 417 | 0 |     free(def); | 
| 418 | 0 |     free(input); | 
| 419 | 0 |     return 1; | 
| 420 | 0 | } | 
| 421 |  |  | 
| 422 |  |  | 
| 423 |  |  | 
| 424 |  | int | 
| 425 |  | netsnmp_sockaddr_ipx(struct sockaddr_ipx *addr, const char *peername) | 
| 426 | 0 | { | 
| 427 | 0 |     return netsnmp_sockaddr_ipx2(addr, peername, NULL); | 
| 428 | 0 | } | 
| 429 |  |  | 
| 430 |  |  | 
| 431 |  |  | 
| 432 |  | netsnmp_transport * | 
| 433 |  | netsnmp_ipx_create_tstring(const char *str, int local, | 
| 434 |  |          const char *default_target) | 
| 435 | 0 | { | 
| 436 | 0 |     struct sockaddr_ipx addr; | 
| 437 |  | 
 | 
| 438 | 0 |     if (netsnmp_sockaddr_ipx2(&addr, str, default_target)) { | 
| 439 | 0 |         return netsnmp_ipx_transport(&addr, local); | 
| 440 | 0 |     } else { | 
| 441 | 0 |         return NULL; | 
| 442 | 0 |     } | 
| 443 | 0 | } | 
| 444 |  |  | 
| 445 |  | static int netsnmp_ipx_ostring_to_sockaddr(struct sockaddr_ipx *sa, | 
| 446 |  |                                            const void *o, size_t o_len) | 
| 447 | 0 | { | 
| 448 | 0 |     const char *p = o; | 
| 449 |  | 
 | 
| 450 | 0 |     if (o_len != 12) | 
| 451 | 0 |         return 0; | 
| 452 |  |  | 
| 453 | 0 |     memset(sa, 0, sizeof(*sa)); | 
| 454 | 0 |     sa->sipx_family = AF_IPX; | 
| 455 | 0 |     memcpy(&sa->sipx_network, p + 0, 4); | 
| 456 | 0 |     memcpy(&sa->sipx_node,    p + 4, 6); | 
| 457 | 0 |     memcpy(&sa->sipx_port,    p + 10, 2); | 
| 458 | 0 |     return 1; | 
| 459 | 0 | } | 
| 460 |  |  | 
| 461 |  | netsnmp_transport * | 
| 462 |  | netsnmp_ipx_create_ostring(const void *o, size_t o_len, int local) | 
| 463 | 0 | { | 
| 464 | 0 |     struct sockaddr_ipx sa; | 
| 465 |  | 
 | 
| 466 | 0 |     if (netsnmp_ipx_ostring_to_sockaddr(&sa, o, o_len)) | 
| 467 | 0 |         return netsnmp_ipx_transport(&sa, local); | 
| 468 |  |  | 
| 469 | 0 |     return NULL; | 
| 470 | 0 | } | 
| 471 |  |  | 
| 472 |  |  | 
| 473 |  |  | 
| 474 |  | void | 
| 475 |  | netsnmp_ipx_ctor(void) | 
| 476 | 3.81k | { | 
| 477 | 3.81k |     ipxDomain.name = netsnmpIPXDomain; | 
| 478 | 3.81k |     ipxDomain.name_length = netsnmpIPXDomain_len; | 
| 479 | 3.81k |     ipxDomain.prefix = calloc(2, sizeof(char *)); | 
| 480 | 3.81k |     if (!ipxDomain.prefix) { | 
| 481 | 0 |         snmp_log(LOG_ERR, "calloc() failed - out of memory\n"); | 
| 482 | 0 |         return; | 
| 483 | 0 |     } | 
| 484 | 3.81k |     ipxDomain.prefix[0] = "ipx"; | 
| 485 |  |  | 
| 486 | 3.81k |     ipxDomain.f_create_from_tstring_new = netsnmp_ipx_create_tstring; | 
| 487 | 3.81k |     ipxDomain.f_create_from_ostring     = netsnmp_ipx_create_ostring; | 
| 488 |  |  | 
| 489 | 3.81k |     netsnmp_tdomain_register(&ipxDomain); | 
| 490 | 3.81k | } |