| Current File : //usr/share/doc/net-snmp/html/snmpUDPDomain_8c_source.html |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<title>net-snmp: snmpUDPDomain.c Source File</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td style="padding-left: 0.5em;">
<div id="projectname">net-snmp
 <span id="projectnumber">5.4.1</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Generated by Doxygen 1.7.6.1 -->
<div id="navrow1" class="tabs">
<ul class="tablist">
<li><a href="index.html"><span>Main Page</span></a></li>
<li><a href="pages.html"><span>Related Pages</span></a></li>
<li><a href="modules.html"><span>Modules</span></a></li>
<li><a href="annotated.html"><span>Data Structures</span></a></li>
<li class="current"><a href="files.html"><span>Files</span></a></li>
<li><a href="examples.html"><span>Examples</span></a></li>
</ul>
</div>
<div id="navrow2" class="tabs2">
<ul class="tablist">
<li><a href="files.html"><span>File List</span></a></li>
<li><a href="globals.html"><span>Globals</span></a></li>
</ul>
</div>
</div>
<div class="header">
<div class="headertitle">
<div class="title">snmpUDPDomain.c</div> </div>
</div><!--header-->
<div class="contents">
<div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/* Portions of this file are subject to the following copyright(s). See</span>
<a name="l00002"></a>00002 <span class="comment"> * the Net-SNMP's COPYING file for more details and other copyrights</span>
<a name="l00003"></a>00003 <span class="comment"> * that may apply:</span>
<a name="l00004"></a>00004 <span class="comment"> */</span>
<a name="l00005"></a>00005 <span class="comment">/*</span>
<a name="l00006"></a>00006 <span class="comment"> * Portions of this file are copyrighted by:</span>
<a name="l00007"></a>00007 <span class="comment"> * Copyright Copyright 2003 Sun Microsystems, Inc. All rights reserved.</span>
<a name="l00008"></a>00008 <span class="comment"> * Use is subject to license terms specified in the COPYING file</span>
<a name="l00009"></a>00009 <span class="comment"> * distributed with the Net-SNMP package.</span>
<a name="l00010"></a>00010 <span class="comment"> */</span>
<a name="l00011"></a>00011
<a name="l00012"></a>00012 <span class="preprocessor">#include <net-snmp/net-snmp-config.h></span>
<a name="l00013"></a>00013
<a name="l00014"></a>00014 <span class="preprocessor">#include <stdio.h></span>
<a name="l00015"></a>00015 <span class="preprocessor">#include <sys/types.h></span>
<a name="l00016"></a>00016 <span class="preprocessor">#include <ctype.h></span>
<a name="l00017"></a>00017 <span class="preprocessor">#include <errno.h></span>
<a name="l00018"></a>00018
<a name="l00019"></a>00019 <span class="preprocessor">#if HAVE_STRING_H</span>
<a name="l00020"></a>00020 <span class="preprocessor"></span><span class="preprocessor">#include <string.h></span>
<a name="l00021"></a>00021 <span class="preprocessor">#else</span>
<a name="l00022"></a>00022 <span class="preprocessor"></span><span class="preprocessor">#include <strings.h></span>
<a name="l00023"></a>00023 <span class="preprocessor">#endif</span>
<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#if HAVE_STDLIB_H</span>
<a name="l00025"></a>00025 <span class="preprocessor"></span><span class="preprocessor">#include <stdlib.h></span>
<a name="l00026"></a>00026 <span class="preprocessor">#endif</span>
<a name="l00027"></a>00027 <span class="preprocessor"></span><span class="preprocessor">#if HAVE_UNISTD_H</span>
<a name="l00028"></a>00028 <span class="preprocessor"></span><span class="preprocessor">#include <unistd.h></span>
<a name="l00029"></a>00029 <span class="preprocessor">#endif</span>
<a name="l00030"></a>00030 <span class="preprocessor"></span><span class="preprocessor">#if HAVE_SYS_SOCKET_H</span>
<a name="l00031"></a>00031 <span class="preprocessor"></span><span class="preprocessor">#include <sys/socket.h></span>
<a name="l00032"></a>00032 <span class="preprocessor">#endif</span>
<a name="l00033"></a>00033 <span class="preprocessor"></span><span class="preprocessor">#if HAVE_NETINET_IN_H</span>
<a name="l00034"></a>00034 <span class="preprocessor"></span><span class="preprocessor">#include <netinet/in.h></span>
<a name="l00035"></a>00035 <span class="preprocessor">#endif</span>
<a name="l00036"></a>00036 <span class="preprocessor"></span><span class="preprocessor">#if HAVE_ARPA_INET_H</span>
<a name="l00037"></a>00037 <span class="preprocessor"></span><span class="preprocessor">#include <arpa/inet.h></span>
<a name="l00038"></a>00038 <span class="preprocessor">#endif</span>
<a name="l00039"></a>00039 <span class="preprocessor"></span><span class="preprocessor">#if HAVE_NETDB_H</span>
<a name="l00040"></a>00040 <span class="preprocessor"></span><span class="preprocessor">#include <netdb.h></span>
<a name="l00041"></a>00041 <span class="preprocessor">#endif</span>
<a name="l00042"></a>00042 <span class="preprocessor"></span><span class="preprocessor">#if HAVE_SYS_UIO_H</span>
<a name="l00043"></a>00043 <span class="preprocessor"></span><span class="preprocessor">#include <sys/uio.h></span>
<a name="l00044"></a>00044 <span class="preprocessor">#endif</span>
<a name="l00045"></a>00045 <span class="preprocessor"></span>
<a name="l00046"></a>00046 <span class="preprocessor">#if HAVE_WINSOCK_H</span>
<a name="l00047"></a>00047 <span class="preprocessor"></span><span class="preprocessor">#include <winsock2.h></span>
<a name="l00048"></a>00048 <span class="preprocessor">#include <ws2tcpip.h></span>
<a name="l00049"></a>00049 <span class="preprocessor">#endif</span>
<a name="l00050"></a>00050 <span class="preprocessor"></span>
<a name="l00051"></a>00051 <span class="preprocessor">#if HAVE_DMALLOC_H</span>
<a name="l00052"></a>00052 <span class="preprocessor"></span><span class="preprocessor">#include <dmalloc.h></span>
<a name="l00053"></a>00053 <span class="preprocessor">#endif</span>
<a name="l00054"></a>00054 <span class="preprocessor"></span>
<a name="l00055"></a>00055 <span class="preprocessor">#include <net-snmp/types.h></span>
<a name="l00056"></a>00056 <span class="preprocessor">#include <net-snmp/output_api.h></span>
<a name="l00057"></a>00057 <span class="preprocessor">#include <net-snmp/config_api.h></span>
<a name="l00058"></a>00058
<a name="l00059"></a>00059 <span class="preprocessor">#include <net-snmp/library/snmp_transport.h></span>
<a name="l00060"></a>00060 <span class="preprocessor">#include <net-snmp/library/snmpUDPDomain.h></span>
<a name="l00061"></a>00061 <span class="preprocessor">#include <net-snmp/library/system.h></span>
<a name="l00062"></a>00062 <span class="preprocessor">#include <<a class="code" href="tools_8h.html">net-snmp/library/tools.h</a>></span>
<a name="l00063"></a>00063
<a name="l00064"></a>00064 <span class="preprocessor">#ifndef INADDR_NONE</span>
<a name="l00065"></a>00065 <span class="preprocessor"></span><span class="preprocessor">#define INADDR_NONE -1</span>
<a name="l00066"></a>00066 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
<a name="l00067"></a>00067 <span class="preprocessor"></span>
<a name="l00068"></a>00068 <span class="keyword">static</span> <a class="code" href="structnetsnmp__tdomain__s.html">netsnmp_tdomain</a> udpDomain;
<a name="l00069"></a>00069
<a name="l00070"></a>00070 <span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair_s</a> {
<a name="l00071"></a>00071 <span class="keyword">struct </span>sockaddr_in remote_addr;
<a name="l00072"></a>00072 <span class="keyword">struct </span>in_addr local_addr;
<a name="l00073"></a>00073 } <a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>;
<a name="l00074"></a>00074
<a name="l00075"></a>00075 <span class="comment">/*</span>
<a name="l00076"></a>00076 <span class="comment"> * not static, since snmpUDPIPv6Domain needs it, but not public, either.</span>
<a name="l00077"></a>00077 <span class="comment"> * (ie don't put it in a public header.)</span>
<a name="l00078"></a>00078 <span class="comment"> */</span>
<a name="l00079"></a>00079 <span class="keywordtype">void</span> _netsnmp_udp_sockopt_set(<span class="keywordtype">int</span> fd, <span class="keywordtype">int</span> server);
<a name="l00080"></a>00080 <span class="keywordtype">int</span>
<a name="l00081"></a>00081 netsnmp_sockaddr_in2(<span class="keyword">struct</span> sockaddr_in *addr,
<a name="l00082"></a>00082 <span class="keyword">const</span> <span class="keywordtype">char</span> *inpeername, <span class="keyword">const</span> <span class="keywordtype">char</span> *default_target);
<a name="l00083"></a>00083
<a name="l00084"></a>00084 <span class="comment">/*</span>
<a name="l00085"></a>00085 <span class="comment"> * Return a string representing the address in data, or else the "far end"</span>
<a name="l00086"></a>00086 <span class="comment"> * address if data is NULL. </span>
<a name="l00087"></a>00087 <span class="comment"> */</span>
<a name="l00088"></a>00088
<a name="l00089"></a>00089 <span class="keyword">static</span> <span class="keywordtype">char</span> *
<a name="l00090"></a>00090 netsnmp_udp_fmtaddr(<a class="code" href="structnetsnmp__transport__s.html">netsnmp_transport</a> *t, <span class="keywordtype">void</span> *data, <span class="keywordtype">int</span> len)
<a name="l00091"></a>00091 {
<a name="l00092"></a>00092 <a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a> *addr_pair = NULL;
<a name="l00093"></a>00093
<a name="l00094"></a>00094 <span class="keywordflow">if</span> (data != NULL && len == <span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>)) {
<a name="l00095"></a>00095 addr_pair = (<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a> *) data;
<a name="l00096"></a>00096 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (t != NULL && t->data != NULL) {
<a name="l00097"></a>00097 addr_pair = (<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a> *) t->data;
<a name="l00098"></a>00098 }
<a name="l00099"></a>00099
<a name="l00100"></a>00100 <span class="keywordflow">if</span> (addr_pair == NULL) {
<a name="l00101"></a>00101 <span class="keywordflow">return</span> strdup(<span class="stringliteral">"UDP: unknown"</span>);
<a name="l00102"></a>00102 } <span class="keywordflow">else</span> {
<a name="l00103"></a>00103 <span class="keyword">struct </span>sockaddr_in *to = NULL;
<a name="l00104"></a>00104 <span class="keywordtype">char</span> tmp[64];
<a name="l00105"></a>00105 to = (<span class="keyword">struct </span>sockaddr_in *) &(addr_pair->remote_addr);
<a name="l00106"></a>00106 <span class="keywordflow">if</span> (to == NULL) {
<a name="l00107"></a>00107 <span class="keywordflow">return</span> strdup(<span class="stringliteral">"UDP: unknown"</span>);
<a name="l00108"></a>00108 }
<a name="l00109"></a>00109
<a name="l00110"></a>00110 sprintf(tmp, <span class="stringliteral">"UDP: [%s]:%hu"</span>,
<a name="l00111"></a>00111 inet_ntoa(to->sin_addr), ntohs(to->sin_port));
<a name="l00112"></a>00112 <span class="keywordflow">return</span> strdup(tmp);
<a name="l00113"></a>00113 }
<a name="l00114"></a>00114 }
<a name="l00115"></a>00115
<a name="l00116"></a>00116
<a name="l00117"></a>00117
<a name="l00118"></a>00118 <span class="preprocessor">#if defined(linux) && defined(IP_PKTINFO)</span>
<a name="l00119"></a>00119 <span class="preprocessor"></span>
<a name="l00120"></a>00120 <span class="preprocessor"># define netsnmp_dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))</span>
<a name="l00121"></a>00121 <span class="preprocessor"></span>
<a name="l00122"></a>00122 <span class="keyword">static</span> <span class="keywordtype">int</span> netsnmp_udp_recvfrom(<span class="keywordtype">int</span> s, <span class="keywordtype">void</span> *buf, <span class="keywordtype">int</span> len, <span class="keyword">struct</span> sockaddr *from, socklen_t *fromlen, <span class="keyword">struct</span> in_addr *dstip)
<a name="l00123"></a>00123 {
<a name="l00124"></a>00124 <span class="keywordtype">int</span> r;
<a name="l00125"></a>00125 <span class="keyword">struct </span>iovec iov[1];
<a name="l00126"></a>00126 <span class="keywordtype">char</span> cmsg[CMSG_SPACE(<span class="keyword">sizeof</span>(<span class="keyword">struct</span> in_pktinfo))];
<a name="l00127"></a>00127 <span class="keyword">struct </span>cmsghdr *cmsgptr;
<a name="l00128"></a>00128 <span class="keyword">struct </span>msghdr msg;
<a name="l00129"></a>00129
<a name="l00130"></a>00130 iov[0].iov_base = buf;
<a name="l00131"></a>00131 iov[0].iov_len = len;
<a name="l00132"></a>00132
<a name="l00133"></a>00133 memset(&msg, 0, <span class="keyword">sizeof</span> msg);
<a name="l00134"></a>00134 msg.msg_name = from;
<a name="l00135"></a>00135 msg.msg_namelen = *fromlen;
<a name="l00136"></a>00136 msg.msg_iov = iov;
<a name="l00137"></a>00137 msg.msg_iovlen = 1;
<a name="l00138"></a>00138 msg.msg_control = &cmsg;
<a name="l00139"></a>00139 msg.msg_controllen = <span class="keyword">sizeof</span>(cmsg);
<a name="l00140"></a>00140
<a name="l00141"></a>00141 r = recvmsg(s, &msg, 0);
<a name="l00142"></a>00142
<a name="l00143"></a>00143 <span class="keywordflow">if</span> (r == -1) {
<a name="l00144"></a>00144 <span class="keywordflow">return</span> -1;
<a name="l00145"></a>00145 }
<a name="l00146"></a>00146
<a name="l00147"></a>00147 DEBUGMSGTL((<span class="stringliteral">"netsnmp_udp"</span>, <span class="stringliteral">"got source addr: %s\n"</span>, inet_ntoa(((<span class="keyword">struct</span> sockaddr_in *)from)->sin_addr)));
<a name="l00148"></a>00148 <span class="keywordflow">for</span> (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
<a name="l00149"></a>00149 <span class="keywordflow">if</span> (cmsgptr->cmsg_level == SOL_IP && cmsgptr->cmsg_type == IP_PKTINFO) {
<a name="l00150"></a>00150 memcpy((<span class="keywordtype">void</span> *) dstip, netsnmp_dstaddr(cmsgptr), <span class="keyword">sizeof</span>(<span class="keyword">struct</span> in_addr));
<a name="l00151"></a>00151 DEBUGMSGTL((<span class="stringliteral">"netsnmp_udp"</span>, <span class="stringliteral">"got destination (local) addr %s\n"</span>,
<a name="l00152"></a>00152 inet_ntoa(*dstip)));
<a name="l00153"></a>00153 }
<a name="l00154"></a>00154 }
<a name="l00155"></a>00155 <span class="keywordflow">return</span> r;
<a name="l00156"></a>00156 }
<a name="l00157"></a>00157
<a name="l00158"></a>00158 <span class="keyword">static</span> <span class="keywordtype">int</span> netsnmp_udp_sendto(<span class="keywordtype">int</span> fd, <span class="keyword">struct</span> in_addr *srcip, <span class="keyword">struct</span> sockaddr *remote,
<a name="l00159"></a>00159 <span class="keywordtype">void</span> *data, <span class="keywordtype">int</span> len)
<a name="l00160"></a>00160 {
<a name="l00161"></a>00161 <span class="keyword">struct </span>iovec iov = { data, len };
<a name="l00162"></a>00162 <span class="keyword">struct </span>{
<a name="l00163"></a>00163 <span class="keyword">struct </span>cmsghdr cm;
<a name="l00164"></a>00164 <span class="keyword">struct </span>in_pktinfo ipi;
<a name="l00165"></a>00165 } cmsg;
<a name="l00166"></a>00166 <span class="keyword">struct </span>msghdr m;
<a name="l00167"></a>00167
<a name="l00168"></a>00168 cmsg.cm.cmsg_len = <span class="keyword">sizeof</span>(<span class="keyword">struct </span>cmsghdr) + sizeof(struct in_pktinfo);
<a name="l00169"></a>00169 cmsg.cm.cmsg_level = SOL_IP;
<a name="l00170"></a>00170 cmsg.cm.cmsg_type = IP_PKTINFO;
<a name="l00171"></a>00171 cmsg.ipi.ipi_ifindex = 0;
<a name="l00172"></a>00172 cmsg.ipi.ipi_spec_dst.s_addr = (srcip ? srcip->s_addr : INADDR_ANY);
<a name="l00173"></a>00173
<a name="l00174"></a>00174 m.msg_name = remote;
<a name="l00175"></a>00175 m.msg_namelen = <span class="keyword">sizeof</span>(<span class="keyword">struct </span>sockaddr_in);
<a name="l00176"></a>00176 m.msg_iov = &iov;
<a name="l00177"></a>00177 m.msg_iovlen = 1;
<a name="l00178"></a>00178 m.msg_control = &cmsg;
<a name="l00179"></a>00179 m.msg_controllen = <span class="keyword">sizeof</span>(cmsg);
<a name="l00180"></a>00180 m.msg_flags = 0;
<a name="l00181"></a>00181
<a name="l00182"></a>00182 <span class="keywordflow">return</span> sendmsg(fd, &m, MSG_NOSIGNAL|MSG_DONTWAIT);
<a name="l00183"></a>00183 }
<a name="l00184"></a>00184 <span class="preprocessor">#endif </span><span class="comment">/* linux && IP_PKTINFO */</span>
<a name="l00185"></a>00185
<a name="l00186"></a>00186 <span class="comment">/*</span>
<a name="l00187"></a>00187 <span class="comment"> * You can write something into opaque that will subsequently get passed back </span>
<a name="l00188"></a>00188 <span class="comment"> * to your send function if you like. For instance, you might want to</span>
<a name="l00189"></a>00189 <span class="comment"> * remember where a PDU came from, so that you can send a reply there... </span>
<a name="l00190"></a>00190 <span class="comment"> */</span>
<a name="l00191"></a>00191
<a name="l00192"></a>00192 <span class="keyword">static</span> <span class="keywordtype">int</span>
<a name="l00193"></a>00193 netsnmp_udp_recv(<a class="code" href="structnetsnmp__transport__s.html">netsnmp_transport</a> *t, <span class="keywordtype">void</span> *buf, <span class="keywordtype">int</span> size,
<a name="l00194"></a>00194 <span class="keywordtype">void</span> **opaque, <span class="keywordtype">int</span> *olength)
<a name="l00195"></a>00195 {
<a name="l00196"></a>00196 <span class="keywordtype">int</span> rc = -1;
<a name="l00197"></a>00197 socklen_t fromlen = <span class="keyword">sizeof</span>(<span class="keyword">struct </span>sockaddr);
<a name="l00198"></a>00198 <a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a> *addr_pair = NULL;
<a name="l00199"></a>00199 <span class="keyword">struct </span>sockaddr *from;
<a name="l00200"></a>00200
<a name="l00201"></a>00201 <span class="keywordflow">if</span> (t != NULL && t->sock >= 0) {
<a name="l00202"></a>00202 addr_pair = (<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a> *) malloc(<span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>));
<a name="l00203"></a>00203 <span class="keywordflow">if</span> (addr_pair == NULL) {
<a name="l00204"></a>00204 *opaque = NULL;
<a name="l00205"></a>00205 *olength = 0;
<a name="l00206"></a>00206 <span class="keywordflow">return</span> -1;
<a name="l00207"></a>00207 } <span class="keywordflow">else</span> {
<a name="l00208"></a>00208 memset(addr_pair, 0, <span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>));
<a name="l00209"></a>00209 from = (<span class="keyword">struct </span>sockaddr *) &(addr_pair->remote_addr);
<a name="l00210"></a>00210 }
<a name="l00211"></a>00211
<a name="l00212"></a>00212 <span class="keywordflow">while</span> (rc < 0) {
<a name="l00213"></a>00213 <span class="preprocessor">#if defined(linux) && defined(IP_PKTINFO)</span>
<a name="l00214"></a>00214 <span class="preprocessor"></span> rc = netsnmp_udp_recvfrom(t->sock, buf, size, from, &fromlen, &(addr_pair->local_addr));
<a name="l00215"></a>00215 <span class="preprocessor">#else</span>
<a name="l00216"></a>00216 <span class="preprocessor"></span> rc = recvfrom(t->sock, buf, size, 0, from, &fromlen);
<a name="l00217"></a>00217 <span class="preprocessor">#endif </span><span class="comment">/* linux && IP_PKTINFO */</span>
<a name="l00218"></a>00218 <span class="keywordflow">if</span> (rc < 0 && errno != EINTR) {
<a name="l00219"></a>00219 <span class="keywordflow">break</span>;
<a name="l00220"></a>00220 }
<a name="l00221"></a>00221 }
<a name="l00222"></a>00222
<a name="l00223"></a>00223 <span class="keywordflow">if</span> (rc >= 0) {
<a name="l00224"></a>00224 <span class="keywordtype">char</span> *str = netsnmp_udp_fmtaddr(NULL, addr_pair, <span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>));
<a name="l00225"></a>00225 DEBUGMSGTL((<span class="stringliteral">"netsnmp_udp"</span>,
<a name="l00226"></a>00226 <span class="stringliteral">"recvfrom fd %d got %d bytes (from %s)\n"</span>,
<a name="l00227"></a>00227 t->sock, rc, str));
<a name="l00228"></a>00228 free(str);
<a name="l00229"></a>00229 } <span class="keywordflow">else</span> {
<a name="l00230"></a>00230 DEBUGMSGTL((<span class="stringliteral">"netsnmp_udp"</span>, <span class="stringliteral">"recvfrom fd %d err %d (\"%s\")\n"</span>,
<a name="l00231"></a>00231 t->sock, errno, strerror(errno)));
<a name="l00232"></a>00232 }
<a name="l00233"></a>00233 *opaque = (<span class="keywordtype">void</span> *)addr_pair;
<a name="l00234"></a>00234 *olength = <span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>);
<a name="l00235"></a>00235 }
<a name="l00236"></a>00236 <span class="keywordflow">return</span> rc;
<a name="l00237"></a>00237 }
<a name="l00238"></a>00238
<a name="l00239"></a>00239
<a name="l00240"></a>00240
<a name="l00241"></a>00241 <span class="keyword">static</span> <span class="keywordtype">int</span>
<a name="l00242"></a>00242 netsnmp_udp_send(<a class="code" href="structnetsnmp__transport__s.html">netsnmp_transport</a> *t, <span class="keywordtype">void</span> *buf, <span class="keywordtype">int</span> size,
<a name="l00243"></a>00243 <span class="keywordtype">void</span> **opaque, <span class="keywordtype">int</span> *olength)
<a name="l00244"></a>00244 {
<a name="l00245"></a>00245 <span class="keywordtype">int</span> rc = -1;
<a name="l00246"></a>00246 <a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a> *addr_pair = NULL;
<a name="l00247"></a>00247 <span class="keyword">struct </span>sockaddr *to = NULL;
<a name="l00248"></a>00248
<a name="l00249"></a>00249 <span class="keywordflow">if</span> (opaque != NULL && *opaque != NULL &&
<a name="l00250"></a>00250 *olength == <span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>)) {
<a name="l00251"></a>00251 addr_pair = (<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a> *) (*opaque);
<a name="l00252"></a>00252 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (t != NULL && t->data != NULL &&
<a name="l00253"></a>00253 t->data_length == <span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>)) {
<a name="l00254"></a>00254 addr_pair = (<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a> *) (t->data);
<a name="l00255"></a>00255 }
<a name="l00256"></a>00256
<a name="l00257"></a>00257 to = (<span class="keyword">struct </span>sockaddr *) &(addr_pair->remote_addr);
<a name="l00258"></a>00258
<a name="l00259"></a>00259 <span class="keywordflow">if</span> (to != NULL && t != NULL && t->sock >= 0) {
<a name="l00260"></a>00260 <span class="keywordtype">char</span> *str = netsnmp_udp_fmtaddr(NULL, (<span class="keywordtype">void</span> *) addr_pair,
<a name="l00261"></a>00261 <span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>));
<a name="l00262"></a>00262 DEBUGMSGTL((<span class="stringliteral">"netsnmp_udp"</span>, <span class="stringliteral">"send %d bytes from %p to %s on fd %d\n"</span>,
<a name="l00263"></a>00263 size, buf, str, t->sock));
<a name="l00264"></a>00264 free(str);
<a name="l00265"></a>00265 <span class="keywordflow">while</span> (rc < 0) {
<a name="l00266"></a>00266 <span class="preprocessor">#if defined(linux) && defined(IP_PKTINFO)</span>
<a name="l00267"></a>00267 <span class="preprocessor"></span> rc = netsnmp_udp_sendto(t->sock, addr_pair ? &(addr_pair->local_addr) : NULL, to, buf, size);
<a name="l00268"></a>00268 <span class="preprocessor">#else</span>
<a name="l00269"></a>00269 <span class="preprocessor"></span> rc = sendto(t->sock, buf, size, 0, to, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr));
<a name="l00270"></a>00270 <span class="preprocessor">#endif </span><span class="comment">/* linux && IP_PKTINFO */</span>
<a name="l00271"></a>00271 <span class="keywordflow">if</span> (rc < 0 && errno != EINTR) {
<a name="l00272"></a>00272 DEBUGMSGTL((<span class="stringliteral">"netsnmp_udp"</span>, <span class="stringliteral">"sendto error, rc %d (errno %d)\n"</span>,
<a name="l00273"></a>00273 rc, errno));
<a name="l00274"></a>00274 <span class="keywordflow">break</span>;
<a name="l00275"></a>00275 }
<a name="l00276"></a>00276 }
<a name="l00277"></a>00277 }
<a name="l00278"></a>00278 <span class="keywordflow">return</span> rc;
<a name="l00279"></a>00279 }
<a name="l00280"></a>00280
<a name="l00281"></a>00281
<a name="l00282"></a>00282
<a name="l00283"></a>00283 <span class="keyword">static</span> <span class="keywordtype">int</span>
<a name="l00284"></a>00284 netsnmp_udp_close(<a class="code" href="structnetsnmp__transport__s.html">netsnmp_transport</a> *t)
<a name="l00285"></a>00285 {
<a name="l00286"></a>00286 <span class="keywordtype">int</span> rc = -1;
<a name="l00287"></a>00287 <span class="keywordflow">if</span> (t->sock >= 0) {
<a name="l00288"></a>00288 <span class="preprocessor">#ifndef HAVE_CLOSESOCKET</span>
<a name="l00289"></a>00289 <span class="preprocessor"></span> rc = close(t->sock);
<a name="l00290"></a>00290 <span class="preprocessor">#else</span>
<a name="l00291"></a>00291 <span class="preprocessor"></span> rc = closesocket(t->sock);
<a name="l00292"></a>00292 <span class="preprocessor">#endif</span>
<a name="l00293"></a>00293 <span class="preprocessor"></span> t->sock = -1;
<a name="l00294"></a>00294 }
<a name="l00295"></a>00295 <span class="keywordflow">return</span> rc;
<a name="l00296"></a>00296 }
<a name="l00297"></a>00297
<a name="l00298"></a>00298 <span class="comment">/*</span>
<a name="l00299"></a>00299 <span class="comment"> * find largest possible buffer between current size and specified size.</span>
<a name="l00300"></a>00300 <span class="comment"> *</span>
<a name="l00301"></a>00301 <span class="comment"> * Try to maximize the current buffer of type "optname"</span>
<a name="l00302"></a>00302 <span class="comment"> * to the maximum allowable size by the OS (as close to</span>
<a name="l00303"></a>00303 <span class="comment"> * size as possible)</span>
<a name="l00304"></a>00304 <span class="comment"> */</span>
<a name="l00305"></a>00305 <span class="keyword">static</span> <span class="keywordtype">int</span>
<a name="l00306"></a>00306 _sock_buffer_maximize(<span class="keywordtype">int</span> s, <span class="keywordtype">int</span> optname, <span class="keyword">const</span> <span class="keywordtype">char</span> *buftype, <span class="keywordtype">int</span> size)
<a name="l00307"></a>00307 {
<a name="l00308"></a>00308 <span class="keywordtype">int</span> curbuf = 0;
<a name="l00309"></a>00309 <span class="keywordtype">size_t</span> curbuflen = <span class="keyword">sizeof</span>(int);
<a name="l00310"></a>00310 <span class="keywordtype">int</span> lo, mid, hi;
<a name="l00311"></a>00311
<a name="l00312"></a>00312 <span class="comment">/*</span>
<a name="l00313"></a>00313 <span class="comment"> * First we need to determine our current buffer</span>
<a name="l00314"></a>00314 <span class="comment"> */</span>
<a name="l00315"></a>00315 <span class="keywordflow">if</span> ((getsockopt(s, SOL_SOCKET, optname, (<span class="keywordtype">void</span> *) &curbuf,
<a name="l00316"></a>00316 &curbuflen) == 0)
<a name="l00317"></a>00317 && (curbuflen == <span class="keyword">sizeof</span>(int))) {
<a name="l00318"></a>00318
<a name="l00319"></a>00319 DEBUGMSGTL((<span class="stringliteral">"verbose:socket:buffer:max"</span>, <span class="stringliteral">"Current %s is %d\n"</span>,
<a name="l00320"></a>00320 buftype, curbuf));
<a name="l00321"></a>00321
<a name="l00322"></a>00322 <span class="comment">/*</span>
<a name="l00323"></a>00323 <span class="comment"> * Let's not be stupid ... if we were asked for less than what we</span>
<a name="l00324"></a>00324 <span class="comment"> * already have, then forget about it</span>
<a name="l00325"></a>00325 <span class="comment"> */</span>
<a name="l00326"></a>00326 <span class="keywordflow">if</span> (size <= curbuf) {
<a name="l00327"></a>00327 DEBUGMSGTL((<span class="stringliteral">"verbose:socket:buffer:max"</span>,
<a name="l00328"></a>00328 <span class="stringliteral">"Requested %s <= current buffer\n"</span>, buftype));
<a name="l00329"></a>00329 <span class="keywordflow">return</span> curbuf;
<a name="l00330"></a>00330 }
<a name="l00331"></a>00331
<a name="l00332"></a>00332 <span class="comment">/*</span>
<a name="l00333"></a>00333 <span class="comment"> * Do a binary search the optimal buffer within 1k of the point of</span>
<a name="l00334"></a>00334 <span class="comment"> * failure. This is rather bruteforce, but simple</span>
<a name="l00335"></a>00335 <span class="comment"> */</span>
<a name="l00336"></a>00336 hi = size;
<a name="l00337"></a>00337 lo = curbuf;
<a name="l00338"></a>00338
<a name="l00339"></a>00339 <span class="keywordflow">while</span> (hi - lo > 1024) {
<a name="l00340"></a>00340 mid = (lo + hi) / 2;
<a name="l00341"></a>00341 <span class="keywordflow">if</span> (setsockopt(s, SOL_SOCKET, optname, (<span class="keywordtype">void</span> *) &mid,
<a name="l00342"></a>00342 <span class="keyword">sizeof</span>(<span class="keywordtype">int</span>)) == 0) {
<a name="l00343"></a>00343 lo = mid; <span class="comment">/* Success: search between mid and hi */</span>
<a name="l00344"></a>00344 } <span class="keywordflow">else</span> {
<a name="l00345"></a>00345 hi = mid; <span class="comment">/* Failed: search between lo and mid */</span>
<a name="l00346"></a>00346 }
<a name="l00347"></a>00347 }
<a name="l00348"></a>00348
<a name="l00349"></a>00349 <span class="comment">/*</span>
<a name="l00350"></a>00350 <span class="comment"> * Now print if this optimization helped or not</span>
<a name="l00351"></a>00351 <span class="comment"> */</span>
<a name="l00352"></a>00352 <span class="keywordflow">if</span> (getsockopt(s,SOL_SOCKET, optname, (<span class="keywordtype">void</span> *) &curbuf,
<a name="l00353"></a>00353 &curbuflen) == 0) {
<a name="l00354"></a>00354 DEBUGMSGTL((<span class="stringliteral">"socket:buffer:max"</span>,
<a name="l00355"></a>00355 <span class="stringliteral">"Maximized %s: %d\n"</span>,buftype, curbuf));
<a name="l00356"></a>00356 }
<a name="l00357"></a>00357 } <span class="keywordflow">else</span> {
<a name="l00358"></a>00358 <span class="comment">/*</span>
<a name="l00359"></a>00359 <span class="comment"> * There is really not a lot we can do anymore.</span>
<a name="l00360"></a>00360 <span class="comment"> * If the OS doesn't give us the current buffer, then what's the </span>
<a name="l00361"></a>00361 <span class="comment"> * point in trying to make it better</span>
<a name="l00362"></a>00362 <span class="comment"> */</span>
<a name="l00363"></a>00363 DEBUGMSGTL((<span class="stringliteral">"socket:buffer:max"</span>, <span class="stringliteral">"Get %s failed ... giving up!\n"</span>,
<a name="l00364"></a>00364 buftype));
<a name="l00365"></a>00365 curbuf = -1;
<a name="l00366"></a>00366 }
<a name="l00367"></a>00367
<a name="l00368"></a>00368 <span class="keywordflow">return</span> curbuf;
<a name="l00369"></a>00369 }
<a name="l00370"></a>00370
<a name="l00371"></a>00371
<a name="l00372"></a>00372 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span> *
<a name="l00373"></a>00373 _sock_buf_type_get(<span class="keywordtype">int</span> optname, <span class="keywordtype">int</span> local)
<a name="l00374"></a>00374 {
<a name="l00375"></a>00375 <span class="keywordflow">if</span> (optname == SO_SNDBUF) {
<a name="l00376"></a>00376 <span class="keywordflow">if</span> (local)
<a name="l00377"></a>00377 <span class="keywordflow">return</span> <span class="stringliteral">"server send buffer"</span>;
<a name="l00378"></a>00378 <span class="keywordflow">else</span>
<a name="l00379"></a>00379 <span class="keywordflow">return</span> <span class="stringliteral">"client send buffer"</span>;
<a name="l00380"></a>00380 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (optname == SO_RCVBUF) {
<a name="l00381"></a>00381 <span class="keywordflow">if</span> (local)
<a name="l00382"></a>00382 <span class="keywordflow">return</span> <span class="stringliteral">"server receive buffer"</span>;
<a name="l00383"></a>00383 <span class="keywordflow">else</span>
<a name="l00384"></a>00384 <span class="keywordflow">return</span> <span class="stringliteral">"client receive buffer"</span>;
<a name="l00385"></a>00385 }
<a name="l00386"></a>00386
<a name="l00387"></a>00387 <span class="keywordflow">return</span> <span class="stringliteral">"unknown buffer"</span>;
<a name="l00388"></a>00388 }
<a name="l00389"></a>00389
<a name="l00390"></a>00390 <span class="comment">/*</span>
<a name="l00391"></a>00391 <span class="comment"> *</span>
<a name="l00392"></a>00392 <span class="comment"> * Get the requested buffersize, based on</span>
<a name="l00393"></a>00393 <span class="comment"> * - sockettype : client (local = 0) or server (local = 1) </span>
<a name="l00394"></a>00394 <span class="comment"> * - buffertype : send (optname = SO_SNDBUF) or recv (SO_RCVBUF)</span>
<a name="l00395"></a>00395 <span class="comment"> *</span>
<a name="l00396"></a>00396 <span class="comment"> * In case a compile time buffer was specified, then use that one</span>
<a name="l00397"></a>00397 <span class="comment"> * if there was no runtime configuration override</span>
<a name="l00398"></a>00398 <span class="comment"> */</span>
<a name="l00399"></a>00399 <span class="keyword">static</span> <span class="keywordtype">int</span>
<a name="l00400"></a>00400 _sock_buffer_size_get(<span class="keywordtype">int</span> optname, <span class="keywordtype">int</span> local, <span class="keyword">const</span> <span class="keywordtype">char</span> **buftype)
<a name="l00401"></a>00401 {
<a name="l00402"></a>00402 <span class="keywordtype">int</span> size;
<a name="l00403"></a>00403
<a name="l00404"></a>00404 <span class="keywordflow">if</span> (NULL != buftype)
<a name="l00405"></a>00405 *buftype = _sock_buf_type_get(optname, local);
<a name="l00406"></a>00406
<a name="l00407"></a>00407 <span class="keywordflow">if</span> (optname == SO_SNDBUF) {
<a name="l00408"></a>00408 <span class="keywordflow">if</span> (local) {
<a name="l00409"></a>00409 size = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
<a name="l00410"></a>00410 NETSNMP_DS_LIB_SERVERSENDBUF);
<a name="l00411"></a>00411 <span class="preprocessor">#ifdef NETSNMP_DEFAULT_SERVER_SEND_BUF</span>
<a name="l00412"></a>00412 <span class="preprocessor"></span> <span class="keywordflow">if</span> (size <= 0)
<a name="l00413"></a>00413 size = NETSNMP_DEFAULT_SERVER_SEND_BUF;
<a name="l00414"></a>00414 <span class="preprocessor">#endif</span>
<a name="l00415"></a>00415 <span class="preprocessor"></span> } <span class="keywordflow">else</span> {
<a name="l00416"></a>00416 size = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
<a name="l00417"></a>00417 NETSNMP_DS_LIB_CLIENTSENDBUF);
<a name="l00418"></a>00418 <span class="preprocessor">#ifdef NETSNMP_DEFAULT_CLIENT_SEND_BUF</span>
<a name="l00419"></a>00419 <span class="preprocessor"></span> <span class="keywordflow">if</span> (size <= 0)
<a name="l00420"></a>00420 size = NETSNMP_DEFAULT_CLIENT_SEND_BUF;
<a name="l00421"></a>00421 <span class="preprocessor">#endif</span>
<a name="l00422"></a>00422 <span class="preprocessor"></span> }
<a name="l00423"></a>00423 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (optname == SO_RCVBUF) {
<a name="l00424"></a>00424 <span class="keywordflow">if</span> (local) {
<a name="l00425"></a>00425 size = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
<a name="l00426"></a>00426 NETSNMP_DS_LIB_SERVERRECVBUF);
<a name="l00427"></a>00427 <span class="preprocessor">#ifdef NETSNMP_DEFAULT_SERVER_RECV_BUF</span>
<a name="l00428"></a>00428 <span class="preprocessor"></span> <span class="keywordflow">if</span> (size <= 0)
<a name="l00429"></a>00429 size = NETSNMP_DEFAULT_SERVER_RECV_BUF;
<a name="l00430"></a>00430 <span class="preprocessor">#endif</span>
<a name="l00431"></a>00431 <span class="preprocessor"></span> } <span class="keywordflow">else</span> {
<a name="l00432"></a>00432 size = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
<a name="l00433"></a>00433 NETSNMP_DS_LIB_CLIENTRECVBUF);
<a name="l00434"></a>00434 <span class="preprocessor">#ifdef NETSNMP_DEFAULT_CLIENT_RECV_BUF</span>
<a name="l00435"></a>00435 <span class="preprocessor"></span> <span class="keywordflow">if</span> (size <= 0)
<a name="l00436"></a>00436 size = NETSNMP_DEFAULT_CLIENT_RECV_BUF;
<a name="l00437"></a>00437 <span class="preprocessor">#endif</span>
<a name="l00438"></a>00438 <span class="preprocessor"></span> }
<a name="l00439"></a>00439 } <span class="keywordflow">else</span> {
<a name="l00440"></a>00440 size = 0;
<a name="l00441"></a>00441 }
<a name="l00442"></a>00442
<a name="l00443"></a>00443 DEBUGMSGTL((<span class="stringliteral">"socket:buffer"</span>, <span class="stringliteral">"Requested %s is %d\n"</span>,
<a name="l00444"></a>00444 (buftype) ? *buftype : <span class="stringliteral">"unknown buffer"</span>, size));
<a name="l00445"></a>00445
<a name="l00446"></a>00446 <span class="keywordflow">return</span>(size);
<a name="l00447"></a>00447 }
<a name="l00448"></a>00448
<a name="l00449"></a>00449 <span class="comment">/*</span>
<a name="l00450"></a>00450 <span class="comment"> * set socket buffer size</span>
<a name="l00451"></a>00451 <span class="comment"> *</span>
<a name="l00452"></a>00452 <span class="comment"> * @param ss : socket</span>
<a name="l00453"></a>00453 <span class="comment"> * @param optname: SO_SNDBUF or SO_RCVBUF</span>
<a name="l00454"></a>00454 <span class="comment"> * @param local : 1 for server, 0 for client</span>
<a name="l00455"></a>00455 <span class="comment"> * @param reqbuf : requested size, or 0 for default</span>
<a name="l00456"></a>00456 <span class="comment"> *</span>
<a name="l00457"></a>00457 <span class="comment"> * @retval -1 : error</span>
<a name="l00458"></a>00458 <span class="comment"> * @retval >0 : new buffer size</span>
<a name="l00459"></a>00459 <span class="comment"> */</span>
<a name="l00460"></a>00460 <span class="keywordtype">int</span>
<a name="l00461"></a>00461 netsnmp_sock_buffer_set(<span class="keywordtype">int</span> s, <span class="keywordtype">int</span> optname, <span class="keywordtype">int</span> local, <span class="keywordtype">int</span> size)
<a name="l00462"></a>00462 {
<a name="l00463"></a>00463 <span class="preprocessor">#if ! defined(SO_SNDBUF) && ! defined(SO_RCVBUF)</span>
<a name="l00464"></a>00464 <span class="preprocessor"></span> DEBUGMSGTL((<span class="stringliteral">"socket:buffer"</span>, <span class="stringliteral">"Changing socket buffer is not supported\n"</span>));
<a name="l00465"></a>00465 <span class="keywordflow">return</span> -1;
<a name="l00466"></a>00466 <span class="preprocessor">#else</span>
<a name="l00467"></a>00467 <span class="preprocessor"></span> <span class="keyword">const</span> <span class="keywordtype">char</span> *buftype;
<a name="l00468"></a>00468 <span class="keywordtype">int</span> curbuf = 0;
<a name="l00469"></a>00469 <span class="keywordtype">size_t</span> curbuflen = <span class="keyword">sizeof</span>(int);
<a name="l00470"></a>00470
<a name="l00471"></a>00471 <span class="preprocessor"># ifndef SO_SNDBUF</span>
<a name="l00472"></a>00472 <span class="preprocessor"></span> <span class="keywordflow">if</span> (SO_SNDBUF == optname) {
<a name="l00473"></a>00473 DEBUGMSGTL((<span class="stringliteral">"socket:buffer"</span>,
<a name="l00474"></a>00474 <span class="stringliteral">"Changing socket send buffer is not supported\n"</span>));
<a name="l00475"></a>00475 <span class="keywordflow">return</span> -1;
<a name="l00476"></a>00476 }
<a name="l00477"></a>00477 <span class="preprocessor"># endif </span><span class="comment">/*SO_SNDBUF */</span>
<a name="l00478"></a>00478 <span class="preprocessor"># ifndef SO_RCVBUF</span>
<a name="l00479"></a>00479 <span class="preprocessor"></span> <span class="keywordflow">if</span> (SO_RCVBUF == optname) {
<a name="l00480"></a>00480 DEBUGMSGTL((<span class="stringliteral">"socket:buffer"</span>,
<a name="l00481"></a>00481 <span class="stringliteral">"Changing socket receive buffer is not supported\n"</span>));
<a name="l00482"></a>00482 <span class="keywordflow">return</span> -1;
<a name="l00483"></a>00483 }
<a name="l00484"></a>00484 <span class="preprocessor"># endif </span><span class="comment">/*SO_RCVBUF */</span>
<a name="l00485"></a>00485
<a name="l00486"></a>00486 <span class="comment">/*</span>
<a name="l00487"></a>00487 <span class="comment"> * What is the requested buffer size ?</span>
<a name="l00488"></a>00488 <span class="comment"> */</span>
<a name="l00489"></a>00489 <span class="keywordflow">if</span> (0 == size)
<a name="l00490"></a>00490 size = _sock_buffer_size_get(optname, local, &buftype);
<a name="l00491"></a>00491 <span class="keywordflow">else</span> {
<a name="l00492"></a>00492 buftype = _sock_buf_type_get(optname, local);
<a name="l00493"></a>00493 DEBUGMSGT((<span class="stringliteral">"verbose:socket:buffer"</span>, <span class="stringliteral">"Requested %s is %d\n"</span>,
<a name="l00494"></a>00494 buftype, size));
<a name="l00495"></a>00495 }
<a name="l00496"></a>00496
<a name="l00497"></a>00497 <span class="keywordflow">if</span> ((getsockopt(s, SOL_SOCKET, optname, (<span class="keywordtype">void</span> *) &curbuf,
<a name="l00498"></a>00498 &curbuflen) == 0)
<a name="l00499"></a>00499 && (curbuflen == <span class="keyword">sizeof</span>(<span class="keywordtype">int</span>))) {
<a name="l00500"></a>00500
<a name="l00501"></a>00501 DEBUGMSGT((<span class="stringliteral">"verbose:socket:buffer"</span>, <span class="stringliteral">"Original %s is %d\n"</span>,
<a name="l00502"></a>00502 buftype, curbuf));
<a name="l00503"></a>00503 <span class="keywordflow">if</span> (curbuf >= size) {
<a name="l00504"></a>00504 DEBUGMSGT((<span class="stringliteral">"verbose:socket:buffer"</span>,
<a name="l00505"></a>00505 <span class="stringliteral">"New %s size is smaller than original!\n"</span>, buftype));
<a name="l00506"></a>00506 }
<a name="l00507"></a>00507 }
<a name="l00508"></a>00508
<a name="l00509"></a>00509 <span class="comment">/*</span>
<a name="l00510"></a>00510 <span class="comment"> * If the buffersize was not specified or it was a negative value</span>
<a name="l00511"></a>00511 <span class="comment"> * then don't change the OS buffers at all</span>
<a name="l00512"></a>00512 <span class="comment"> */</span>
<a name="l00513"></a>00513 <span class="keywordflow">if</span> (size <= 0) {
<a name="l00514"></a>00514 DEBUGMSGT((<span class="stringliteral">"socket:buffer"</span>,
<a name="l00515"></a>00515 <span class="stringliteral">"%s not valid or not specified; using OS default(%d)\n"</span>,
<a name="l00516"></a>00516 buftype,curbuf));
<a name="l00517"></a>00517 <span class="keywordflow">return</span> curbuf;
<a name="l00518"></a>00518 }
<a name="l00519"></a>00519
<a name="l00520"></a>00520 <span class="comment">/*</span>
<a name="l00521"></a>00521 <span class="comment"> * Try to set the requested send buffer</span>
<a name="l00522"></a>00522 <span class="comment"> */</span>
<a name="l00523"></a>00523 <span class="keywordflow">if</span> (setsockopt(s, SOL_SOCKET, optname, (<span class="keywordtype">void</span> *) &size, <span class="keyword">sizeof</span>(<span class="keywordtype">int</span>)) == 0) {
<a name="l00524"></a>00524 <span class="comment">/*</span>
<a name="l00525"></a>00525 <span class="comment"> * Because some platforms lie about the actual buffer that has been </span>
<a name="l00526"></a>00526 <span class="comment"> * set (Linux will always say it worked ...), we print some </span>
<a name="l00527"></a>00527 <span class="comment"> * diagnostic output for debugging</span>
<a name="l00528"></a>00528 <span class="comment"> */</span>
<a name="l00529"></a>00529 DEBUGIF(<span class="stringliteral">"socket:buffer"</span>) {
<a name="l00530"></a>00530 DEBUGMSGT((<span class="stringliteral">"socket:buffer"</span>, <span class="stringliteral">"Set %s to %d\n"</span>,
<a name="l00531"></a>00531 buftype, size));
<a name="l00532"></a>00532 <span class="keywordflow">if</span> ((getsockopt(s, SOL_SOCKET, optname, (<span class="keywordtype">void</span> *) &curbuf,
<a name="l00533"></a>00533 &curbuflen) == 0)
<a name="l00534"></a>00534 && (curbuflen == <span class="keyword">sizeof</span>(<span class="keywordtype">int</span>))) {
<a name="l00535"></a>00535
<a name="l00536"></a>00536 DEBUGMSGT((<span class="stringliteral">"verbose:socket:buffer"</span>,
<a name="l00537"></a>00537 <span class="stringliteral">"Now %s is %d\n"</span>, buftype, curbuf));
<a name="l00538"></a>00538 }
<a name="l00539"></a>00539 }
<a name="l00540"></a>00540 <span class="comment">/*</span>
<a name="l00541"></a>00541 <span class="comment"> * If the new buffer is smaller than the size we requested, we will</span>
<a name="l00542"></a>00542 <span class="comment"> * try to increment the new buffer with 1k increments </span>
<a name="l00543"></a>00543 <span class="comment"> * (this will sometime allow us to reach a more optimal buffer.)</span>
<a name="l00544"></a>00544 <span class="comment"> * For example : On Solaris, if the max OS buffer is 100k and you</span>
<a name="l00545"></a>00545 <span class="comment"> * request 110k, you end up with the default 8k :-(</span>
<a name="l00546"></a>00546 <span class="comment"> */</span>
<a name="l00547"></a>00547 <span class="keywordflow">if</span> (curbuf < size) {
<a name="l00548"></a>00548 curbuf = _sock_buffer_maximize(s, optname, buftype, size);
<a name="l00549"></a>00549 <span class="keywordflow">if</span>(-1 != curbuf)
<a name="l00550"></a>00550 size = curbuf;
<a name="l00551"></a>00551 }
<a name="l00552"></a>00552
<a name="l00553"></a>00553 } <span class="keywordflow">else</span> {
<a name="l00554"></a>00554 <span class="comment">/*</span>
<a name="l00555"></a>00555 <span class="comment"> * Obviously changing the buffer failed, most like like because we </span>
<a name="l00556"></a>00556 <span class="comment"> * requested a buffer greater than the OS limit.</span>
<a name="l00557"></a>00557 <span class="comment"> * Therefore we need to search for an optimal buffer that is close</span>
<a name="l00558"></a>00558 <span class="comment"> * enough to the point of failure.</span>
<a name="l00559"></a>00559 <span class="comment"> * This will allow us to reach a more optimal buffer.</span>
<a name="l00560"></a>00560 <span class="comment"> * For example : On Solaris, if the max OS buffer is 100k and you </span>
<a name="l00561"></a>00561 <span class="comment"> * request 110k, you end up with the default 8k :-(</span>
<a name="l00562"></a>00562 <span class="comment"> * After this quick seach we would get 1k close to 100k (the max)</span>
<a name="l00563"></a>00563 <span class="comment"> */</span>
<a name="l00564"></a>00564 DEBUGMSGTL((<span class="stringliteral">"socket:buffer"</span>, <span class="stringliteral">"couldn't set %s to %d\n"</span>,
<a name="l00565"></a>00565 buftype, size));
<a name="l00566"></a>00566
<a name="l00567"></a>00567 curbuf = _sock_buffer_maximize(s, optname, buftype, size);
<a name="l00568"></a>00568 <span class="keywordflow">if</span>(-1 != curbuf)
<a name="l00569"></a>00569 size = curbuf;
<a name="l00570"></a>00570 }
<a name="l00571"></a>00571
<a name="l00572"></a>00572 <span class="keywordflow">return</span> size;
<a name="l00573"></a>00573 <span class="preprocessor">#endif</span>
<a name="l00574"></a>00574 <span class="preprocessor"></span>}
<a name="l00575"></a>00575
<a name="l00576"></a>00576 <span class="comment">/*</span>
<a name="l00577"></a>00577 <span class="comment"> * Open a UDP-based transport for SNMP. Local is TRUE if addr is the local</span>
<a name="l00578"></a>00578 <span class="comment"> * address to bind to (i.e. this is a server-type session); otherwise addr is </span>
<a name="l00579"></a>00579 <span class="comment"> * the remote address to send things to. </span>
<a name="l00580"></a>00580 <span class="comment"> */</span>
<a name="l00581"></a>00581
<a name="l00582"></a>00582 <a class="code" href="structnetsnmp__transport__s.html">netsnmp_transport</a> *
<a name="l00583"></a>00583 netsnmp_udp_transport(<span class="keyword">struct</span> sockaddr_in *addr, <span class="keywordtype">int</span> local)
<a name="l00584"></a>00584 {
<a name="l00585"></a>00585 <a class="code" href="structnetsnmp__transport__s.html">netsnmp_transport</a> *t = NULL;
<a name="l00586"></a>00586 <span class="keywordtype">int</span> rc = 0;
<a name="l00587"></a>00587 <span class="keywordtype">char</span> *str = NULL;
<a name="l00588"></a>00588 <span class="keywordtype">char</span> *client_socket = NULL;
<a name="l00589"></a>00589 <a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a> addr_pair;
<a name="l00590"></a>00590
<a name="l00591"></a>00591 <span class="keywordflow">if</span> (addr == NULL || addr->sin_family != AF_INET) {
<a name="l00592"></a>00592 <span class="keywordflow">return</span> NULL;
<a name="l00593"></a>00593 }
<a name="l00594"></a>00594
<a name="l00595"></a>00595 memset(&addr_pair, 0, <span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>));
<a name="l00596"></a>00596 memcpy(&(addr_pair.remote_addr), addr, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr_in));
<a name="l00597"></a>00597
<a name="l00598"></a>00598 t = (<a class="code" href="structnetsnmp__transport__s.html">netsnmp_transport</a> *) malloc(<span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__transport__s.html">netsnmp_transport</a>));
<a name="l00599"></a>00599 <span class="keywordflow">if</span> (t == NULL) {
<a name="l00600"></a>00600 <span class="keywordflow">return</span> NULL;
<a name="l00601"></a>00601 }
<a name="l00602"></a>00602
<a name="l00603"></a>00603 str = netsnmp_udp_fmtaddr(NULL, (<span class="keywordtype">void</span> *)&addr_pair,
<a name="l00604"></a>00604 <span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>));
<a name="l00605"></a>00605 DEBUGMSGTL((<span class="stringliteral">"netsnmp_udp"</span>, <span class="stringliteral">"open %s %s\n"</span>, local ? <span class="stringliteral">"local"</span> : <span class="stringliteral">"remote"</span>,
<a name="l00606"></a>00606 str));
<a name="l00607"></a>00607 free(str);
<a name="l00608"></a>00608
<a name="l00609"></a>00609 memset(t, 0, <span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__transport__s.html">netsnmp_transport</a>));
<a name="l00610"></a>00610
<a name="l00611"></a>00611 t->domain = netsnmpUDPDomain;
<a name="l00612"></a>00612 t->domain_length = netsnmpUDPDomain_len;
<a name="l00613"></a>00613
<a name="l00614"></a>00614 t->sock = socket(PF_INET, SOCK_DGRAM, 0);
<a name="l00615"></a>00615 <span class="keywordflow">if</span> (t->sock < 0) {
<a name="l00616"></a>00616 netsnmp_transport_free(t);
<a name="l00617"></a>00617 <span class="keywordflow">return</span> NULL;
<a name="l00618"></a>00618 }
<a name="l00619"></a>00619
<a name="l00620"></a>00620 _netsnmp_udp_sockopt_set(t->sock, local);
<a name="l00621"></a>00621
<a name="l00622"></a>00622 <span class="keywordflow">if</span> (local) {
<a name="l00623"></a>00623 <span class="comment">/*</span>
<a name="l00624"></a>00624 <span class="comment"> * This session is inteneded as a server, so we must bind on to the</span>
<a name="l00625"></a>00625 <span class="comment"> * given IP address, which may include an interface address, or could</span>
<a name="l00626"></a>00626 <span class="comment"> * be INADDR_ANY, but certainly includes a port number.</span>
<a name="l00627"></a>00627 <span class="comment"> */</span>
<a name="l00628"></a>00628
<a name="l00629"></a>00629 t->local = (u_char *) malloc(6);
<a name="l00630"></a>00630 <span class="keywordflow">if</span> (t->local == NULL) {
<a name="l00631"></a>00631 netsnmp_transport_free(t);
<a name="l00632"></a>00632 <span class="keywordflow">return</span> NULL;
<a name="l00633"></a>00633 }
<a name="l00634"></a>00634 memcpy(t->local, (u_char *) & (addr->sin_addr.s_addr), 4);
<a name="l00635"></a>00635 t->local[4] = (htons(addr->sin_port) & 0xff00) >> 8;
<a name="l00636"></a>00636 t->local[5] = (htons(addr->sin_port) & 0x00ff) >> 0;
<a name="l00637"></a>00637 t->local_length = 6;
<a name="l00638"></a>00638
<a name="l00639"></a>00639 <span class="preprocessor">#if defined(linux) && defined(IP_PKTINFO)</span>
<a name="l00640"></a>00640 <span class="preprocessor"></span> {
<a name="l00641"></a>00641 <span class="keywordtype">int</span> sockopt = 1;
<a name="l00642"></a>00642 <span class="keywordflow">if</span> (setsockopt(t->sock, SOL_IP, IP_PKTINFO, &sockopt, <span class="keyword">sizeof</span> sockopt) == -1) {
<a name="l00643"></a>00643 DEBUGMSGTL((<span class="stringliteral">"netsnmp_udp"</span>, <span class="stringliteral">"couldn't set IP_PKTINFO: %s\n"</span>,
<a name="l00644"></a>00644 strerror(errno)));
<a name="l00645"></a>00645 <span class="keywordflow">return</span> NULL;
<a name="l00646"></a>00646 }
<a name="l00647"></a>00647 DEBUGMSGTL((<span class="stringliteral">"netsnmp_udp"</span>, <span class="stringliteral">"set IP_PKTINFO\n"</span>));
<a name="l00648"></a>00648 }
<a name="l00649"></a>00649 <span class="preprocessor">#endif</span>
<a name="l00650"></a>00650 <span class="preprocessor"></span> rc = bind(t->sock, (<span class="keyword">struct</span> sockaddr *) addr,
<a name="l00651"></a>00651 <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr));
<a name="l00652"></a>00652 <span class="keywordflow">if</span> (rc != 0) {
<a name="l00653"></a>00653 netsnmp_udp_close(t);
<a name="l00654"></a>00654 netsnmp_transport_free(t);
<a name="l00655"></a>00655 <span class="keywordflow">return</span> NULL;
<a name="l00656"></a>00656 }
<a name="l00657"></a>00657 t->data = NULL;
<a name="l00658"></a>00658 t->data_length = 0;
<a name="l00659"></a>00659 } <span class="keywordflow">else</span> {
<a name="l00660"></a>00660 <span class="comment">/*</span>
<a name="l00661"></a>00661 <span class="comment"> * This is a client session. If we've been given a</span>
<a name="l00662"></a>00662 <span class="comment"> * client address to send from, then bind to that.</span>
<a name="l00663"></a>00663 <span class="comment"> * Otherwise the send will use "something sensible".</span>
<a name="l00664"></a>00664 <span class="comment"> */</span>
<a name="l00665"></a>00665 client_socket = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
<a name="l00666"></a>00666 NETSNMP_DS_LIB_CLIENT_ADDR);
<a name="l00667"></a>00667 <span class="keywordflow">if</span> (client_socket) {
<a name="l00668"></a>00668 <span class="keyword">struct </span>sockaddr_in client_addr;
<a name="l00669"></a>00669 netsnmp_sockaddr_in2(&client_addr, client_socket, NULL);
<a name="l00670"></a>00670 client_addr.sin_port = 0;
<a name="l00671"></a>00671 bind(t->sock, (<span class="keyword">struct</span> sockaddr *)&client_addr,
<a name="l00672"></a>00672 <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr));
<a name="l00673"></a>00673 }
<a name="l00674"></a>00674 <span class="comment">/*</span>
<a name="l00675"></a>00675 <span class="comment"> * Save the (remote) address in the</span>
<a name="l00676"></a>00676 <span class="comment"> * transport-specific data pointer for later use by netsnmp_udp_send.</span>
<a name="l00677"></a>00677 <span class="comment"> */</span>
<a name="l00678"></a>00678
<a name="l00679"></a>00679 t->data = malloc(<span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>));
<a name="l00680"></a>00680 t->remote = (u_char *)malloc(6);
<a name="l00681"></a>00681 <span class="keywordflow">if</span> (t->data == NULL || t->remote == NULL) {
<a name="l00682"></a>00682 netsnmp_transport_free(t);
<a name="l00683"></a>00683 <span class="keywordflow">return</span> NULL;
<a name="l00684"></a>00684 }
<a name="l00685"></a>00685 memcpy(t->remote, (u_char *) & (addr->sin_addr.s_addr), 4);
<a name="l00686"></a>00686 t->remote[4] = (htons(addr->sin_port) & 0xff00) >> 8;
<a name="l00687"></a>00687 t->remote[5] = (htons(addr->sin_port) & 0x00ff) >> 0;
<a name="l00688"></a>00688 t->remote_length = 6;
<a name="l00689"></a>00689 memcpy(t->data, &addr_pair, <span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>));
<a name="l00690"></a>00690 t->data_length = <span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>);
<a name="l00691"></a>00691 }
<a name="l00692"></a>00692
<a name="l00693"></a>00693 <span class="comment">/*</span>
<a name="l00694"></a>00694 <span class="comment"> * 16-bit length field, 8 byte UDP header, 20 byte IPv4 header </span>
<a name="l00695"></a>00695 <span class="comment"> */</span>
<a name="l00696"></a>00696
<a name="l00697"></a>00697 t->msgMaxSize = 0xffff - 8 - 20;
<a name="l00698"></a>00698 t->f_recv = netsnmp_udp_recv;
<a name="l00699"></a>00699 t->f_send = netsnmp_udp_send;
<a name="l00700"></a>00700 t->f_close = netsnmp_udp_close;
<a name="l00701"></a>00701 t->f_accept = NULL;
<a name="l00702"></a>00702 t->f_fmtaddr = netsnmp_udp_fmtaddr;
<a name="l00703"></a>00703
<a name="l00704"></a>00704 <span class="keywordflow">return</span> t;
<a name="l00705"></a>00705 }
<a name="l00706"></a>00706
<a name="l00707"></a>00707
<a name="l00708"></a>00708 <span class="keywordtype">void</span>
<a name="l00709"></a>00709 _netsnmp_udp_sockopt_set(<span class="keywordtype">int</span> fd, <span class="keywordtype">int</span> local)
<a name="l00710"></a>00710 {
<a name="l00711"></a>00711 <span class="preprocessor">#ifdef SO_BSDCOMPAT</span>
<a name="l00712"></a>00712 <span class="preprocessor"></span> <span class="comment">/*</span>
<a name="l00713"></a>00713 <span class="comment"> * Patch for Linux. Without this, UDP packets that fail get an ICMP</span>
<a name="l00714"></a>00714 <span class="comment"> * response. Linux turns the failed ICMP response into an error message</span>
<a name="l00715"></a>00715 <span class="comment"> * and return value, unlike all other OS's. </span>
<a name="l00716"></a>00716 <span class="comment"> */</span>
<a name="l00717"></a>00717 <span class="keywordflow">if</span> (0 == netsnmp_os_prematch(<span class="stringliteral">"Linux"</span>,<span class="stringliteral">"2.4"</span>))
<a name="l00718"></a>00718 {
<a name="l00719"></a>00719 <span class="keywordtype">int</span> one = 1;
<a name="l00720"></a>00720 DEBUGMSGTL((<span class="stringliteral">"socket:option"</span>, <span class="stringliteral">"setting socket option SO_BSDCOMPAT\n"</span>));
<a name="l00721"></a>00721 setsockopt(fd, SOL_SOCKET, SO_BSDCOMPAT, (<span class="keywordtype">void</span> *) &one,
<a name="l00722"></a>00722 <span class="keyword">sizeof</span>(one));
<a name="l00723"></a>00723 }
<a name="l00724"></a>00724 <span class="preprocessor">#endif </span><span class="comment">/*SO_BSDCOMPAT */</span>
<a name="l00725"></a>00725 <span class="comment">/*</span>
<a name="l00726"></a>00726 <span class="comment"> * SO_REUSEADDR will allow multiple apps to open the same port at</span>
<a name="l00727"></a>00727 <span class="comment"> * the same time. Only the last one to open the socket will get</span>
<a name="l00728"></a>00728 <span class="comment"> * data. Obviously, for an agent, this is a bad thing. There should</span>
<a name="l00729"></a>00729 <span class="comment"> * only be one listener.</span>
<a name="l00730"></a>00730 <span class="comment"> */</span>
<a name="l00731"></a>00731 <span class="preprocessor">#ifdef ALLOW_PORT_HIJACKING</span>
<a name="l00732"></a>00732 <span class="preprocessor"></span><span class="preprocessor">#ifdef SO_REUSEADDR</span>
<a name="l00733"></a>00733 <span class="preprocessor"></span> <span class="comment">/*</span>
<a name="l00734"></a>00734 <span class="comment"> * Allow the same port to be specified multiple times without failing.</span>
<a name="l00735"></a>00735 <span class="comment"> * (useful for a listener)</span>
<a name="l00736"></a>00736 <span class="comment"> */</span>
<a name="l00737"></a>00737 {
<a name="l00738"></a>00738 <span class="keywordtype">int</span> one = 1;
<a name="l00739"></a>00739 DEBUGMSGTL((<span class="stringliteral">"socket:option"</span>, <span class="stringliteral">"setting socket option SO_REUSEADDR\n"</span>));
<a name="l00740"></a>00740 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (<span class="keywordtype">void</span> *) &one,
<a name="l00741"></a>00741 <span class="keyword">sizeof</span>(one));
<a name="l00742"></a>00742 }
<a name="l00743"></a>00743 <span class="preprocessor">#endif </span><span class="comment">/*SO_REUSEADDR */</span>
<a name="l00744"></a>00744 <span class="preprocessor">#endif</span>
<a name="l00745"></a>00745 <span class="preprocessor"></span>
<a name="l00746"></a>00746 <span class="comment">/*</span>
<a name="l00747"></a>00747 <span class="comment"> * Try to set the send and receive buffers to a reasonably large value, so</span>
<a name="l00748"></a>00748 <span class="comment"> * that we can send and receive big PDUs (defaults to 8192 bytes (!) on</span>
<a name="l00749"></a>00749 <span class="comment"> * Solaris, for instance). Don't worry too much about errors -- just</span>
<a name="l00750"></a>00750 <span class="comment"> * plough on regardless. </span>
<a name="l00751"></a>00751 <span class="comment"> */</span>
<a name="l00752"></a>00752 netsnmp_sock_buffer_set(fd, SO_SNDBUF, local, 0);
<a name="l00753"></a>00753 netsnmp_sock_buffer_set(fd, SO_RCVBUF, local, 0);
<a name="l00754"></a>00754 }
<a name="l00755"></a>00755
<a name="l00756"></a>00756 <span class="keywordtype">int</span>
<a name="l00757"></a>00757 netsnmp_sockaddr_in2(<span class="keyword">struct</span> sockaddr_in *addr,
<a name="l00758"></a>00758 <span class="keyword">const</span> <span class="keywordtype">char</span> *inpeername, <span class="keyword">const</span> <span class="keywordtype">char</span> *default_target)
<a name="l00759"></a>00759 {
<a name="l00760"></a>00760 <span class="preprocessor">#if HAVE_GETADDRINFO</span>
<a name="l00761"></a>00761 <span class="preprocessor"></span> <span class="keyword">struct </span>addrinfo *addrs = NULL;
<a name="l00762"></a>00762 <span class="keyword">struct </span>addrinfo hint;
<a name="l00763"></a>00763 <span class="keywordtype">int</span> err;
<a name="l00764"></a>00764 <span class="preprocessor">#elif HAVE_GETIPNODEBYNAME</span>
<a name="l00765"></a>00765 <span class="preprocessor"></span> <span class="keyword">struct </span>hostent *hp = NULL;
<a name="l00766"></a>00766 <span class="keywordtype">int</span> err;
<a name="l00767"></a>00767 <span class="preprocessor">#elif HAVE_GETHOSTBYNAME</span>
<a name="l00768"></a>00768 <span class="preprocessor"></span> <span class="keyword">struct </span>hostent *hp = NULL;
<a name="l00769"></a>00769 <span class="preprocessor">#endif</span>
<a name="l00770"></a>00770 <span class="preprocessor"></span>
<a name="l00771"></a>00771 <span class="keywordflow">if</span> (addr == NULL) {
<a name="l00772"></a>00772 <span class="keywordflow">return</span> 0;
<a name="l00773"></a>00773 }
<a name="l00774"></a>00774
<a name="l00775"></a>00775 DEBUGMSGTL((<span class="stringliteral">"netsnmp_sockaddr_in"</span>,
<a name="l00776"></a>00776 <span class="stringliteral">"addr %p, inpeername \"%s\", default_target \"%s\"\n"</span>,
<a name="l00777"></a>00777 addr, inpeername ? inpeername : <span class="stringliteral">"[NIL]"</span>,
<a name="l00778"></a>00778 default_target ? default_target : <span class="stringliteral">"[NIL]"</span>));
<a name="l00779"></a>00779
<a name="l00780"></a>00780 memset(addr, 0, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> sockaddr_in));
<a name="l00781"></a>00781 addr->sin_addr.s_addr = htonl(INADDR_ANY);
<a name="l00782"></a>00782 addr->sin_family = AF_INET;
<a name="l00783"></a>00783 addr->sin_port = htons((u_short)SNMP_PORT);
<a name="l00784"></a>00784
<a name="l00785"></a>00785 {
<a name="l00786"></a>00786 <span class="keywordtype">int</span> port = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
<a name="l00787"></a>00787 NETSNMP_DS_LIB_DEFAULT_PORT);
<a name="l00788"></a>00788
<a name="l00789"></a>00789 <span class="keywordflow">if</span> (port != 0) {
<a name="l00790"></a>00790 addr->sin_port = htons((u_short)port);
<a name="l00791"></a>00791 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (default_target != NULL)
<a name="l00792"></a>00792 netsnmp_sockaddr_in2(addr, default_target, NULL);
<a name="l00793"></a>00793 }
<a name="l00794"></a>00794
<a name="l00795"></a>00795 <span class="keywordflow">if</span> (inpeername != NULL && *inpeername != <span class="charliteral">'\0'</span>) {
<a name="l00796"></a>00796 <span class="keyword">const</span> <span class="keywordtype">char</span> *host, *port;
<a name="l00797"></a>00797 <span class="keywordtype">char</span> *peername = NULL;
<a name="l00798"></a>00798 <span class="keywordtype">char</span> *cp;
<a name="l00799"></a>00799 <span class="comment">/*</span>
<a name="l00800"></a>00800 <span class="comment"> * Duplicate the peername because we might want to mank around with</span>
<a name="l00801"></a>00801 <span class="comment"> * it. </span>
<a name="l00802"></a>00802 <span class="comment"> */</span>
<a name="l00803"></a>00803
<a name="l00804"></a>00804 peername = strdup(inpeername);
<a name="l00805"></a>00805 <span class="keywordflow">if</span> (peername == NULL) {
<a name="l00806"></a>00806 <span class="keywordflow">return</span> 0;
<a name="l00807"></a>00807 }
<a name="l00808"></a>00808
<a name="l00809"></a>00809 <span class="comment">/*</span>
<a name="l00810"></a>00810 <span class="comment"> * Try and extract an appended port number. </span>
<a name="l00811"></a>00811 <span class="comment"> */</span>
<a name="l00812"></a>00812 cp = strchr(peername, <span class="charliteral">':'</span>);
<a name="l00813"></a>00813 <span class="keywordflow">if</span> (cp != NULL) {
<a name="l00814"></a>00814 *cp = <span class="charliteral">'\0'</span>;
<a name="l00815"></a>00815 port = cp + 1;
<a name="l00816"></a>00816 host = peername;
<a name="l00817"></a>00817 } <span class="keywordflow">else</span> {
<a name="l00818"></a>00818 host = NULL;
<a name="l00819"></a>00819 port = peername;
<a name="l00820"></a>00820 }
<a name="l00821"></a>00821
<a name="l00822"></a>00822 <span class="comment">/*</span>
<a name="l00823"></a>00823 <span class="comment"> * Try to convert the user port specifier</span>
<a name="l00824"></a>00824 <span class="comment"> */</span>
<a name="l00825"></a>00825 <span class="keywordflow">if</span> (port && *port == <span class="charliteral">'\0'</span>)
<a name="l00826"></a>00826 port = NULL;
<a name="l00827"></a>00827
<a name="l00828"></a>00828 <span class="keywordflow">if</span> (port != NULL) {
<a name="l00829"></a>00829 <span class="keywordtype">long</span> <span class="keywordtype">int</span> l;
<a name="l00830"></a>00830 <span class="keywordtype">char</span>* ep;
<a name="l00831"></a>00831
<a name="l00832"></a>00832 DEBUGMSGTL((<span class="stringliteral">"netsnmp_sockaddr_in"</span>, <span class="stringliteral">"check user service %s\n"</span>,
<a name="l00833"></a>00833 port));
<a name="l00834"></a>00834
<a name="l00835"></a>00835 l = strtol(port, &ep, 10);
<a name="l00836"></a>00836 <span class="keywordflow">if</span> (ep != port && *ep == <span class="charliteral">'\0'</span> && 0 <= l && l <= 0x0ffff)
<a name="l00837"></a>00837 addr->sin_port = htons((u_short)l);
<a name="l00838"></a>00838 <span class="keywordflow">else</span> {
<a name="l00839"></a>00839 <span class="keywordflow">if</span> (host == NULL) {
<a name="l00840"></a>00840 DEBUGMSGTL((<span class="stringliteral">"netsnmp_sockaddr_in"</span>,
<a name="l00841"></a>00841 <span class="stringliteral">"servname not numeric, "</span>
<a name="l00842"></a>00842 <span class="stringliteral">"check if it really is a destination)"</span>));
<a name="l00843"></a>00843 host = port;
<a name="l00844"></a>00844 port = NULL;
<a name="l00845"></a>00845 } <span class="keywordflow">else</span> {
<a name="l00846"></a>00846 DEBUGMSGTL((<span class="stringliteral">"netsnmp_sockaddr_in"</span>,
<a name="l00847"></a>00847 <span class="stringliteral">"servname not numeric"</span>));
<a name="l00848"></a>00848 free(peername);
<a name="l00849"></a>00849 <span class="keywordflow">return</span> 0;
<a name="l00850"></a>00850 }
<a name="l00851"></a>00851 }
<a name="l00852"></a>00852 }
<a name="l00853"></a>00853
<a name="l00854"></a>00854 <span class="comment">/*</span>
<a name="l00855"></a>00855 <span class="comment"> * Try to convert the user host specifier</span>
<a name="l00856"></a>00856 <span class="comment"> */</span>
<a name="l00857"></a>00857 <span class="keywordflow">if</span> (host && *host == <span class="charliteral">'\0'</span>)
<a name="l00858"></a>00858 host = NULL;
<a name="l00859"></a>00859
<a name="l00860"></a>00860 <span class="keywordflow">if</span> (host != NULL) {
<a name="l00861"></a>00861 DEBUGMSGTL((<span class="stringliteral">"netsnmp_sockaddr_in"</span>,
<a name="l00862"></a>00862 <span class="stringliteral">"check destination %s\n"</span>, host));
<a name="l00863"></a>00863
<a name="l00864"></a>00864 <span class="preprocessor">#if HAVE_GETADDRINFO</span>
<a name="l00865"></a>00865 <span class="preprocessor"></span> memset(&hint, 0, <span class="keyword">sizeof</span> hint);
<a name="l00866"></a>00866 hint.ai_flags = 0;
<a name="l00867"></a>00867 hint.ai_family = PF_INET;
<a name="l00868"></a>00868 hint.ai_socktype = SOCK_DGRAM;
<a name="l00869"></a>00869 hint.ai_protocol = 0;
<a name="l00870"></a>00870
<a name="l00871"></a>00871 err = getaddrinfo(peername, NULL, &hint, &addrs);
<a name="l00872"></a>00872 <span class="keywordflow">if</span> (err != 0) {
<a name="l00873"></a>00873 <span class="preprocessor">#if HAVE_GAI_STRERROR</span>
<a name="l00874"></a>00874 <span class="preprocessor"></span> <a class="code" href="group__snmp__logging.html#ga9ba905368ea1c551b969af44b13e37c2" title="This snmp logging function allows variable argument list given the specified format and priority...">snmp_log</a>(LOG_ERR, <span class="stringliteral">"getaddrinfo: %s %s\n"</span>, peername,
<a name="l00875"></a>00875 gai_strerror(err));
<a name="l00876"></a>00876 <span class="preprocessor">#else</span>
<a name="l00877"></a>00877 <span class="preprocessor"></span> <a class="code" href="group__snmp__logging.html#ga9ba905368ea1c551b969af44b13e37c2" title="This snmp logging function allows variable argument list given the specified format and priority...">snmp_log</a>(LOG_ERR, <span class="stringliteral">"getaddrinfo: %s (error %d)\n"</span>, peername,
<a name="l00878"></a>00878 err);
<a name="l00879"></a>00879 <span class="preprocessor">#endif</span>
<a name="l00880"></a>00880 <span class="preprocessor"></span> free(peername);
<a name="l00881"></a>00881 <span class="keywordflow">return</span> 0;
<a name="l00882"></a>00882 }
<a name="l00883"></a>00883 <span class="keywordflow">if</span> (addrs != NULL) {
<a name="l00884"></a>00884 DEBUGMSGTL((<span class="stringliteral">"netsnmp_sockaddr_in"</span>,
<a name="l00885"></a>00885 <span class="stringliteral">"hostname (resolved okay)\n"</span>));
<a name="l00886"></a>00886 memcpy(&addr->sin_addr,
<a name="l00887"></a>00887 &((<span class="keyword">struct</span> sockaddr_in *) addrs->ai_addr)->sin_addr,
<a name="l00888"></a>00888 <span class="keyword">sizeof</span>(<span class="keyword">struct</span> in_addr));
<a name="l00889"></a>00889 freeaddrinfo(addrs);
<a name="l00890"></a>00890 }
<a name="l00891"></a>00891 <span class="keywordflow">else</span> {
<a name="l00892"></a>00892 DEBUGMSGTL((<span class="stringliteral">"netsnmp_sockaddr_in"</span>,
<a name="l00893"></a>00893 <span class="stringliteral">"Failed to resolve IPv4 hostname\n"</span>));
<a name="l00894"></a>00894 }
<a name="l00895"></a>00895 <span class="preprocessor">#elif HAVE_GETHOSTBYNAME</span>
<a name="l00896"></a>00896 <span class="preprocessor"></span> hp = gethostbyname(host);
<a name="l00897"></a>00897 <span class="keywordflow">if</span> (hp == NULL) {
<a name="l00898"></a>00898 DEBUGMSGTL((<span class="stringliteral">"netsnmp_sockaddr_in"</span>,
<a name="l00899"></a>00899 <span class="stringliteral">"hostname (couldn't resolve)\n"</span>));
<a name="l00900"></a>00900 free(peername);
<a name="l00901"></a>00901 <span class="keywordflow">return</span> 0;
<a name="l00902"></a>00902 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (hp->h_addrtype != AF_INET) {
<a name="l00903"></a>00903 DEBUGMSGTL((<span class="stringliteral">"netsnmp_sockaddr_in"</span>,
<a name="l00904"></a>00904 <span class="stringliteral">"hostname (not AF_INET!)\n"</span>));
<a name="l00905"></a>00905 free(peername);
<a name="l00906"></a>00906 <span class="keywordflow">return</span> 0;
<a name="l00907"></a>00907 } <span class="keywordflow">else</span> {
<a name="l00908"></a>00908 DEBUGMSGTL((<span class="stringliteral">"netsnmp_sockaddr_in"</span>,
<a name="l00909"></a>00909 <span class="stringliteral">"hostname (resolved okay)\n"</span>));
<a name="l00910"></a>00910 memcpy(&addr->sin_addr, hp->h_addr, hp->h_length);
<a name="l00911"></a>00911 }
<a name="l00912"></a>00912 <span class="preprocessor">#elif HAVE_GETIPNODEBYNAME</span>
<a name="l00913"></a>00913 <span class="preprocessor"></span> hp = getipnodebyname(peername, AF_INET, 0, &err);
<a name="l00914"></a>00914 <span class="keywordflow">if</span> (hp == NULL) {
<a name="l00915"></a>00915 DEBUGMSGTL((<span class="stringliteral">"netsnmp_sockaddr_in"</span>,
<a name="l00916"></a>00916 <span class="stringliteral">"hostname (couldn't resolve = %d)\n"</span>, err));
<a name="l00917"></a>00917 free(peername);
<a name="l00918"></a>00918 <span class="keywordflow">return</span> 0;
<a name="l00919"></a>00919 }
<a name="l00920"></a>00920 DEBUGMSGTL((<span class="stringliteral">"netsnmp_sockaddr_in"</span>,
<a name="l00921"></a>00921 <span class="stringliteral">"hostname (resolved okay)\n"</span>));
<a name="l00922"></a>00922 memcpy(&(addr->sin_addr), hp->h_addr, hp->h_length);
<a name="l00923"></a>00923 <span class="preprocessor">#else </span><span class="comment">/* HAVE_GETIPNODEBYNAME */</span>
<a name="l00924"></a>00924 <span class="comment">/*</span>
<a name="l00925"></a>00925 <span class="comment"> * There is no name resolving function available.</span>
<a name="l00926"></a>00926 <span class="comment"> */</span>
<a name="l00927"></a>00927 DEBUGMSGTL((<span class="stringliteral">"netsnmp_sockaddr_in"</span>,
<a name="l00928"></a>00928 <span class="stringliteral">"no getaddrinfo()/getipnodebyname()/gethostbyname()\n"</span>));
<a name="l00929"></a>00929 free(peername);
<a name="l00930"></a>00930 <span class="keywordflow">return</span> 0;
<a name="l00931"></a>00931 <span class="preprocessor">#endif </span><span class="comment">/* HAVE_GETHOSTBYNAME */</span>
<a name="l00932"></a>00932 }
<a name="l00933"></a>00933 free(peername);
<a name="l00934"></a>00934 }
<a name="l00935"></a>00935
<a name="l00936"></a>00936 <span class="comment">/*</span>
<a name="l00937"></a>00937 <span class="comment"> * Finished</span>
<a name="l00938"></a>00938 <span class="comment"> */</span>
<a name="l00939"></a>00939
<a name="l00940"></a>00940 DEBUGMSGTL((<span class="stringliteral">"netsnmp_sockaddr_in"</span>, <span class="stringliteral">"return { AF_INET, %s:%hu }\n"</span>,
<a name="l00941"></a>00941 inet_ntoa(addr->sin_addr), ntohs(addr->sin_port)));
<a name="l00942"></a>00942 <span class="keywordflow">return</span> 1;
<a name="l00943"></a>00943 }
<a name="l00944"></a>00944
<a name="l00945"></a>00945
<a name="l00946"></a>00946 <span class="keywordtype">int</span>
<a name="l00947"></a>00947 netsnmp_sockaddr_in(<span class="keyword">struct</span> sockaddr_in *addr,
<a name="l00948"></a>00948 <span class="keyword">const</span> <span class="keywordtype">char</span> *inpeername, <span class="keywordtype">int</span> remote_port)
<a name="l00949"></a>00949 {
<a name="l00950"></a>00950 <span class="keywordtype">char</span> buf[<span class="keyword">sizeof</span>(int) * 3 + 2];
<a name="l00951"></a>00951 sprintf(buf, <span class="stringliteral">":%u"</span>, remote_port);
<a name="l00952"></a>00952 <span class="keywordflow">return</span> netsnmp_sockaddr_in2(addr, inpeername, remote_port ? buf : NULL);
<a name="l00953"></a>00953 }
<a name="l00954"></a>00954
<a name="l00955"></a>00955 <span class="preprocessor">#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)</span>
<a name="l00956"></a>00956 <span class="preprocessor"></span><span class="comment">/*</span>
<a name="l00957"></a>00957 <span class="comment"> * The following functions provide the "com2sec" configuration token</span>
<a name="l00958"></a>00958 <span class="comment"> * functionality for compatibility. </span>
<a name="l00959"></a>00959 <span class="comment"> */</span>
<a name="l00960"></a>00960
<a name="l00961"></a>00961 <span class="preprocessor">#define EXAMPLE_NETWORK "NETWORK"</span>
<a name="l00962"></a>00962 <span class="preprocessor"></span><span class="preprocessor">#define EXAMPLE_COMMUNITY "COMMUNITY"</span>
<a name="l00963"></a>00963 <span class="preprocessor"></span>
<a name="l00964"></a><a class="code" href="struct__com2SecEntry.html">00964</a> <span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct__com2SecEntry.html">_com2SecEntry</a> {
<a name="l00965"></a>00965 <span class="keywordtype">char</span> community[COMMUNITY_MAX_LEN];
<a name="l00966"></a>00966 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> network;
<a name="l00967"></a>00967 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> mask;
<a name="l00968"></a>00968 <span class="keywordtype">char</span> secName[VACMSTRINGLEN];
<a name="l00969"></a>00969 <span class="keywordtype">char</span> contextName[VACMSTRINGLEN];
<a name="l00970"></a>00970 <span class="keyword">struct </span><a class="code" href="struct__com2SecEntry.html">_com2SecEntry</a> *next;
<a name="l00971"></a>00971 } <a class="code" href="struct__com2SecEntry.html">com2SecEntry</a>;
<a name="l00972"></a>00972
<a name="l00973"></a>00973 <a class="code" href="struct__com2SecEntry.html">com2SecEntry</a> *com2SecList = NULL, *com2SecListLast = NULL;
<a name="l00974"></a>00974
<a name="l00975"></a>00975 <span class="keywordtype">void</span>
<a name="l00976"></a>00976 netsnmp_udp_parse_security(<span class="keyword">const</span> <span class="keywordtype">char</span> *token, <span class="keywordtype">char</span> *param)
<a name="l00977"></a>00977 {
<a name="l00978"></a>00978 <span class="keywordtype">char</span> secName[VACMSTRINGLEN];
<a name="l00979"></a>00979 <span class="keywordtype">char</span> contextName[VACMSTRINGLEN];
<a name="l00980"></a>00980 <span class="keywordtype">char</span> community[COMMUNITY_MAX_LEN];
<a name="l00981"></a>00981 <span class="keywordtype">char</span> source[SNMP_MAXBUF_SMALL];
<a name="l00982"></a>00982 <span class="keywordtype">char</span> *cp = NULL;
<a name="l00983"></a>00983 <span class="keyword">const</span> <span class="keywordtype">char</span> *strmask = NULL;
<a name="l00984"></a>00984 <a class="code" href="struct__com2SecEntry.html">com2SecEntry</a> *e = NULL;
<a name="l00985"></a>00985 in_addr_t network = 0, mask = 0;
<a name="l00986"></a>00986
<a name="l00987"></a>00987 <span class="comment">/*</span>
<a name="l00988"></a>00988 <span class="comment"> * Get security, source address/netmask and community strings. </span>
<a name="l00989"></a>00989 <span class="comment"> */</span>
<a name="l00990"></a>00990
<a name="l00991"></a>00991 cp = copy_nword( param, secName, <span class="keyword">sizeof</span>(secName));
<a name="l00992"></a>00992 <span class="keywordflow">if</span> (strcmp(secName, <span class="stringliteral">"-Cn"</span>) == 0) {
<a name="l00993"></a>00993 <span class="keywordflow">if</span> (!cp) {
<a name="l00994"></a>00994 config_perror(<span class="stringliteral">"missing CONTEXT_NAME parameter"</span>);
<a name="l00995"></a>00995 <span class="keywordflow">return</span>;
<a name="l00996"></a>00996 }
<a name="l00997"></a>00997 cp = copy_nword( cp, contextName, <span class="keyword">sizeof</span>(contextName));
<a name="l00998"></a>00998 cp = copy_nword( cp, secName, <span class="keyword">sizeof</span>(secName));
<a name="l00999"></a>00999 } <span class="keywordflow">else</span> {
<a name="l01000"></a>01000 contextName[0] = <span class="charliteral">'\0'</span>;
<a name="l01001"></a>01001 }
<a name="l01002"></a>01002 <span class="keywordflow">if</span> (secName[0] == <span class="charliteral">'\0'</span>) {
<a name="l01003"></a>01003 config_perror(<span class="stringliteral">"missing NAME parameter"</span>);
<a name="l01004"></a>01004 <span class="keywordflow">return</span>;
<a name="l01005"></a>01005 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (strlen(secName) > (VACMSTRINGLEN - 1)) {
<a name="l01006"></a>01006 config_perror(<span class="stringliteral">"security name too long"</span>);
<a name="l01007"></a>01007 <span class="keywordflow">return</span>;
<a name="l01008"></a>01008 }
<a name="l01009"></a>01009 cp = copy_nword( cp, source, <span class="keyword">sizeof</span>(source));
<a name="l01010"></a>01010 <span class="keywordflow">if</span> (source[0] == <span class="charliteral">'\0'</span>) {
<a name="l01011"></a>01011 config_perror(<span class="stringliteral">"missing SOURCE parameter"</span>);
<a name="l01012"></a>01012 <span class="keywordflow">return</span>;
<a name="l01013"></a>01013 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (strncmp(source, EXAMPLE_NETWORK, strlen(EXAMPLE_NETWORK)) ==
<a name="l01014"></a>01014 0) {
<a name="l01015"></a>01015 config_perror(<span class="stringliteral">"example config NETWORK not properly configured"</span>);
<a name="l01016"></a>01016 <span class="keywordflow">return</span>;
<a name="l01017"></a>01017 }
<a name="l01018"></a>01018 cp = copy_nword( cp, community, <span class="keyword">sizeof</span>(community));
<a name="l01019"></a>01019 <span class="keywordflow">if</span> (community[0] == <span class="charliteral">'\0'</span>) {
<a name="l01020"></a>01020 config_perror(<span class="stringliteral">"missing COMMUNITY parameter\n"</span>);
<a name="l01021"></a>01021 <span class="keywordflow">return</span>;
<a name="l01022"></a>01022 } <span class="keywordflow">else</span>
<a name="l01023"></a>01023 <span class="keywordflow">if</span> (strncmp
<a name="l01024"></a>01024 (community, EXAMPLE_COMMUNITY, strlen(EXAMPLE_COMMUNITY))
<a name="l01025"></a>01025 == 0) {
<a name="l01026"></a>01026 config_perror(<span class="stringliteral">"example config COMMUNITY not properly configured"</span>);
<a name="l01027"></a>01027 <span class="keywordflow">return</span>;
<a name="l01028"></a>01028 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (strlen(community) > (COMMUNITY_MAX_LEN - 1)) {
<a name="l01029"></a>01029 config_perror(<span class="stringliteral">"community name too long"</span>);
<a name="l01030"></a>01030 <span class="keywordflow">return</span>;
<a name="l01031"></a>01031 }
<a name="l01032"></a>01032
<a name="l01033"></a>01033 <span class="comment">/*</span>
<a name="l01034"></a>01034 <span class="comment"> * Process the source address/netmask string. </span>
<a name="l01035"></a>01035 <span class="comment"> */</span>
<a name="l01036"></a>01036
<a name="l01037"></a>01037 cp = strchr(source, <span class="charliteral">'/'</span>);
<a name="l01038"></a>01038 <span class="keywordflow">if</span> (cp != NULL) {
<a name="l01039"></a>01039 <span class="comment">/*</span>
<a name="l01040"></a>01040 <span class="comment"> * Mask given. </span>
<a name="l01041"></a>01041 <span class="comment"> */</span>
<a name="l01042"></a>01042 *cp = <span class="charliteral">'\0'</span>;
<a name="l01043"></a>01043 strmask = cp + 1;
<a name="l01044"></a>01044 }
<a name="l01045"></a>01045
<a name="l01046"></a>01046 <span class="comment">/*</span>
<a name="l01047"></a>01047 <span class="comment"> * Deal with the network part first. </span>
<a name="l01048"></a>01048 <span class="comment"> */</span>
<a name="l01049"></a>01049
<a name="l01050"></a>01050 <span class="keywordflow">if</span> ((strcmp(source, <span class="stringliteral">"default"</span>) == 0)
<a name="l01051"></a>01051 || (strcmp(source, <span class="stringliteral">"0.0.0.0"</span>) == 0)) {
<a name="l01052"></a>01052 network = 0;
<a name="l01053"></a>01053 strmask = <span class="stringliteral">"0.0.0.0"</span>;
<a name="l01054"></a>01054 } <span class="keywordflow">else</span> {
<a name="l01055"></a>01055 <span class="comment">/*</span>
<a name="l01056"></a>01056 <span class="comment"> * Try interpreting as a dotted quad. </span>
<a name="l01057"></a>01057 <span class="comment"> */</span>
<a name="l01058"></a>01058 network = inet_addr(source);
<a name="l01059"></a>01059
<a name="l01060"></a>01060 <span class="keywordflow">if</span> (network == (in_addr_t) -1) {
<a name="l01061"></a>01061 <span class="comment">/*</span>
<a name="l01062"></a>01062 <span class="comment"> * Nope, wasn't a dotted quad. Must be a hostname. </span>
<a name="l01063"></a>01063 <span class="comment"> */</span>
<a name="l01064"></a>01064 <span class="preprocessor">#ifdef HAVE_GETHOSTBYNAME</span>
<a name="l01065"></a>01065 <span class="preprocessor"></span> <span class="keyword">struct </span>hostent *hp = gethostbyname(source);
<a name="l01066"></a>01066 <span class="keywordflow">if</span> (hp == NULL) {
<a name="l01067"></a>01067 config_perror(<span class="stringliteral">"bad source address"</span>);
<a name="l01068"></a>01068 <span class="keywordflow">return</span>;
<a name="l01069"></a>01069 } <span class="keywordflow">else</span> {
<a name="l01070"></a>01070 <span class="keywordflow">if</span> (hp->h_addrtype != AF_INET) {
<a name="l01071"></a>01071 config_perror(<span class="stringliteral">"no IP address for source hostname"</span>);
<a name="l01072"></a>01072 <span class="keywordflow">return</span>;
<a name="l01073"></a>01073 }
<a name="l01074"></a>01074 network = *((in_addr_t *) hp->h_addr);
<a name="l01075"></a>01075 }
<a name="l01076"></a>01076 <span class="preprocessor">#else </span><span class="comment">/*HAVE_GETHOSTBYNAME */</span>
<a name="l01077"></a>01077 <span class="comment">/*</span>
<a name="l01078"></a>01078 <span class="comment"> * Oh dear. </span>
<a name="l01079"></a>01079 <span class="comment"> */</span>
<a name="l01080"></a>01080 config_perror(<span class="stringliteral">"cannot resolve source hostname"</span>);
<a name="l01081"></a>01081 <span class="keywordflow">return</span>;
<a name="l01082"></a>01082 <span class="preprocessor">#endif </span><span class="comment">/*HAVE_GETHOSTBYNAME */</span>
<a name="l01083"></a>01083 }
<a name="l01084"></a>01084 }
<a name="l01085"></a>01085
<a name="l01086"></a>01086 <span class="comment">/*</span>
<a name="l01087"></a>01087 <span class="comment"> * Now work out the mask. </span>
<a name="l01088"></a>01088 <span class="comment"> */</span>
<a name="l01089"></a>01089
<a name="l01090"></a>01090 <span class="keywordflow">if</span> (strmask == NULL || *strmask == <span class="charliteral">'\0'</span>) {
<a name="l01091"></a>01091 <span class="comment">/*</span>
<a name="l01092"></a>01092 <span class="comment"> * No mask was given. Use 255.255.255.255. </span>
<a name="l01093"></a>01093 <span class="comment"> */</span>
<a name="l01094"></a>01094 mask = 0xffffffffL;
<a name="l01095"></a>01095 } <span class="keywordflow">else</span> {
<a name="l01096"></a>01096 <span class="keywordflow">if</span> (strchr(strmask, <span class="charliteral">'.'</span>)) {
<a name="l01097"></a>01097 <span class="comment">/*</span>
<a name="l01098"></a>01098 <span class="comment"> * Try to interpret mask as a dotted quad. </span>
<a name="l01099"></a>01099 <span class="comment"> */</span>
<a name="l01100"></a>01100 mask = inet_addr(strmask);
<a name="l01101"></a>01101 <span class="keywordflow">if</span> (mask == (in_addr_t) -1 &&
<a name="l01102"></a>01102 strncmp(strmask, <span class="stringliteral">"255.255.255.255"</span>, 15) != 0) {
<a name="l01103"></a>01103 config_perror(<span class="stringliteral">"bad mask"</span>);
<a name="l01104"></a>01104 <span class="keywordflow">return</span>;
<a name="l01105"></a>01105 }
<a name="l01106"></a>01106 } <span class="keywordflow">else</span> {
<a name="l01107"></a>01107 <span class="comment">/*</span>
<a name="l01108"></a>01108 <span class="comment"> * Try to interpret mask as a "number of 1 bits". </span>
<a name="l01109"></a>01109 <span class="comment"> */</span>
<a name="l01110"></a>01110 <span class="keywordtype">int</span> maskLen = atoi(strmask), maskBit = 0x80000000L;
<a name="l01111"></a>01111 <span class="keywordflow">if</span> (maskLen <= 0 || maskLen > 32) {
<a name="l01112"></a>01112 config_perror(<span class="stringliteral">"bad mask length"</span>);
<a name="l01113"></a>01113 <span class="keywordflow">return</span>;
<a name="l01114"></a>01114 }
<a name="l01115"></a>01115 <span class="keywordflow">while</span> (maskLen--) {
<a name="l01116"></a>01116 mask |= maskBit;
<a name="l01117"></a>01117 maskBit >>= 1;
<a name="l01118"></a>01118 }
<a name="l01119"></a>01119 mask = htonl(mask);
<a name="l01120"></a>01120 }
<a name="l01121"></a>01121 }
<a name="l01122"></a>01122
<a name="l01123"></a>01123 <span class="comment">/*</span>
<a name="l01124"></a>01124 <span class="comment"> * Check that the network and mask are consistent. </span>
<a name="l01125"></a>01125 <span class="comment"> */</span>
<a name="l01126"></a>01126
<a name="l01127"></a>01127 <span class="keywordflow">if</span> (network & ~mask) {
<a name="l01128"></a>01128 config_perror(<span class="stringliteral">"source/mask mismatch"</span>);
<a name="l01129"></a>01129 <span class="keywordflow">return</span>;
<a name="l01130"></a>01130 }
<a name="l01131"></a>01131
<a name="l01132"></a>01132 e = (<a class="code" href="struct__com2SecEntry.html">com2SecEntry</a> *) malloc(<span class="keyword">sizeof</span>(<a class="code" href="struct__com2SecEntry.html">com2SecEntry</a>));
<a name="l01133"></a>01133 <span class="keywordflow">if</span> (e == NULL) {
<a name="l01134"></a>01134 config_perror(<span class="stringliteral">"memory error"</span>);
<a name="l01135"></a>01135 <span class="keywordflow">return</span>;
<a name="l01136"></a>01136 }
<a name="l01137"></a>01137
<a name="l01138"></a>01138 <span class="comment">/*</span>
<a name="l01139"></a>01139 <span class="comment"> * Everything is okay. Copy the parameters to the structure allocated</span>
<a name="l01140"></a>01140 <span class="comment"> * above and add it to END of the list. </span>
<a name="l01141"></a>01141 <span class="comment"> */</span>
<a name="l01142"></a>01142
<a name="l01143"></a>01143 DEBUGMSGTL((<span class="stringliteral">"netsnmp_udp_parse_security"</span>,
<a name="l01144"></a>01144 <span class="stringliteral">"<\"%s\", 0x%08x/0x%08x> => \"%s\"\n"</span>, community, network,
<a name="l01145"></a>01145 mask, secName));
<a name="l01146"></a>01146
<a name="l01147"></a>01147 strcpy(e->contextName, contextName);
<a name="l01148"></a>01148 strcpy(e->secName, secName);
<a name="l01149"></a>01149 strcpy(e->community, community);
<a name="l01150"></a>01150 e->network = network;
<a name="l01151"></a>01151 e->mask = mask;
<a name="l01152"></a>01152 e->next = NULL;
<a name="l01153"></a>01153
<a name="l01154"></a>01154 <span class="keywordflow">if</span> (com2SecListLast != NULL) {
<a name="l01155"></a>01155 com2SecListLast->next = e;
<a name="l01156"></a>01156 com2SecListLast = e;
<a name="l01157"></a>01157 } <span class="keywordflow">else</span> {
<a name="l01158"></a>01158 com2SecListLast = com2SecList = e;
<a name="l01159"></a>01159 }
<a name="l01160"></a>01160 }
<a name="l01161"></a>01161
<a name="l01162"></a>01162
<a name="l01163"></a>01163 <span class="keywordtype">void</span>
<a name="l01164"></a>01164 netsnmp_udp_com2SecList_free(<span class="keywordtype">void</span>)
<a name="l01165"></a>01165 {
<a name="l01166"></a>01166 <a class="code" href="struct__com2SecEntry.html">com2SecEntry</a> *e = com2SecList;
<a name="l01167"></a>01167 <span class="keywordflow">while</span> (e != NULL) {
<a name="l01168"></a>01168 <a class="code" href="struct__com2SecEntry.html">com2SecEntry</a> *tmp = e;
<a name="l01169"></a>01169 e = e->next;
<a name="l01170"></a>01170 free(tmp);
<a name="l01171"></a>01171 }
<a name="l01172"></a>01172 com2SecList = com2SecListLast = NULL;
<a name="l01173"></a>01173 }
<a name="l01174"></a>01174 <span class="preprocessor">#endif </span><span class="comment">/* support for community based SNMP */</span>
<a name="l01175"></a>01175
<a name="l01176"></a>01176 <span class="keywordtype">void</span>
<a name="l01177"></a>01177 netsnmp_udp_agent_config_tokens_register(<span class="keywordtype">void</span>)
<a name="l01178"></a>01178 {
<a name="l01179"></a>01179 <span class="preprocessor">#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)</span>
<a name="l01180"></a>01180 <span class="preprocessor"></span> register_app_config_handler(<span class="stringliteral">"com2sec"</span>, netsnmp_udp_parse_security,
<a name="l01181"></a>01181 netsnmp_udp_com2SecList_free,
<a name="l01182"></a>01182 <span class="stringliteral">"[-Cn CONTEXT] secName IPv4-network-address[/netmask] community"</span>);
<a name="l01183"></a>01183 <span class="preprocessor">#endif </span><span class="comment">/* support for community based SNMP */</span>
<a name="l01184"></a>01184 }
<a name="l01185"></a>01185
<a name="l01186"></a>01186
<a name="l01187"></a>01187
<a name="l01188"></a>01188 <span class="comment">/*</span>
<a name="l01189"></a>01189 <span class="comment"> * Return 0 if there are no com2sec entries, or return 1 if there ARE com2sec </span>
<a name="l01190"></a>01190 <span class="comment"> * entries. On return, if a com2sec entry matched the passed parameters,</span>
<a name="l01191"></a>01191 <span class="comment"> * then *secName points at the appropriate security name, or is NULL if the</span>
<a name="l01192"></a>01192 <span class="comment"> * parameters did not match any com2sec entry. </span>
<a name="l01193"></a>01193 <span class="comment"> */</span>
<a name="l01194"></a>01194
<a name="l01195"></a>01195 <span class="preprocessor">#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)</span>
<a name="l01196"></a>01196 <span class="preprocessor"></span><span class="keywordtype">int</span>
<a name="l01197"></a>01197 netsnmp_udp_getSecName(<span class="keywordtype">void</span> *opaque, <span class="keywordtype">int</span> olength,
<a name="l01198"></a>01198 <span class="keyword">const</span> <span class="keywordtype">char</span> *community,
<a name="l01199"></a>01199 <span class="keywordtype">size_t</span> community_len, <span class="keywordtype">char</span> **secName,
<a name="l01200"></a>01200 <span class="keywordtype">char</span> **contextName)
<a name="l01201"></a>01201 {
<a name="l01202"></a>01202 <a class="code" href="struct__com2SecEntry.html">com2SecEntry</a> *c;
<a name="l01203"></a>01203 <a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a> *addr_pair = (<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a> *) opaque;
<a name="l01204"></a>01204 <span class="keyword">struct </span>sockaddr_in *from = (<span class="keyword">struct </span>sockaddr_in *) &(addr_pair->remote_addr);
<a name="l01205"></a>01205 <span class="keywordtype">char</span> *ztcommunity = NULL;
<a name="l01206"></a>01206
<a name="l01207"></a>01207 <span class="keywordflow">if</span> (secName != NULL) {
<a name="l01208"></a>01208 *secName = NULL; <span class="comment">/* Haven't found anything yet */</span>
<a name="l01209"></a>01209 }
<a name="l01210"></a>01210
<a name="l01211"></a>01211 <span class="comment">/*</span>
<a name="l01212"></a>01212 <span class="comment"> * Special case if there are NO entries (as opposed to no MATCHING</span>
<a name="l01213"></a>01213 <span class="comment"> * entries). </span>
<a name="l01214"></a>01214 <span class="comment"> */</span>
<a name="l01215"></a>01215
<a name="l01216"></a>01216 <span class="keywordflow">if</span> (com2SecList == NULL) {
<a name="l01217"></a>01217 DEBUGMSGTL((<span class="stringliteral">"netsnmp_udp_getSecName"</span>, <span class="stringliteral">"no com2sec entries\n"</span>));
<a name="l01218"></a>01218 <span class="keywordflow">return</span> 0;
<a name="l01219"></a>01219 }
<a name="l01220"></a>01220
<a name="l01221"></a>01221 <span class="comment">/*</span>
<a name="l01222"></a>01222 <span class="comment"> * If there is no IPv4 source address, then there can be no valid security</span>
<a name="l01223"></a>01223 <span class="comment"> * name. </span>
<a name="l01224"></a>01224 <span class="comment"> */</span>
<a name="l01225"></a>01225
<a name="l01226"></a>01226 <span class="keywordflow">if</span> (opaque == NULL || olength != <span class="keyword">sizeof</span>(<a class="code" href="structnetsnmp__udp__addr__pair__s.html">netsnmp_udp_addr_pair</a>) ||
<a name="l01227"></a>01227 from->sin_family != AF_INET) {
<a name="l01228"></a>01228 DEBUGMSGTL((<span class="stringliteral">"netsnmp_udp_getSecName"</span>,
<a name="l01229"></a>01229 <span class="stringliteral">"no IPv4 source address in PDU?\n"</span>));
<a name="l01230"></a>01230 <span class="keywordflow">return</span> 1;
<a name="l01231"></a>01231 }
<a name="l01232"></a>01232
<a name="l01233"></a>01233 DEBUGIF(<span class="stringliteral">"netsnmp_udp_getSecName"</span>) {
<a name="l01234"></a>01234 ztcommunity = (<span class="keywordtype">char</span> *)malloc(community_len + 1);
<a name="l01235"></a>01235 <span class="keywordflow">if</span> (ztcommunity != NULL) {
<a name="l01236"></a>01236 memcpy(ztcommunity, community, community_len);
<a name="l01237"></a>01237 ztcommunity[community_len] = <span class="charliteral">'\0'</span>;
<a name="l01238"></a>01238 }
<a name="l01239"></a>01239
<a name="l01240"></a>01240 DEBUGMSGTL((<span class="stringliteral">"netsnmp_udp_getSecName"</span>, <span class="stringliteral">"resolve <\"%s\", 0x%08x>\n"</span>,
<a name="l01241"></a>01241 ztcommunity ? ztcommunity : <span class="stringliteral">"<malloc error>"</span>,
<a name="l01242"></a>01242 from->sin_addr.s_addr));
<a name="l01243"></a>01243 }
<a name="l01244"></a>01244
<a name="l01245"></a>01245 <span class="keywordflow">for</span> (c = com2SecList; c != NULL; c = c->next) {
<a name="l01246"></a>01246 DEBUGMSGTL((<span class="stringliteral">"netsnmp_udp_getSecName"</span>,<span class="stringliteral">"compare <\"%s\", 0x%08x/0x%08x>"</span>,
<a name="l01247"></a>01247 c->community, c->network, c->mask));
<a name="l01248"></a>01248 <span class="keywordflow">if</span> ((community_len == strlen(c->community)) &&
<a name="l01249"></a>01249 (memcmp(community, c->community, community_len) == 0) &&
<a name="l01250"></a>01250 ((from->sin_addr.s_addr & c->mask) == c->network)) {
<a name="l01251"></a>01251 DEBUGMSG((<span class="stringliteral">"netsnmp_udp_getSecName"</span>, <span class="stringliteral">"... SUCCESS\n"</span>));
<a name="l01252"></a>01252 <span class="keywordflow">if</span> (secName != NULL) {
<a name="l01253"></a>01253 *secName = c->secName;
<a name="l01254"></a>01254 *contextName = c->contextName;
<a name="l01255"></a>01255 }
<a name="l01256"></a>01256 <span class="keywordflow">break</span>;
<a name="l01257"></a>01257 }
<a name="l01258"></a>01258 DEBUGMSG((<span class="stringliteral">"netsnmp_udp_getSecName"</span>, <span class="stringliteral">"... nope\n"</span>));
<a name="l01259"></a>01259 }
<a name="l01260"></a>01260 <span class="keywordflow">if</span> (ztcommunity != NULL) {
<a name="l01261"></a>01261 free(ztcommunity);
<a name="l01262"></a>01262 }
<a name="l01263"></a>01263 <span class="keywordflow">return</span> 1;
<a name="l01264"></a>01264 }
<a name="l01265"></a>01265 <span class="preprocessor">#endif </span><span class="comment">/* support for community based SNMP */</span>
<a name="l01266"></a>01266
<a name="l01267"></a>01267
<a name="l01268"></a>01268 <a class="code" href="structnetsnmp__transport__s.html">netsnmp_transport</a> *
<a name="l01269"></a>01269 netsnmp_udp_create_tstring(<span class="keyword">const</span> <span class="keywordtype">char</span> *str, <span class="keywordtype">int</span> local,
<a name="l01270"></a>01270 <span class="keyword">const</span> <span class="keywordtype">char</span> *default_target)
<a name="l01271"></a>01271 {
<a name="l01272"></a>01272 <span class="keyword">struct </span>sockaddr_in addr;
<a name="l01273"></a>01273
<a name="l01274"></a>01274 <span class="keywordflow">if</span> (netsnmp_sockaddr_in2(&addr, str, default_target)) {
<a name="l01275"></a>01275 <span class="keywordflow">return</span> netsnmp_udp_transport(&addr, local);
<a name="l01276"></a>01276 } <span class="keywordflow">else</span> {
<a name="l01277"></a>01277 <span class="keywordflow">return</span> NULL;
<a name="l01278"></a>01278 }
<a name="l01279"></a>01279 }
<a name="l01280"></a>01280
<a name="l01281"></a>01281
<a name="l01282"></a>01282 <a class="code" href="structnetsnmp__transport__s.html">netsnmp_transport</a> *
<a name="l01283"></a>01283 netsnmp_udp_create_ostring(<span class="keyword">const</span> u_char * o, <span class="keywordtype">size_t</span> o_len, <span class="keywordtype">int</span> local)
<a name="l01284"></a>01284 {
<a name="l01285"></a>01285 <span class="keyword">struct </span>sockaddr_in addr;
<a name="l01286"></a>01286
<a name="l01287"></a>01287 <span class="keywordflow">if</span> (o_len == 6) {
<a name="l01288"></a>01288 <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> porttmp = (o[4] << 8) + o[5];
<a name="l01289"></a>01289 addr.sin_family = AF_INET;
<a name="l01290"></a>01290 memcpy((u_char *) & (addr.sin_addr.s_addr), o, 4);
<a name="l01291"></a>01291 addr.sin_port = htons(porttmp);
<a name="l01292"></a>01292 <span class="keywordflow">return</span> netsnmp_udp_transport(&addr, local);
<a name="l01293"></a>01293 }
<a name="l01294"></a>01294 <span class="keywordflow">return</span> NULL;
<a name="l01295"></a>01295 }
<a name="l01296"></a>01296
<a name="l01297"></a>01297
<a name="l01298"></a>01298 <span class="keywordtype">void</span>
<a name="l01299"></a>01299 netsnmp_udp_ctor(<span class="keywordtype">void</span>)
<a name="l01300"></a>01300 {
<a name="l01301"></a>01301 udpDomain.name = netsnmpUDPDomain;
<a name="l01302"></a>01302 udpDomain.name_length = netsnmpUDPDomain_len;
<a name="l01303"></a>01303 udpDomain.prefix = (<span class="keyword">const</span> <span class="keywordtype">char</span>**)calloc(2, <span class="keyword">sizeof</span>(<span class="keywordtype">char</span> *));
<a name="l01304"></a>01304 udpDomain.prefix[0] = <span class="stringliteral">"udp"</span>;
<a name="l01305"></a>01305
<a name="l01306"></a>01306 udpDomain.f_create_from_tstring_new = netsnmp_udp_create_tstring;
<a name="l01307"></a>01307 udpDomain.f_create_from_ostring = netsnmp_udp_create_ostring;
<a name="l01308"></a>01308
<a name="l01309"></a>01309 netsnmp_tdomain_register(&udpDomain);
<a name="l01310"></a>01310 }
</pre></div></div><!-- contents -->
<hr class="footer"/><address class="footer"><small>
Generated by  <a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.7.6.1
</small></address>
</body>
</html>