Coverage Report

Created: 2024-07-27 06:09

/src/net-snmp/snmplib/transports/snmpUDPBaseDomain.c
Line
Count
Source (jump to first uncovered line)
1
/* UDP base transport support functions
2
 *
3
 * Portions of this file are subject to the following copyright(s).  See
4
 * the Net-SNMP's COPYING file for more details and other copyrights
5
 * that may apply:
6
 *
7
 * Portions of this file are copyrighted by:
8
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
9
 * Use is subject to license terms specified in the COPYING file
10
 * distributed with the Net-SNMP package.
11
 */
12
13
#include <net-snmp/net-snmp-config.h>
14
15
#include <net-snmp/types.h>
16
#include <net-snmp/library/snmpUDPBaseDomain.h>
17
18
#include <stddef.h>
19
#include <stdio.h>
20
#include <sys/types.h>
21
#include <ctype.h>
22
#ifdef HAVE_STDLIB_H
23
#include <stdlib.h>
24
#endif
25
#ifdef HAVE_STRING_H
26
#include <string.h>
27
#else
28
#include <strings.h>
29
#endif
30
#ifdef HAVE_NETINET_IN_H
31
#include <netinet/in.h>
32
#endif
33
#ifdef HAVE_NET_IF_H
34
#include <net/if.h>
35
#endif
36
#ifdef HAVE_ARPA_INET_H
37
#include <arpa/inet.h>
38
#endif
39
#ifdef HAVE_NETDB_H
40
#include <netdb.h>
41
#endif
42
#ifdef HAVE_SYS_UIO_H
43
#include <sys/uio.h>
44
#endif
45
#ifdef WIN32
46
#include <mswsock.h>
47
#endif
48
#include <errno.h>
49
50
#include <net-snmp/types.h>
51
#include <net-snmp/library/snmpSocketBaseDomain.h>
52
#include <net-snmp/library/snmpUDPDomain.h>
53
#include <net-snmp/library/snmp_debug.h>
54
#include <net-snmp/library/tools.h>
55
#include <net-snmp/library/default_store.h>
56
#include <net-snmp/library/system.h>
57
#include <net-snmp/library/snmp_assert.h>
58
59
#ifndef  MSG_DONTWAIT
60
#define MSG_DONTWAIT 0
61
#endif
62
63
void
64
_netsnmp_udp_sockopt_set(int fd, int local)
65
2.81k
{
66
2.81k
#ifdef  SO_BSDCOMPAT
67
    /*
68
     * Patch for Linux.  Without this, UDP packets that fail get an ICMP
69
     * response.  Linux turns the failed ICMP response into an error message
70
     * and return value, unlike all other OS's.  
71
     */
72
2.81k
    if (0 == netsnmp_os_prematch("Linux","2.4"))
73
0
    {
74
0
        int             one = 1;
75
0
        DEBUGMSGTL(("socket:option", "setting socket option SO_BSDCOMPAT\n"));
76
0
        setsockopt(fd, SOL_SOCKET, SO_BSDCOMPAT, (void *) &one,
77
0
                   sizeof(one));
78
0
    }
79
2.81k
#endif                          /*SO_BSDCOMPAT */
80
    /*
81
     * SO_REUSEADDR will allow multiple apps to open the same port at
82
     * the same time. Only the last one to open the socket will get
83
     * data. Obviously, for an agent, this is a bad thing. There should
84
     * only be one listener.
85
     */
86
#ifdef ALLOW_PORT_HIJACKING
87
#ifdef  SO_REUSEADDR
88
    /*
89
     * Allow the same port to be specified multiple times without failing.
90
     *    (useful for a listener)
91
     */
92
    {
93
        int             one = 1;
94
        DEBUGMSGTL(("socket:option", "setting socket option SO_REUSEADDR\n"));
95
        setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &one,
96
                   sizeof(one));
97
    }
98
#endif                          /*SO_REUSEADDR */
99
#endif
100
101
    /*
102
     * Try to set the send and receive buffers to a reasonably large value, so
103
     * that we can send and receive big PDUs (defaults to 8192 bytes (!) on
104
     * Solaris, for instance).  Don't worry too much about errors -- just
105
     * plough on regardless.  
106
     */
107
2.81k
    netsnmp_sock_buffer_set(fd, SO_SNDBUF, local, 0);
108
2.81k
    netsnmp_sock_buffer_set(fd, SO_RCVBUF, local, 0);
