Coverage Report

Created: 2024-02-25 06:16

/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
}