/src/net-snmp/snmplib/transports/snmpIPv4BaseDomain.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* IPV4 base transport support functions |
2 | | */ |
3 | | |
4 | | #include <net-snmp/net-snmp-config.h> |
5 | | |
6 | | #include <net-snmp/types.h> |
7 | | #include "snmpIPBaseDomain.h" |
8 | | #include <net-snmp/library/snmpIPv4BaseDomain.h> |
9 | | #include <net-snmp/library/snmp_assert.h> |
10 | | |
11 | | #include <stddef.h> |
12 | | #include <stdio.h> |
13 | | #include <sys/types.h> |
14 | | #include <ctype.h> |
15 | | #ifdef HAVE_STDLIB_H |
16 | | #include <stdlib.h> |
17 | | #endif |
18 | | #ifdef HAVE_STRING_H |
19 | | #include <string.h> |
20 | | #else |
21 | | #include <strings.h> |
22 | | #endif |
23 | | #ifdef HAVE_SYS_SOCKET_H |
24 | | #include <sys/socket.h> |
25 | | #endif |
26 | | #ifdef HAVE_NETINET_IN_H |
27 | | #include <netinet/in.h> |
28 | | #endif |
29 | | #ifdef HAVE_ARPA_INET_H |
30 | | #include <arpa/inet.h> |
31 | | #endif |
32 | | #ifdef HAVE_NETDB_H |
33 | | #include <netdb.h> |
34 | | #endif |
35 | | |
36 | | #include <net-snmp/types.h> |
37 | | #include <net-snmp/library/snmp.h> |
38 | | #include <net-snmp/library/snmp_debug.h> |
39 | | #include <net-snmp/library/default_store.h> |
40 | | #include <net-snmp/library/system.h> |
41 | | |
42 | | #include "inet_ntop.h" |
43 | | |
44 | | #ifndef INADDR_NONE |
45 | | #define INADDR_NONE -1 |
46 | | #endif |
47 | | |
48 | | /** |
49 | | * Convert a "traditional" peername into a sockaddr_in structure which is |
50 | | * written to *addr. |
51 | | * |
52 | | * @return 1 if the conversion was successful, or 0 if it failed. |
53 | | */ |
54 | | int |
55 | | netsnmp_sockaddr_in(struct sockaddr_in *addr, |
56 | | const char *inpeername, int remote_port) |
57 | 0 | { |
58 | 0 | char buf[sizeof(int) * 3 + 2]; |
59 | |
|
60 | 0 | sprintf(buf, ":%u", remote_port); |
61 | 0 | return netsnmp_sockaddr_in2(addr, inpeername, remote_port ? buf : NULL); |
62 | 0 | } |
63 | | |
64 | | /** |
65 | | * Convert a "traditional" peername into a sockaddr_in structure which is |
66 | | * written to *addr. |
67 | | * |
68 | | * @return 1 if the conversion was successful, or 0 if it failed. |
69 | | */ |
70 | | int |
71 | | netsnmp_sockaddr_in2(struct sockaddr_in *addr, |
72 | | const char *inpeername, const char *default_target) |
73 | 0 | { |
74 | 0 | struct netsnmp_ep ep; |
75 | 0 | int ret; |
76 | |
|
77 | 0 | ret = netsnmp_sockaddr_in3(&ep, inpeername, default_target); |
78 | 0 | if (ret == 0) |
79 | 0 | return 0; |
80 | 0 | *addr = ep.a.sin; |
81 | 0 | return ret; |
82 | 0 | } |
83 | | |
84 | | int |
85 | | netsnmp_sockaddr_in3(struct netsnmp_ep *ep, |
86 | | const char *inpeername, const char *default_target) |
87 | 3.06k | { |
88 | 3.06k | struct sockaddr_in *addr = &ep->a.sin; |
89 | 3.06k | struct netsnmp_ep_str ep_str; |
90 | 3.06k | int port, ret; |
91 | | |
92 | 3.06k | if (!ep) |
93 | 0 | return 0; |
94 | | |
95 | 3.06k | DEBUGMSGTL(("netsnmp_sockaddr_in", |
96 | 3.06k | "addr %p, inpeername \"%s\", default_target \"%s\"\n", |
97 | 3.06k | ep, inpeername ? inpeername : "[NIL]", |
98 | 3.06k | default_target ? default_target : "[NIL]")); |
99 | | |
100 | 3.06k | memset(ep, 0, sizeof(*ep)); |
101 | 3.06k | addr->sin_addr.s_addr = htonl(INADDR_ANY); |
102 | 3.06k | addr->sin_family = AF_INET; |
103 | 3.06k | addr->sin_port = htons((u_short)SNMP_PORT); |
104 | | |
105 | 3.06k | memset(&ep_str, 0, sizeof(ep_str)); |
106 | 3.06k | port = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, |
107 | 3.06k | NETSNMP_DS_LIB_DEFAULT_PORT); |
108 | 3.06k | if (port != 0) |
109 | 0 | snprintf(ep_str.port, sizeof(ep_str.port), "%d", port); |
110 | 3.06k | else if (default_target && |
111 | 3.06k | !netsnmp_parse_ep_str(&ep_str, default_target)) |
112 | 0 | snmp_log(LOG_ERR, "Invalid default target %s\n", |
113 | 0 | default_target); |
114 | 3.06k | if (inpeername && *inpeername != '\0') { |
115 | 0 | if (ep_str.addr) { |
116 | 0 | free(ep_str.addr); /* free default target */ |
117 | 0 | ep_str.addr = NULL; |
118 | 0 | } |
119 | 0 | if (!netsnmp_parse_ep_str(&ep_str, inpeername)) |
120 | 0 | return 0; |
121 | 0 | } |
122 | | |
123 | 3.06k | if (ep_str.port[0]) |
124 | 3.06k | addr->sin_port = htons(atoi(ep_str.port)); |
125 | 3.06k | if (ep_str.iface[0]) |
126 | 0 | strlcpy(ep->iface, ep_str.iface, sizeof(ep->iface)); |
127 | 3.06k | if (ep_str.addr && strcmp(ep_str.addr, "255.255.255.255") == 0) { |
128 | | /* |
129 | | * The explicit broadcast address hack |
130 | | */ |
131 | 0 | DEBUGMSGTL(("netsnmp_sockaddr_in", "Explicit UDP broadcast\n")); |
132 | 0 | addr->sin_addr.s_addr = INADDR_NONE; |
133 | 3.06k | } else if (ep_str.addr && strcmp(ep_str.addr, "") != 0) { |
134 | 0 | ret = netsnmp_gethostbyname_v4(ep_str.addr, &addr->sin_addr.s_addr); |
135 | 0 | if (ret < 0) { |
136 | 0 | DEBUGMSGTL(("netsnmp_sockaddr_in", |
137 | 0 | "couldn't resolve hostname \"%s\"\n", ep_str.addr)); |
138 | 0 | free(ep_str.addr); |
139 | 0 | return 0; |
140 | 0 | } |
141 | 0 | DEBUGMSGTL(("netsnmp_sockaddr_in", |
142 | 0 | "hostname (resolved okay)\n")); |
143 | 0 | } |
144 | | |
145 | | /* |
146 | | * Finished |
147 | | */ |
148 | | |
149 | 3.06k | DEBUGMSGTL(("netsnmp_sockaddr_in", "return { AF_INET, %s:%hu }\n", |
150 | 3.06k | inet_ntoa(addr->sin_addr), ntohs(addr->sin_port))); |
151 | 3.06k | free(ep_str.addr); |
152 | 3.06k | return 1; |
153 | 3.06k | } |
154 | | |
155 | | char * |
156 | | netsnmp_ipv4_fmtaddr(const char *prefix, netsnmp_transport *t, |
157 | | const void *data, int len) |
158 | 0 | { |
159 | 0 | const netsnmp_indexed_addr_pair *addr_pair; |
160 | 0 | const struct sockaddr_in *from, *to; |
161 | 0 | struct hostent *host; |
162 | 0 | char *tmp; |
163 | |
|
164 | 0 | if (t && !data) { |
165 | 0 | data = t->data; |
166 | 0 | len = t->data_length; |
167 | 0 | } |
168 | |
|
169 | 0 | switch (data ? len : 0) { |
170 | 0 | case sizeof(netsnmp_indexed_addr_pair): |
171 | 0 | addr_pair = data; |
172 | 0 | break; |
173 | 0 | case sizeof(struct sockaddr_in): { |
174 | 0 | char a[16]; |
175 | |
|
176 | 0 | to = data; |
177 | 0 | if (asprintf(&tmp, "%s: [%s]:%hu", prefix, |
178 | 0 | inet_ntop(AF_INET, &to->sin_addr, a, sizeof(a)), |
179 | 0 | ntohs(to->sin_port)) < 0) |
180 | 0 | tmp = NULL; |
181 | 0 | return tmp; |
182 | 0 | } |
183 | 0 | default: |
184 | 0 | netsnmp_assert(0); |
185 | 0 | if (asprintf(&tmp, "%s: unknown", prefix) < 0) |
186 | 0 | tmp = NULL; |
187 | 0 | return tmp; |
188 | 0 | } |
189 | | |
190 | 0 | from = (const struct sockaddr_in *)&addr_pair->local_addr; |
191 | 0 | to = (const struct sockaddr_in *)&addr_pair->remote_addr; |
192 | 0 | netsnmp_assert(from->sin_family == 0 || from->sin_family == AF_INET); |
193 | 0 | netsnmp_assert(to->sin_family == 0 || to->sin_family == AF_INET); |
194 | 0 | if (t && t->flags & NETSNMP_TRANSPORT_FLAG_HOSTNAME) { |
195 | | /* XXX: hmm... why isn't this prefixed */ |
196 | | /* assuming intentional */ |
197 | 0 | host = netsnmp_gethostbyaddr(&to->sin_addr, sizeof(struct in_addr), AF_INET); |
198 | 0 | return (host ? strdup(host->h_name) : NULL); |
199 | 0 | } else { |
200 | 0 | char a1[16]; |
201 | 0 | char a2[16]; |
202 | |
|
203 | 0 | if (asprintf(&tmp, "%s: [%s]:%hu->[%s]:%hu", prefix, |
204 | 0 | inet_ntop(AF_INET, &to->sin_addr, a1, sizeof(a1)), |
205 | 0 | ntohs(to->sin_port), |
206 | 0 | inet_ntop(AF_INET, &from->sin_addr, a2, sizeof(a2)), |
207 | 0 | ntohs(from->sin_port)) < 0) |
208 | 0 | tmp = NULL; |
209 | 0 | } |
210 | | |
211 | 0 | return tmp; |
212 | 0 | } |
213 | | |
214 | | void netsnmp_ipv4_get_taddr(struct netsnmp_transport_s *t, void **addr, |
215 | | size_t *addr_len) |
216 | 0 | { |
217 | 0 | struct sockaddr_in *sin = t->remote; |
218 | |
|
219 | 0 | netsnmp_assert(t->remote_length == sizeof(*sin)); |
220 | |
|
221 | 0 | *addr_len = 6; |
222 | 0 | if ((*addr = malloc(*addr_len))) { |
223 | 0 | unsigned char *p = *addr; |
224 | |
|
225 | 0 | memcpy(p, &sin->sin_addr, 4); |
226 | 0 | memcpy(p + 4, &sin->sin_port, 2); |
227 | 0 | } |
228 | 0 | } |
229 | | |
230 | | int netsnmp_ipv4_ostring_to_sockaddr(struct sockaddr_in *sin, const void *o, |
231 | | size_t o_len) |
232 | 0 | { |
233 | 0 | const char *p = o; |
234 | |
|
235 | 0 | if (o_len != 6) |
236 | 0 | return 0; |
237 | | |
238 | 0 | memset(sin, 0, sizeof(*sin)); |
239 | 0 | sin->sin_family = AF_INET; |
240 | 0 | memcpy(&sin->sin_addr, p + 0, 4); |
241 | 0 | memcpy(&sin->sin_port, p + 4, 2); |
242 | 0 | return 1; |
243 | 0 | } |