109
2.81k
}
110
111
#if defined(HAVE_IP_PKTINFO) || (defined(HAVE_IP_RECVDSTADDR) && defined(HAVE_IP_SENDSRCADDR))
112
113
#define netsnmp_udpbase_recvfrom_sendto_defined
114
115
enum {
116
#if defined(HAVE_IP_PKTINFO)
117
    cmsg_data_size = sizeof(struct in_pktinfo)
118
#elif defined(HAVE_IP_RECVDSTADDR)
119
    cmsg_data_size = sizeof(struct in_addr)
120
#endif
121
};
122
123
#ifdef WIN32
124
#ifndef WSAID_WSASENDMSG
125
#define WSAID_WSASENDMSG \
126
    {0xa441e712,0x754f,0x43ca,{0x84,0xa7,0x0d,0xee,0x44,0xcf,0x60,0x6d}}
127
typedef INT (WINAPI * LPFN_WSASENDMSG)(SOCKET, LPWSAMSG, DWORD, LPDWORD,
128
                                       LPWSAOVERLAPPED,
129
                                       LPWSAOVERLAPPED_COMPLETION_ROUTINE);
130
#endif
131
132
static LPFN_WSARECVMSG pfWSARecvMsg;
133
static LPFN_WSASENDMSG pfWSASendMsg;
134
#endif
135
136
int
137
netsnmp_udpbase_recvfrom(int s, void *buf, int len, struct sockaddr *from,
138
                         socklen_t *fromlen, struct sockaddr *dstip,
139
                         socklen_t *dstlen, int *if_index)
140
0
{
141
0
    int r;
142
0
#if !defined(WIN32)
143
0
    struct iovec iov;
144
0
    char cmsg[CMSG_SPACE(cmsg_data_size)];
145
0
    struct cmsghdr *cm;
146
0
    struct msghdr msg;
147
148
0
    iov.iov_base = buf;
149
0
    iov.iov_len = len;
150
151
0
    memset(&msg, 0, sizeof msg);
152
0
    msg.msg_name = from;
153
0
    msg.msg_namelen = *fromlen;
154
0
    msg.msg_iov = &iov;
155
0
    msg.msg_iovlen = 1;
156
0
    msg.msg_control = &cmsg;
157
0
    msg.msg_controllen = sizeof(cmsg);
158
159
0
    r = recvmsg(s, &msg, MSG_DONTWAIT);
160
#else /* !defined(WIN32) */
161
    WSABUF wsabuf;
162
    char cmsg[WSA_CMSG_SPACE(sizeof(struct in_pktinfo))];
163
    WSACMSGHDR *cm;
164
    WSAMSG msg;
165
    DWORD bytes_received;
166
167
    wsabuf.buf = buf;
168
    wsabuf.len = len;
169
170
    msg.name = from;
171
    msg.namelen = *fromlen;
172
    msg.lpBuffers = &wsabuf;
173
    msg.dwBufferCount = 1;
174
    msg.Control.len = sizeof(cmsg);
175
    msg.Control.buf = cmsg;
176
    msg.dwFlags = 0;
177
178
    if (pfWSARecvMsg) {
179
        r = pfWSARecvMsg(s, &msg, &bytes_received, NULL, NULL) == 0 ?
180
            bytes_received : -1;
181
        *fromlen = msg.namelen;
182
    } else {
183
        r = recvfrom(s, buf, len, MSG_DONTWAIT, from, fromlen);
184
    }
185
#endif /* !defined(WIN32) */
186
187
0
    if (r == -1) {
188
0
        return -1;
189
0
    }
190
191
0
    DEBUGMSGTL(("udpbase:recv", "got source addr: %s\n",
192
0
                inet_ntoa(((struct sockaddr_in *)from)->sin_addr)));
193
194
0
    {
195
        /* Get the local port number for use in diagnostic messages */
196
0
        int r2 = getsockname(s, dstip, dstlen);
197
0
        netsnmp_assert(r2 == 0);
198
0
    }
199
200
0
#if !defined(WIN32)
201
0
    for (cm = CMSG_FIRSTHDR(&msg); cm != NULL; cm = CMSG_NXTHDR(&msg, cm)) {
202
0
#if defined(HAVE_IP_PKTINFO)
203
0
        if (cm->cmsg_level == SOL_IP && cm->cmsg_type == IP_PKTINFO) {
204
0
            struct in_pktinfo* src = (struct in_pktinfo *)CMSG_DATA(cm);
205
0
            netsnmp_assert(dstip->sa_family == AF_INET);
206
0
            ((struct sockaddr_in*)dstip)->sin_addr = src->ipi_addr;
207
0
            *if_index = src->ipi_ifindex;
208
0
            DEBUGMSGTL(("udpbase:recv",
209
0
                        "got destination (local) addr %s, iface %d\n",
210
0
                        inet_ntoa(src->ipi_addr), *if_index));
211
0
        }
212
#elif defined(HAVE_IP_RECVDSTADDR)
213
        if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR) {
214
            struct in_addr* src = (struct in_addr *)CMSG_DATA(cm);
215
            ((struct sockaddr_in*)dstip)->sin_addr = *src;
216
            DEBUGMSGTL(("netsnmp_udp", "got destination (local) addr %s\n",
217
                        inet_ntoa(*src)));
218
        }
219
#endif
220
0
    }
