Wes Hardaker | eb6d4fc | 2002-01-04 21:00:48 +0000 | [diff] [blame] | 1 | #include <net-snmp/net-snmp-config.h> |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 2 | |
| 3 | #include <stdio.h> |
| 4 | #include <sys/types.h> |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 5 | #include <errno.h> |
| 6 | |
| 7 | #if HAVE_STRING_H |
| 8 | #include <string.h> |
| 9 | #else |
| 10 | #include <strings.h> |
| 11 | #endif |
| 12 | #if HAVE_STDLIB_H |
| 13 | #include <stdlib.h> |
| 14 | #endif |
| 15 | #if HAVE_UNISTD_H |
| 16 | #include <unistd.h> |
| 17 | #endif |
| 18 | #if HAVE_SYS_SOCKET_H |
| 19 | #include <sys/socket.h> |
| 20 | #endif |
| 21 | #if HAVE_NETINET_IN_H |
| 22 | #include <netinet/in.h> |
| 23 | #endif |
| 24 | #if HAVE_ARPA_INET_H |
| 25 | #include <arpa/inet.h> |
| 26 | #endif |
| 27 | #if HAVE_NETDB_H |
| 28 | #include <netdb.h> |
| 29 | #endif |
John Naylon | 608e832 | 2001-12-05 15:48:35 +0000 | [diff] [blame] | 30 | #if HAVE_FCNTL_H |
| 31 | #include <fcntl.h> |
| 32 | #endif |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 33 | |
Niels Baggesen | 6d875f3 | 2002-12-16 07:40:39 +0000 | [diff] [blame] | 34 | #if HAVE_DMALLOC_H |
| 35 | #include <dmalloc.h> |
| 36 | #endif |
| 37 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 38 | #include <net-snmp/types.h> |
Dave Shield | 67e824b | 2002-02-14 12:41:29 +0000 | [diff] [blame] | 39 | #include <net-snmp/output_api.h> |
| 40 | #include <net-snmp/config_api.h> |
| 41 | |
Dave Shield | ff06f8d | 2002-02-14 14:23:04 +0000 | [diff] [blame] | 42 | #include <net-snmp/library/snmp_transport.h> |
| 43 | #include <net-snmp/library/snmpUDPIPv6Domain.h> |
| 44 | #include <net-snmp/library/snmpTCPIPv6Domain.h> |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 45 | |
Dave Shield | 187ccf6 | 2004-01-29 14:13:59 +0000 | [diff] [blame] | 46 | oid netsnmp_TCPIPv6Domain[] = { TRANSPORT_DOMAIN_TCP_IPV6 }; |
Wes Hardaker | d7de7e9 | 2002-03-08 15:43:16 +0000 | [diff] [blame] | 47 | static netsnmp_tdomain tcp6Domain; |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 48 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 49 | /* |
| 50 | * Return a string representing the address in data, or else the "far end" |
| 51 | * address if data is NULL. |
| 52 | */ |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 53 | |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 54 | static char * |
| 55 | netsnmp_tcp6_fmtaddr(netsnmp_transport *t, void *data, int len) |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 56 | { |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 57 | struct sockaddr_in6 *to = NULL; |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 58 | |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 59 | DEBUGMSGTL(("netsnmp_tcp6", "fmtaddr: t = %p, data = %p, len = %d\n", t, |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 60 | data, len)); |
| 61 | if (data != NULL && len == sizeof(struct sockaddr_in6)) { |
| 62 | to = (struct sockaddr_in6 *) data; |
| 63 | } else if (t != NULL && t->data != NULL) { |
| 64 | to = (struct sockaddr_in6 *) t->data; |
| 65 | } |
| 66 | if (to == NULL) { |
| 67 | return strdup("TCP/IPv6: unknown"); |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 68 | } else { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 69 | char addr[INET6_ADDRSTRLEN]; |
| 70 | char tmp[INET6_ADDRSTRLEN + 8]; |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 71 | |
| 72 | sprintf(tmp, "[%s]:%hd", |
| 73 | inet_ntop(AF_INET6, (void *) &(to->sin6_addr), addr, |
| 74 | INET6_ADDRSTRLEN), ntohs(to->sin6_port)); |
| 75 | return strdup(tmp); |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 76 | } |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 77 | } |
| 78 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 79 | /* |
| 80 | * You can write something into opaque that will subsequently get passed back |
| 81 | * to your send function if you like. For instance, you might want to |
| 82 | * remember where a PDU came from, so that you can send a reply there... |
| 83 | */ |
| 84 | |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 85 | static int |
| 86 | netsnmp_tcp6_recv(netsnmp_transport *t, void *buf, int size, |
| 87 | void **opaque, int *olength) |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 88 | { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 89 | int rc = -1; |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 90 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 91 | if (t != NULL && t->sock >= 0) { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 92 | while (rc < 0) { |
| 93 | rc = recv(t->sock, buf, size, 0); |
| 94 | if (rc < 0 && errno != EINTR) { |
| 95 | DEBUGMSGTL(("netsnmp_tcp6", "recv fd %d err %d (\"%s\")\n", |
| 96 | t->sock, errno, strerror(errno))); |
| 97 | return -1; |
| 98 | } |
| 99 | } |
| 100 | DEBUGMSGTL(("netsnmp_tcp6", "recv fd %d got %d bytes\n", t->sock, rc)); |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 101 | } else { |
| 102 | return -1; |
| 103 | } |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 104 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 105 | if (opaque != NULL && olength != NULL) { |
| 106 | if (t->data_length > 0) { |
| 107 | if ((*opaque = malloc(t->data_length)) != NULL) { |
| 108 | memcpy(*opaque, t->data, t->data_length); |
| 109 | *olength = t->data_length; |
| 110 | } else { |
| 111 | *olength = 0; |
| 112 | } |
| 113 | } else { |
| 114 | *opaque = NULL; |
| 115 | *olength = 0; |
| 116 | } |
| 117 | } |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 118 | |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 119 | return rc; |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 120 | } |
| 121 | |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 122 | static int |
| 123 | netsnmp_tcp6_send(netsnmp_transport *t, void *buf, int size, |
| 124 | void **opaque, int *olength) |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 125 | { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 126 | int rc = -1; |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 127 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 128 | if (t != NULL && t->sock >= 0) { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 129 | while (rc < 0) { |
| 130 | rc = send(t->sock, buf, size, 0); |
| 131 | if (rc < 0 && errno != EINTR) { |
| 132 | break; |
| 133 | } |
| 134 | } |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 135 | } |
| 136 | return rc; |
| 137 | } |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 138 | |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 139 | static int |
| 140 | netsnmp_tcp6_close(netsnmp_transport *t) |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 141 | { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 142 | int rc = -1; |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 143 | if (t != NULL && t->sock >= 0) { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 144 | DEBUGMSGTL(("netsnmp_tcp6", "close fd %d\n", t->sock)); |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 145 | #ifndef HAVE_CLOSESOCKET |
| 146 | rc = close(t->sock); |
| 147 | #else |
| 148 | rc = closesocket(t->sock); |
| 149 | #endif |
| 150 | t->sock = -1; |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 151 | } |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 152 | return rc; |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 153 | } |
| 154 | |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 155 | static int |
| 156 | netsnmp_tcp6_accept(netsnmp_transport *t) |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 157 | { |
| 158 | struct sockaddr_in6 *farend = NULL; |
Wes Hardaker | d3f6bad | 2002-05-06 22:59:34 +0000 | [diff] [blame] | 159 | int newsock = -1, sockflags = 0; |
Wes Hardaker | d3f6bad | 2002-05-06 22:59:34 +0000 | [diff] [blame] | 160 | socklen_t farendlen = sizeof(struct sockaddr_in6); |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 161 | char *string = NULL; |
| 162 | |
| 163 | farend = (struct sockaddr_in6 *) malloc(sizeof(struct sockaddr_in6)); |
| 164 | |
| 165 | if (farend == NULL) { |
| 166 | /* |
| 167 | * Indicate that the acceptance of this socket failed. |
| 168 | */ |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 169 | DEBUGMSGTL(("netsnmp_tcp6", "accept: malloc failed\n")); |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 170 | return -1; |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 171 | } |
| 172 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 173 | if (t != NULL && t->sock >= 0) { |
| 174 | newsock = accept(t->sock, (struct sockaddr *) farend, &farendlen); |
| 175 | |
| 176 | if (newsock < 0) { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 177 | DEBUGMSGTL(("netsnmp_tcp6","accept failed rc %d errno %d \"%s\"\n", |
| 178 | newsock, errno, strerror(errno))); |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 179 | free(farend); |
| 180 | return newsock; |
| 181 | } |
| 182 | |
| 183 | if (t->data != NULL) { |
| 184 | free(t->data); |
| 185 | } |
| 186 | |
| 187 | t->data = farend; |
| 188 | t->data_length = farendlen; |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 189 | string = netsnmp_tcp6_fmtaddr(NULL, farend, farendlen); |
| 190 | DEBUGMSGTL(("netsnmp_tcp6", "accept succeeded (from %s)\n", string)); |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 191 | free(string); |
| 192 | |
| 193 | /* |
| 194 | * Try to make the new socket blocking. |
| 195 | */ |
| 196 | |
| 197 | #ifdef WIN32 |
| 198 | ioctlsocket(newsock, FIONBIO, &sockflags); |
| 199 | #else |
| 200 | if ((sockflags = fcntl(newsock, F_GETFL, 0)) >= 0) { |
| 201 | fcntl(newsock, F_SETFL, (sockflags & ~O_NONBLOCK)); |
| 202 | } else { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 203 | DEBUGMSGTL(("netsnmp_tcp6", "accept: couldn't f_getfl of fd %d\n", |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 204 | newsock)); |
| 205 | } |
| 206 | #endif |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 207 | return newsock; |
| 208 | } else { |
| 209 | free(farend); |
| 210 | return -1; |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | |
| 215 | |
| 216 | /* |
| 217 | * Open a TCP/IPv6-based transport for SNMP. Local is TRUE if addr is the |
| 218 | * local address to bind to (i.e. this is a server-type session); otherwise |
| 219 | * addr is the remote address to send things to. |
| 220 | */ |
| 221 | |
| 222 | netsnmp_transport * |
| 223 | netsnmp_tcp6_transport(struct sockaddr_in6 *addr, int local) |
| 224 | { |
| 225 | netsnmp_transport *t = NULL; |
| 226 | int rc = 0; |
| 227 | char *string = NULL; |
| 228 | |
| 229 | if (addr == NULL || addr->sin6_family != AF_INET6) { |
| 230 | return NULL; |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 231 | } |
| 232 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 233 | t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport)); |
| 234 | if (t == NULL) { |
| 235 | return NULL; |
| 236 | } |
| 237 | memset(t, 0, sizeof(netsnmp_transport)); |
| 238 | |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 239 | string = netsnmp_tcp6_fmtaddr(NULL, (void *)addr, |
| 240 | sizeof(struct sockaddr_in6)); |
| 241 | DEBUGMSGTL(("netsnmp_tcp6", "open %s %s\n", local ? "local" : "remote", |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 242 | string)); |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 243 | free(string); |
| 244 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 245 | memset(t, 0, sizeof(netsnmp_transport)); |
| 246 | |
| 247 | t->data = malloc(sizeof(struct sockaddr_in6)); |
| 248 | if (t->data == NULL) { |
| 249 | netsnmp_transport_free(t); |
| 250 | return NULL; |
| 251 | } |
| 252 | t->data_length = sizeof(struct sockaddr_in6); |
| 253 | memcpy(t->data, addr, sizeof(struct sockaddr_in6)); |
| 254 | |
Wes Hardaker | e3f8d25 | 2002-05-01 16:31:38 +0000 | [diff] [blame] | 255 | t->domain = netsnmp_TCPIPv6Domain; |
| 256 | t->domain_length = sizeof(netsnmp_TCPIPv6Domain) / sizeof(oid); |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 257 | |
| 258 | t->sock = socket(PF_INET6, SOCK_STREAM, 0); |
| 259 | if (t->sock < 0) { |
| 260 | netsnmp_transport_free(t); |
| 261 | return NULL; |
| 262 | } |
| 263 | |
| 264 | t->flags = NETSNMP_TRANSPORT_FLAG_STREAM; |
| 265 | |
| 266 | if (local) { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 267 | int sockflags = 0, opt = 1; |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 268 | |
| 269 | /* |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 270 | * This session is inteneded as a server, so we must bind on to the |
| 271 | * given IP address, which may include an interface address, or could |
| 272 | * be INADDR_ANY, but certainly includes a port number. |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 273 | */ |
| 274 | |
| 275 | t->flags |= NETSNMP_TRANSPORT_FLAG_LISTEN; |
| 276 | t->local = malloc(18); |
| 277 | if (t->local == NULL) { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 278 | netsnmp_tcp6_close(t); |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 279 | netsnmp_transport_free(t); |
| 280 | return NULL; |
| 281 | } |
| 282 | memcpy(t->local, addr->sin6_addr.s6_addr, 16); |
| 283 | t->local[16] = (addr->sin6_port & 0xff00) >> 8; |
| 284 | t->local[17] = (addr->sin6_port & 0x00ff) >> 0; |
| 285 | t->local_length = 18; |
| 286 | |
| 287 | /* |
| 288 | * We should set SO_REUSEADDR too. |
| 289 | */ |
| 290 | |
| 291 | setsockopt(t->sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); |
| 292 | |
| 293 | rc = bind(t->sock, (struct sockaddr *) addr, |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 294 | sizeof(struct sockaddr_in6)); |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 295 | if (rc != 0) { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 296 | netsnmp_tcp6_close(t); |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 297 | netsnmp_transport_free(t); |
| 298 | return NULL; |
| 299 | } |
| 300 | |
| 301 | /* |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 302 | * Since we are going to be letting select() tell us when connections |
| 303 | * are ready to be accept()ed, we need to make the socket n0n-blocking |
| 304 | * to avoid the race condition described in W. R. Stevens, ``Unix |
| 305 | * Network Programming Volume I Second Edition'', pp. 422--4, which |
| 306 | * could otherwise wedge the agent. |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 307 | */ |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 308 | |
| 309 | #ifdef WIN32 |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 310 | opt = 1; |
| 311 | ioctlsocket(t->sock, FIONBIO, &opt); |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 312 | #else |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 313 | sockflags = fcntl(t->sock, F_GETFL, 0); |
| 314 | fcntl(t->sock, F_SETFL, sockflags | O_NONBLOCK); |
| 315 | #endif |
| 316 | |
| 317 | /* |
| 318 | * Now sit here and wait for connections to arrive. |
| 319 | */ |
| 320 | |
| 321 | rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN); |
| 322 | if (rc != 0) { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 323 | netsnmp_tcp6_close(t); |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 324 | netsnmp_transport_free(t); |
| 325 | return NULL; |
| 326 | } |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 327 | } else { |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 328 | t->remote = malloc(18); |
| 329 | if (t->remote == NULL) { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 330 | netsnmp_tcp6_close(t); |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 331 | netsnmp_transport_free(t); |
| 332 | return NULL; |
| 333 | } |
| 334 | memcpy(t->remote, addr->sin6_addr.s6_addr, 16); |
| 335 | t->remote[16] = (addr->sin6_port & 0xff00) >> 8; |
| 336 | t->remote[17] = (addr->sin6_port & 0x00ff) >> 0; |
| 337 | t->remote_length = 18; |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 338 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 339 | /* |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 340 | * This is a client-type session, so attempt to connect to the far |
| 341 | * end. We don't go non-blocking here because it's not obvious what |
| 342 | * you'd then do if you tried to do snmp_sends before the connection |
| 343 | * had completed. So this can block. |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 344 | */ |
| 345 | |
| 346 | rc = connect(t->sock, (struct sockaddr *) addr, |
| 347 | sizeof(struct sockaddr_in6)); |
| 348 | |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 349 | DEBUGMSGTL(("netsnmp_tcp6", "connect returns %d\n", rc)); |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 350 | |
| 351 | if (rc < 0) { |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 352 | netsnmp_tcp6_close(t); |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 353 | netsnmp_transport_free(t); |
| 354 | return NULL; |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | /* |
| 359 | * Message size is not limited by this transport (hence msgMaxSize |
| 360 | * is equal to the maximum legal size of an SNMP message). |
| 361 | */ |
| 362 | |
| 363 | t->msgMaxSize = 0x7fffffff; |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 364 | t->f_recv = netsnmp_tcp6_recv; |
| 365 | t->f_send = netsnmp_tcp6_send; |
| 366 | t->f_close = netsnmp_tcp6_close; |
| 367 | t->f_accept = netsnmp_tcp6_accept; |
| 368 | t->f_fmtaddr = netsnmp_tcp6_fmtaddr; |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 369 | |
| 370 | return t; |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 371 | } |
| 372 | |
| 373 | |
| 374 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 375 | netsnmp_transport * |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 376 | netsnmp_tcp6_create_tstring(const char *string, int local) |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 377 | { |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 378 | struct sockaddr_in6 addr; |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 379 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 380 | if (netsnmp_sockaddr_in6(&addr, string, 0)) { |
| 381 | return netsnmp_tcp6_transport(&addr, local); |
| 382 | } else { |
| 383 | return NULL; |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 384 | } |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 385 | } |
| 386 | |
| 387 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 388 | /* |
| 389 | * See: |
| 390 | * |
| 391 | * http://www.ietf.org/internet-drafts/draft-ietf-ops-taddress-mib-01.txt |
| 392 | * |
| 393 | * (or newer equivalent) for details of the TC which we are using for |
| 394 | * the mapping here. |
| 395 | */ |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 396 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 397 | netsnmp_transport * |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 398 | netsnmp_tcp6_create_ostring(const u_char * o, size_t o_len, int local) |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 399 | { |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 400 | struct sockaddr_in6 addr; |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 401 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 402 | if (o_len == 18) { |
| 403 | memset((u_char *) & addr, 0, sizeof(struct sockaddr_in6)); |
| 404 | addr.sin6_family = AF_INET6; |
| 405 | memcpy((u_char *) & (addr.sin6_addr.s6_addr), o, 16); |
| 406 | addr.sin6_port = (o[16] << 8) + o[17]; |
| 407 | return netsnmp_tcp6_transport(&addr, local); |
| 408 | } |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 409 | return NULL; |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 410 | } |
| 411 | |
| 412 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 413 | void |
| 414 | netsnmp_tcp6_ctor(void) |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 415 | { |
Wes Hardaker | e3f8d25 | 2002-05-01 16:31:38 +0000 | [diff] [blame] | 416 | tcp6Domain.name = netsnmp_TCPIPv6Domain; |
Wes Hardaker | d3f6bad | 2002-05-06 22:59:34 +0000 | [diff] [blame] | 417 | tcp6Domain.name_length = sizeof(netsnmp_TCPIPv6Domain) / sizeof(oid); |
John Naylon | 47e64df | 2002-08-09 13:57:43 +0000 | [diff] [blame] | 418 | tcp6Domain.f_create_from_tstring = netsnmp_tcp6_create_tstring; |
| 419 | tcp6Domain.f_create_from_ostring = netsnmp_tcp6_create_ostring; |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 420 | tcp6Domain.prefix = calloc(4, sizeof(char *)); |
| 421 | tcp6Domain.prefix[0] = "tcp6"; |
| 422 | tcp6Domain.prefix[1] = "tcpv6"; |
| 423 | tcp6Domain.prefix[2] = "tcpipv6"; |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 424 | |
Wes Hardaker | 6d1f602 | 2002-04-20 07:08:20 +0000 | [diff] [blame] | 425 | netsnmp_tdomain_register(&tcp6Domain); |
John Naylon | c1ec3d8 | 2001-12-05 15:27:14 +0000 | [diff] [blame] | 426 | } |