libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2008-2011, 2013 Peter Miller 00004 * 00005 * This program is free software; you can redistribute it and/or modify it 00006 * under the terms of the GNU Lesser General Public License as published by 00007 * the Free Software Foundation; either version 3 of the License, or (at 00008 * your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 #include <libexplain/ac/errno.h> 00020 #include <libexplain/ac/sys/socket.h> 00021 #include <libexplain/ac/sys/stat.h> 00022 #include <libexplain/ac/sys/un.h> 00023 00024 #include <libexplain/buffer/address_family.h> 00025 #include <libexplain/buffer/eacces.h> 00026 #include <libexplain/buffer/eaddrinuse.h> 00027 #include <libexplain/buffer/eafnosupport.h> 00028 #include <libexplain/buffer/ebadf.h> 00029 #include <libexplain/buffer/efault.h> 00030 #include <libexplain/buffer/eintr.h> 00031 #include <libexplain/buffer/enotsock.h> 00032 #include <libexplain/buffer/errno/connect.h> 00033 #include <libexplain/buffer/errno/generic.h> 00034 #include <libexplain/buffer/errno/path_resolution.h> 00035 #include <libexplain/buffer/fildes_to_pathname.h> 00036 #include <libexplain/buffer/file_type.h> 00037 #include <libexplain/buffer/gettext.h> 00038 #include <libexplain/buffer/pointer.h> 00039 #include <libexplain/buffer/software_error.h> 00040 #include <libexplain/buffer/sockaddr.h> 00041 #include <libexplain/explanation.h> 00042 #include <libexplain/option.h> 00043 00044 00045 static void 00046 explain_buffer_errno_connect_system_call(explain_string_buffer_t *sb, 00047 int errnum, int fildes, const struct sockaddr *serv_addr, 00048 int serv_addr_size) 00049 { 00050 (void)errnum; 00051 explain_string_buffer_printf(sb, "connect(fildes = %d", fildes); 00052 explain_buffer_fildes_to_pathname(sb, fildes); 00053 explain_string_buffer_puts(sb, ", serv_addr = "); 00054 explain_buffer_sockaddr(sb, serv_addr, serv_addr_size); 00055 explain_string_buffer_printf 00056 ( 00057 sb, 00058 ", serv_addr_size = %d)", 00059 serv_addr_size 00060 ); 00061 } 00062 00063 00064 static void 00065 explain_buffer_errno_connect_explanation(explain_string_buffer_t *sb, 00066 int errnum, int fildes, const struct sockaddr *serv_addr, 00067 int serv_addr_size) 00068 { 00069 /* 00070 * http://www.opengroup.org/onlinepubs/009695399/functions/connect.html 00071 */ 00072 (void)serv_addr_size; 00073 switch (errnum) 00074 { 00075 case EACCES: 00076 if (serv_addr->sa_family == AF_UNIX) 00077 { 00078 const struct sockaddr_un *saddr; 00079 explain_final_t final_component; 00080 00081 saddr = (const struct sockaddr_un *)serv_addr; 00082 explain_final_init(&final_component); 00083 final_component.want_to_write = 1; 00084 final_component.must_be_a_st_mode = 1; 00085 final_component.st_mode = S_IFSOCK; 00086 final_component.path_max = sizeof(saddr->sun_path) - 1; 00087 explain_buffer_eacces 00088 ( 00089 sb, 00090 saddr->sun_path, 00091 "sock_addr", 00092 &final_component 00093 ); 00094 break; 00095 } 00096 /* fall through... */ 00097 00098 case EPERM: 00099 explain_buffer_gettext 00100 ( 00101 sb, 00102 /* 00103 * xgettext: This message is used to explain an EPERM error 00104 * reported by the connect(2) system call, in the case where 00105 * the process tried to connect to a broadcast address 00106 * without having the socket broadcast flag enabled; or, the 00107 * connection request failed because of a local firewall 00108 * rule 00109 */ 00110 i18n("the process tried to connect to a broadcast address " 00111 "without having the socket broadcast flag enabled; or, the " 00112 "connection request failed because of a local firewall " 00113 "rule") 00114 ); 00115 break; 00116 00117 case EADDRINUSE: 00118 explain_buffer_eaddrinuse(sb, fildes); 00119 break; 00120 00121 case EAFNOSUPPORT: 00122 explain_buffer_eafnosupport 00123 ( 00124 sb, 00125 fildes, 00126 "fildes", 00127 serv_addr, 00128 "serv_addr" 00129 ); 00130 break; 00131 00132 case EAGAIN: 00133 explain_buffer_gettext 00134 ( 00135 sb, 00136 /* 00137 * xgettext: This message is used to explain an EAGAIN error 00138 * reported by the connect(2) system call, in the case where 00139 * no more free local ports or insufficient entries in the 00140 * routing cache. 00141 */ 00142 i18n("no more free local ports or insufficient entries in the " 00143 "routing cache") 00144 ); 00145 #ifdef __linux__ 00146 if 00147 ( 00148 serv_addr->sa_family == PF_INET 00149 && 00150 explain_option_dialect_specific() 00151 ) 00152 { 00153 explain_string_buffer_puts(sb->footnotes, "; "); 00154 explain_buffer_gettext 00155 ( 00156 sb->footnotes, 00157 /* 00158 * xgettext: This message is used to supplement an 00159 * EAGAIN explanation for the connect(2) system call, on 00160 * Linux the number of local ports can be increased. 00161 */ 00162 i18n("see the net.ipv4.ip_local_port_range sysctl in ip(7) " 00163 "for how to increase the number of local ports") 00164 ); 00165 } 00166 #endif 00167 break; 00168 00169 case EALREADY: 00170 explain_buffer_gettext 00171 ( 00172 sb, 00173 /* 00174 * xgettext: This message is used to explain an EALREADY 00175 * error reported by the connect(2) system call, in the 00176 * case where the socket is non-blocking and a previous 00177 * connection attempt has not yet been completed. 00178 */ 00179 i18n("the socket is non-blocking and a previous connection " 00180 "attempt has not yet been completed") 00181 ); 00182 explain_buffer_software_error(sb); 00183 break; 00184 00185 case EBADF: 00186 explain_buffer_ebadf(sb, fildes, "fildes"); 00187 break; 00188 00189 case ECONNREFUSED: 00190 explain_buffer_gettext 00191 ( 00192 sb, 00193 /* 00194 * xgettext: This message is used to explain an ECONNREFUSED 00195 * error reported by the connect(2) system call, in the 00196 * case where the remote server is accessible but is not 00197 * listening for connections to the given port; or, an 00198 * intervening firewall refused the connection. 00199 */ 00200 i18n("the remote server is accessible but is not listening for " 00201 "connections to the given port; or, an intervening firewall " 00202 "refused the connection") 00203 ); 00204 break; 00205 00206 case EFAULT: 00207 explain_buffer_efault(sb, "sock_addr"); 00208 break; 00209 00210 case EINPROGRESS: 00211 explain_buffer_gettext 00212 ( 00213 sb, 00214 /* 00215 * xgettext: This message is used to explain an EINPROGRESS 00216 * error reported by the connect(2) system call, in the 00217 * case where the socket is non-blocking and the connection 00218 * cannot be completed immediately. 00219 */ 00220 i18n("the socket is non-blocking and the connection cannot " 00221 "be completed immediately") 00222 ); 00223 explain_buffer_software_error(sb); 00224 break; 00225 00226 case EINTR: 00227 explain_buffer_eintr(sb, "connect"); 00228 break; 00229 00230 case EISCONN: 00231 { 00232 struct sockaddr_storage sas; 00233 struct sockaddr *sa; 00234 socklen_t siz; 00235 00236 sa = (struct sockaddr *)&sas; 00237 siz = sizeof(sas); 00238 if (getsockname(fildes, sa, &siz) >= 0) 00239 { 00240 char addr[500]; 00241 explain_string_buffer_t addr_sb; 00242 00243 explain_string_buffer_init(&addr_sb, addr, sizeof(addr)); 00244 explain_buffer_sockaddr(&addr_sb, sa, siz); 00245 explain_string_buffer_printf_gettext 00246 ( 00247 sb, 00248 /* 00249 * xgettext: This message is used to explain an EISCONN 00250 * error reported by the connect(2) system call, in the case 00251 * where the socket is already connected. 00252 * 00253 * %1$s => The network address to which it is connected 00254 */ 00255 i18n("the socket is already connected to %s"), 00256 addr 00257 ); 00258 } 00259 else 00260 { 00261 explain_buffer_gettext 00262 ( 00263 sb, 00264 /* 00265 * xgettext: This message is used to explain an EISCONN 00266 * error reported by the connect(2) system call, in the case 00267 * where the socket is already connected, but the exact 00268 * address cannot be determined. 00269 */ 00270 i18n("the socket is already connected to a network address") 00271 ); 00272 } 00273 explain_buffer_software_error(sb); 00274 } 00275 break; 00276 00277 case ENETUNREACH: 00278 /* FIXME: diagnose more routing table cases */ 00279 explain_buffer_gettext 00280 ( 00281 sb, 00282 /* 00283 * xgettext: This message is used to explain an ENETUNREACH 00284 * error reported by the connect(2) system call, in the case 00285 * where network or host is unreachable. 00286 */ 00287 i18n("network or host is unreachable; sometimes this is a " 00288 "routing issue, sometimes the network is physically " 00289 "disconnected, sometimes a router is turned off, sometimes " 00290 "the host is physically disconnected, sometimes the host is " 00291 "turned off") 00292 ); 00293 break; 00294 00295 case ENOTSOCK: 00296 explain_buffer_enotsock(sb, fildes, "fildes"); 00297 break; 00298 00299 case ETIMEDOUT: 00300 explain_buffer_gettext 00301 ( 00302 sb, 00303 /* 00304 * xgettext: This message is used to explain an ETIMEDOUT 00305 * error reported by the connect(2) system call, in the case 00306 * where the connection attempt took to long. 00307 */ 00308 i18n("the connection attempt took to long; the server may be too " 00309 "busy to accept new connections, or an intervening firewall " 00310 "may be discarding your packets") 00311 ); 00312 break; 00313 00314 default: 00315 explain_buffer_errno_generic(sb, errnum, "connect"); 00316 break; 00317 } 00318 } 00319 00320 00321 void 00322 explain_buffer_errno_connect(explain_string_buffer_t *sb, int errnum, 00323 int fildes, const struct sockaddr *serv_addr, int serv_addr_size) 00324 { 00325 explain_explanation_t exp; 00326 00327 explain_explanation_init(&exp, errnum); 00328 explain_buffer_errno_connect_system_call 00329 ( 00330 &exp.system_call_sb, 00331 errnum, 00332 fildes, 00333 serv_addr, 00334 serv_addr_size 00335 ); 00336 explain_buffer_errno_connect_explanation 00337 ( 00338 &exp.explanation_sb, 00339 errnum, 00340 fildes, 00341 serv_addr, 00342 serv_addr_size 00343 ); 00344 explain_explanation_assemble(&exp, sb); 00345 } 00346 00347 00348 /* vim: set ts=8 sw=4 et : */