221
#else /* !defined(WIN32) */
222
    for (cm = WSA_CMSG_FIRSTHDR(&msg); cm; cm = WSA_CMSG_NXTHDR(&msg, cm)) {
223
        if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_PKTINFO) {
224
            struct in_pktinfo* src = (struct in_pktinfo *)WSA_CMSG_DATA(cm);
225
            netsnmp_assert(dstip->sa_family == AF_INET);
226
            ((struct sockaddr_in*)dstip)->sin_addr = src->ipi_addr;
227
            *if_index = src->ipi_ifindex;
228
            DEBUGMSGTL(("udpbase:recv",
229
                        "got destination (local) addr %s, iface %d\n",
230
                        inet_ntoa(src->ipi_addr), *if_index));
231
        }
232
    }
233
#endif /* !defined(WIN32) */
234
0
    return r;
235
0
}
236
237
#if !defined(WIN32)
238
int netsnmp_udpbase_sendto_unix(int fd, const struct in_addr *srcip,
239
                                int if_index, const struct sockaddr *remote,
240
                                const void *data, int len)
241
0
{
242
0
    struct iovec iov;
243
0
    struct msghdr m = { NULL };
244
0
    char          cmsg[CMSG_SPACE(cmsg_data_size)];
245
0
    int           rc;
246
0
    char          iface[IFNAMSIZ];
247
0
    socklen_t     ifacelen = IFNAMSIZ;
248
249
0
    iov.iov_base = NETSNMP_REMOVE_CONST(void *, data);
250
0
    iov.iov_len  = len;
251
252
0
    m.msg_name    = NETSNMP_REMOVE_CONST(void *, remote);
253
0
    m.msg_namelen = sizeof(struct sockaddr_in);
254
0
    m.msg_iov   = &iov;
255
0
    m.msg_iovlen  = 1;
256
0
    m.msg_flags   = 0;
257
258
0
    if (srcip && srcip->s_addr != INADDR_ANY) {
259
0
        struct cmsghdr *cm;
260
0
        struct in_pktinfo ipi;
261
0
        int use_sendto = FALSE;
262
263
0
        memset(cmsg, 0, sizeof(cmsg));
264
265
0
        m.msg_control    = &cmsg;
266
0
        m.msg_controllen = sizeof(cmsg);
267
268
0
        cm = CMSG_FIRSTHDR(&m);
269
0
        cm->cmsg_len = CMSG_LEN(cmsg_data_size);
270
271
0
#if defined(HAVE_IP_PKTINFO)
272
0
        cm->cmsg_level = SOL_IP;
273
0
        cm->cmsg_type = IP_PKTINFO;
274
275
0
        memset(&ipi, 0, sizeof(ipi));
276
0
#ifdef HAVE_SO_BINDTODEVICE
277
        /*
278
         * For asymmetric multihomed users, we only set ifindex to 0 to
279
         * let kernel handle return if there was no iface bound to the
280
         * socket.
281
         */
282
0
        if (getsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, iface,
283
0
                       &ifacelen) != 0)  {
284
0
            DEBUGMSGTL(("udpbase:sendto",
285
0
                        "getsockopt SO_BINDTODEVICE failed: %s\n",
286
0
                        strerror(errno)));
287
0
        } else if (ifacelen == 0) {
288
0
            DEBUGMSGTL(("udpbase:sendto",
289
0
                        "sendto: SO_BINDTODEVICE not set\n"));
290
0
        } else {
291
0
            DEBUGMSGTL(("udpbase:sendto",
292
0
                        "sendto: SO_BINDTODEVICE dev=%s using ifindex=%d\n",
293
0
                        iface, if_index));
294
0
            use_sendto = TRUE;
295
0
        }
296
0
#endif /* HAVE_SO_BINDTODEVICE */
297
298
0
#ifdef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST
299
0
        DEBUGMSGTL(("udpbase:sendto", "sending from %s\n",
300
0
                    inet_ntoa(*srcip)));
301
0
        ipi.ipi_spec_dst.s_addr = srcip->s_addr;
302
#else
303
        DEBUGMSGTL(("udpbase:sendto", "ignoring from address %s\n",
304
                    inet_ntoa(*srcip)));
305
#endif
306
0
        memcpy(CMSG_DATA(cm), &ipi, sizeof(ipi));
307
308
        /*
309
         * For Linux and VRF, use sendto() instead of sendmsg(). Do not pass a
310
         * cmsg with IP_PKTINFO set because that would override the bind to
311
         * VRF which is set by 'vrf exec' command. That would break VRF.
312
         */
313
0
        if (use_sendto)
314
0
            rc = sendto(fd, data, len, MSG_DONTWAIT, remote,
315
0
                        sizeof(struct sockaddr));
316
0
        else
317
0
            rc = sendmsg(fd, &m, MSG_DONTWAIT);
318
0
        if (rc >= 0 || (errno != EINVAL && errno != ENETUNREACH))
319
0
            return rc;
320
321
        /*
322
         * The error might be caused by broadcast srcip (i.e. we're responding
323
         * to a broadcast request) - sendmsg does not like it. Try to resend it
324
         * using the interface on which it was received
325
         */
326
327
0
        DEBUGMSGTL(("udpbase:sendto", "re-sending on iface %d\n", if_index));
328
329
0
        {
330
0
            struct in_pktinfo ipi;
331
332
0
            memset(&ipi, 0, sizeof(ipi));
333
0
            ipi.ipi_ifindex = if_index;
334
0
#ifdef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST
335
0
            ipi.ipi_spec_dst.s_addr = INADDR_ANY;
336
0
#endif
337
0
            memcpy(CMSG_DATA(cm), &ipi, sizeof(ipi));
338
0
        }
339
#elif defined(HAVE_IP_SENDSRCADDR)
340
        cm->cmsg_level = IPPROTO_IP;
341
        cm->cmsg_type = IP_SENDSRCADDR;
342
        memcpy((struct in_addr *)CMSG_DATA(cm), srcip, sizeof(struct in_addr));
343
#endif
344
0
        rc = sendmsg(fd, &m, MSG_DONTWAIT);
345
0
        if (rc >= 0 || errno != EINVAL)
346
0
            return rc;
347
348
0
        DEBUGMSGTL(("udpbase:sendto", "re-sending without source address\n"));
349
0
        m.msg_control = NULL;
350
0
        m.msg_controllen = 0;
351
0
    }
352
353
0
    return sendmsg(fd, &m, MSG_DONTWAIT);
354
0
}
355
#else /* !defined(WIN32) */
356
int netsnmp_udpbase_sendto_win32(int fd, const struct in_addr *srcip,
357
                                 int if_index, const struct sockaddr *remote,
358
                                 const void *data, int len)
359
{
360
    WSABUF        wsabuf;
361
    WSAMSG        m;
362
    char          cmsg[WSA_CMSG_SPACE(sizeof(struct in_pktinfo))];
363
    DWORD         bytes_sent;
364
    int           rc;
365
366
    wsabuf.buf = NETSNMP_REMOVE_CONST(void *, data);
367
    wsabuf.len = len;
368
369
    memset(&m, 0, sizeof(m));
370
    m.name          = NETSNMP_REMOVE_CONST(struct sockaddr *, remote);
371
    m.namelen       = sizeof(struct sockaddr_in);
372
    m.lpBuffers     = &wsabuf;
373
    m.dwBufferCount = 1;
374
375
    if (pfWSASendMsg && srcip && srcip->s_addr != INADDR_ANY) {
376
        WSACMSGHDR *cm;
377
378
        DEBUGMSGTL(("udpbase:sendto", "sending from [%d] %s\n", if_index,
379
                    inet_ntoa(*srcip)));
380
381
        memset(cmsg, 0, sizeof(cmsg));
382
383
        m.Control.buf = cmsg;
384
        m.Control.len = sizeof(cmsg);
385
386
        cm = WSA_CMSG_FIRSTHDR(&m);
387
        cm->cmsg_len = WSA_CMSG_LEN(cmsg_data_size);
388
        cm->cmsg_level = IPPROTO_IP;
389
        cm->cmsg_type = IP_PKTINFO;
390
391
        {
392
            struct in_pktinfo ipi = { 0 };
393
            ipi.ipi_ifindex = if_index;
394
            ipi.ipi_addr.s_addr = srcip->s_addr;
395
            memcpy(WSA_CMSG_DATA(cm), &ipi, sizeof(ipi));
396
        }
397
398
        rc = pfWSASendMsg(fd, &m, 0, &bytes_sent, NULL, NULL);
399
        if (rc == 0)
400
            return bytes_sent;
401
        DEBUGMSGTL(("udpbase:sendto", "sending from [%d] %s failed: %d\n",
402
                    if_index, inet_ntoa(*srcip), WSAGetLastError()));
403
    }
404
    rc = sendto(fd, data, len, 0, remote, sizeof(struct sockaddr));
405
    return rc;
406
}
407
#endif /* !defined(WIN32) */
408
409
int netsnmp_udpbase_sendto(int fd, const struct in_addr *srcip, int if_index,
410
                           const struct sockaddr *remote, const void *data,
411
                           int len)
412
0
{
413
0
#if !defined(WIN32)
414
0
    return netsnmp_udpbase_sendto_unix(fd, srcip, if_index, remote, data, len);
415
#else /* !defined(WIN32) */
416
    return netsnmp_udpbase_sendto_win32(fd, srcip, if_index, remote, data, len);
417
#endif /* !defined(WIN32) */
418
0
}
419
#endif /* HAVE_IP_PKTINFO || HAVE_IP_RECVDSTADDR */
420
421
/*
422
 * You can write something into opaque that will subsequently get passed back 
423
 * to your send function if you like.  For instance, you might want to
424
 * remember where a PDU came from, so that you can send a reply there...  
425
 */
426
427
int
428
netsnmp_udpbase_recv(netsnmp_transport *t, void *buf, int size,
429
                     void **opaque, int *olength)
430
0
{
431
0
    int             rc = -1;
432
0
    socklen_t       fromlen = sizeof(netsnmp_sockaddr_storage);
433
0
    netsnmp_indexed_addr_pair *addr_pair = NULL;
434
0
    struct sockaddr *from;
435
436
0
    if (t != NULL && t->sock >= 0) {
437
0
        addr_pair = SNMP_MALLOC_TYPEDEF(netsnmp_indexed_addr_pair);
438
0
        if (addr_pair == NULL) {
439
0
            *opaque = NULL;
440
0
            *olength = 0;
441
0
            return -1;
442
0
        } else
443
0
            from = &addr_pair->remote_addr.sa;
444
445
0
  while (rc < 0) {
446
0
#ifdef netsnmp_udpbase_recvfrom_sendto_defined
447
0
            socklen_t local_addr_len = sizeof(addr_pair->local_addr);
448
0
            rc = netsnmp_udp_recvfrom(t->sock, buf, size, from, &fromlen,
449
0
                                      &addr_pair->local_addr.sa,
450
0
                                      &local_addr_len, &(addr_pair->if_index));
451
#else
452
            rc = recvfrom(t->sock, buf, size, MSG_DONTWAIT, from, &fromlen);
453
#endif /* netsnmp_udpbase_recvfrom_sendto_defined */
454
0
      if (rc < 0 && errno != EINTR) {
455
0
    break;
456
0
      }
457
0
  }
458
459
0
        if (rc >= 0) {
460
0
            DEBUGIF("netsnmp_udp") {
461
0
                char *str = netsnmp_udp_fmtaddr(
462
0
                    NULL, addr_pair, sizeof(netsnmp_indexed_addr_pair));
463
0
                DEBUGMSGTL(("netsnmp_udp",
464
0
                            "recvfrom fd %d got %d bytes (from %s)\n",
465
0
                            t->sock, rc, str));
466
0
                free(str);
467
0
            }
468
0
        } else {
469
0
            DEBUGMSGTL(("netsnmp_udp", "recvfrom fd %d err %d (\"%s\")\n",
470
0
                        t->sock, errno, strerror(errno)));
471
0
        }
472
0
        *opaque = (void *)addr_pair;
473
0
        *olength = sizeof(netsnmp_indexed_addr_pair);
474
0
    }
475
0
    return rc;
476
0
}
477
478
479
480
int
481
netsnmp_udpbase_send(netsnmp_transport *t, const void *buf, int size,
482
                     void **opaque, int *olength)
483
0
{
484
0
    int rc = -1;
485
0
    const netsnmp_indexed_addr_pair *addr_pair = NULL;
486
0
    const struct sockaddr *to = NULL;
487
488
0
    if (opaque != NULL && *opaque != NULL && NULL != olength &&
489
0
        ((*olength == sizeof(netsnmp_indexed_addr_pair) ||
490
0
          (*olength == sizeof(struct sockaddr_in))))) {
491
0
        addr_pair = (const netsnmp_indexed_addr_pair *) (*opaque);
492
0
    } else if (t != NULL && t->data != NULL &&
493
0
                t->data_length == sizeof(netsnmp_indexed_addr_pair)) {
494
0
        addr_pair = (netsnmp_indexed_addr_pair *) (t->data);
495
0
    } else {
496
0
        int len = -1;
497
0
        if (opaque != NULL && *opaque != NULL && NULL != olength)
498
0
            len = *olength;
499
0
        else if (t != NULL && t->data != NULL)
500
0
            len = t->data_length;
501
0
        snmp_log(LOG_ERR, "unknown addr type of size %d\n", len);
502
0
        return SNMPERR_GENERR;
503
0
    }
504
505
0
    to = &addr_pair->remote_addr.sa;
506
507
0
    if (to != NULL && t != NULL && t->sock >= 0) {
508
0
        DEBUGIF("netsnmp_udp") {
509
0
            char *str = netsnmp_udp_fmtaddr(NULL, addr_pair,
510
0
                                            sizeof(netsnmp_indexed_addr_pair));
511
0
            DEBUGMSGTL(("netsnmp_udp", "send %d bytes from %p to %s on fd %d\n",
512
0
                        size, buf, str, t->sock));
513
0
            free(str);
514
0
        }
515
0
  while (rc < 0) {
516
0
#ifdef netsnmp_udpbase_recvfrom_sendto_defined
517
0
            rc = netsnmp_udp_sendto(t->sock,
518
0
                    addr_pair ? &(addr_pair->local_addr.sin.sin_addr) : NULL,
519
0
                    addr_pair ? addr_pair->if_index : 0, to, buf, size);
520
#else
521
            rc = sendto(t->sock, buf, size, 0, to, sizeof(struct sockaddr));
522
#endif /* netsnmp_udpbase_recvfrom_sendto_defined */
523
0
      if (rc < 0 && errno != EINTR) {
524
0
                DEBUGMSGTL(("netsnmp_udp", "sendto error, rc %d (errno %d)\n",
525
0
                            rc, errno));
526
0
    break;
527
0
      }
528
0
  }
529
0
    }
530
0
    return rc;
531
0
}
532
533
void
534
netsnmp_udp_base_ctor(void)
535
0
{
536
#if defined(WIN32) && defined(HAVE_IP_PKTINFO)
537
    SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
538
    GUID WSARecvMsgGuid = WSAID_WSARECVMSG;
539
    GUID WSASendMsgGuid = WSAID_WSASENDMSG;
540
    DWORD nbytes;
541
    int result;
542
543
    netsnmp_static_assert(sizeof(in_addr_t) ==
544
                          sizeof((struct sockaddr_in *)NULL)->sin_addr);
545
    netsnmp_assert(s != SOCKET_ERROR);
546
    /* WSARecvMsg(): Windows XP / Windows Server 2003 and later */
547
    result = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
548
                      &WSARecvMsgGuid, sizeof(WSARecvMsgGuid),
549
                      &pfWSARecvMsg, sizeof(pfWSARecvMsg), &nbytes, NULL, NULL);
550
    if (result == SOCKET_ERROR)
551
        DEBUGMSGTL(("netsnmp_udp", "WSARecvMsg() not found (errno %d)\n",
552
                    WSAGetLastError()));
553
554
    /* WSASendMsg(): Windows Vista / Windows Server 2008 and later */
555
    result = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
556
                      &WSASendMsgGuid, sizeof(WSASendMsgGuid),
557
                      &pfWSASendMsg, sizeof(pfWSASendMsg), &nbytes, NULL, NULL);
558
    if (result == SOCKET_ERROR)
559
        DEBUGMSGTL(("netsnmp_udp", "WSASendMsg() not found (errno %d)\n",
560
                    WSAGetLastError()));
561
562
    closesocket(s);
563
#endif
564
0
}