libexplain  1.4.D001
libexplain/buffer/errno/bind.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2008-2010, 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/net/if.h>
00021 #include <libexplain/ac/sys/socket.h>
00022 #include <libexplain/ac/sys/stat.h>
00023 #include <libexplain/ac/sys/un.h>
00024 
00025 #include <libexplain/buffer/dac.h>
00026 #include <libexplain/buffer/eacces.h>
00027 #include <libexplain/buffer/eaddrinuse.h>
00028 #include <libexplain/buffer/eafnosupport.h>
00029 #include <libexplain/buffer/ebadf.h>
00030 #include <libexplain/buffer/efault.h>
00031 #include <libexplain/buffer/einval.h>
00032 #include <libexplain/buffer/eloop.h>
00033 #include <libexplain/buffer/enametoolong.h>
00034 #include <libexplain/buffer/enoent.h>
00035 #include <libexplain/buffer/enomem.h>
00036 #include <libexplain/buffer/enotdir.h>
00037 #include <libexplain/buffer/enotsock.h>
00038 #include <libexplain/buffer/erofs.h>
00039 #include <libexplain/buffer/errno/bind.h>
00040 #include <libexplain/buffer/errno/generic.h>
00041 #include <libexplain/buffer/errno/path_resolution.h>
00042 #include <libexplain/buffer/fildes_to_pathname.h>
00043 #include <libexplain/buffer/gettext.h>
00044 #include <libexplain/buffer/pointer.h>
00045 #include <libexplain/buffer/sockaddr.h>
00046 #include <libexplain/explanation.h>
00047 #include <libexplain/fildes_to_address_family.h>
00048 
00049 
00050 static void
00051 explain_buffer_errno_bind_system_call(explain_string_buffer_t *sb,
00052     int errnum, int fildes, const struct sockaddr *sock_addr,
00053     int sock_addr_size)
00054 {
00055     (void)errnum;
00056     explain_string_buffer_printf(sb, "bind(fildes = %d", fildes);
00057     explain_buffer_fildes_to_pathname(sb, fildes);
00058     explain_string_buffer_puts(sb, ", sock_addr = ");
00059     explain_buffer_sockaddr(sb, sock_addr, sock_addr_size);
00060     explain_string_buffer_printf
00061     (
00062         sb,
00063         ", sock_addr_size = %d",
00064         sock_addr_size
00065     );
00066     explain_string_buffer_putc(sb, ')');
00067 }
00068 
00069 
00070 static void
00071 explain_final_sock_init(explain_final_t *fp)
00072 {
00073     explain_final_init(fp);
00074     fp->want_to_create = 1;
00075     fp->want_to_read = 1;
00076     fp->must_be_a_st_mode = 1;
00077     fp->st_mode = S_IFSOCK;
00078 }
00079 
00080 
00081 static void
00082 the_socket_is_already_bound(explain_string_buffer_t *sb, int fildes)
00083 {
00084     struct sockaddr_storage sas;
00085     struct sockaddr *sas_p;
00086     socklen_t       sa_len;
00087 
00088     sas_p = (struct sockaddr *)&sas;
00089     sa_len = sizeof(sas);
00090     if (getsockname(fildes, sas_p, &sa_len) >= 0)
00091     {
00092         char            addr[500];
00093         explain_string_buffer_t addr_sb;
00094 
00095         explain_string_buffer_init(&addr_sb, addr, sizeof(addr));
00096         explain_buffer_sockaddr(&addr_sb, sas_p, sa_len);
00097         explain_string_buffer_printf_gettext
00098         (
00099             sb,
00100             /*
00101              * xgettext: This message is used to explain an EINVAL error
00102              * returned by the bind(2) system call, in the case where
00103              * the socket is already bound to an address.
00104              *
00105              * %1$s => a representation of the struct sockaddr that the
00106              *         socket is already bound to.
00107              */
00108             i18n("the socket is already bound to %s"),
00109             addr
00110         );
00111     }
00112     else
00113     {
00114         explain_buffer_gettext
00115         (
00116             sb,
00117             /*
00118              * xgettext: This message is used to explain an EINVAL
00119              * error returned by the bind(2) system call, in the case
00120              * where the socket is already bound to an address, but the
00121              * address cannot be determined.
00122              */
00123             i18n("the socket is already bound to an address")
00124         );
00125     }
00126 }
00127 
00128 
00129 static void
00130 explain_buffer_errno_bind_explanation(explain_string_buffer_t *sb,
00131     int errnum, int fildes, const struct sockaddr *sock_addr,
00132     int sock_addr_size)
00133 {
00134     /*
00135      * http://www.opengroup.org/onlinepubs/009695399/functions/bind.html
00136      */
00137     (void)sock_addr_size;
00138     switch (errnum)
00139     {
00140     case EACCES:
00141         if (sock_addr->sa_family == AF_UNIX)
00142         {
00143             explain_final_t final_component;
00144             const struct sockaddr_un *saddr;
00145 
00146             saddr = (const struct sockaddr_un *)sock_addr;
00147             explain_final_sock_init(&final_component);
00148             final_component.want_to_write = 1;
00149             final_component.want_to_create = 1;
00150             final_component.must_be_a_st_mode = 1;
00151             final_component.st_mode = S_IFSOCK;
00152             final_component.path_max = sizeof(saddr->sun_path) - 1;
00153             explain_buffer_eacces
00154             (
00155                 sb,
00156                 saddr->sun_path,
00157                 "sock_addr->sun_path",
00158                 &final_component
00159             );
00160         }
00161         else
00162         {
00163             explain_buffer_gettext
00164             (
00165                 sb,
00166                 /*
00167                  * xgettext: This message is used to explain an EACCES
00168                  * error reported by a bind(2) system call, in the case
00169                  * where a privileged port is specific, and the process
00170                  * does not have permission.
00171                  */
00172                 i18n("the network port address is protected")
00173             );
00174             explain_buffer_dac_net_bind_service(sb);
00175         }
00176         break;
00177 
00178     case EADDRINUSE:
00179         if (sock_addr->sa_family == AF_UNIX)
00180         {
00181             explain_buffer_gettext
00182             (
00183                 sb,
00184                 /*
00185                  * xgettext: This message is used when an AF_UNIX socket
00186                  * file already exists when it should not.  While the
00187                  * bind(2) call will create the entry in the file
00188                  * system, the correponding close(2) will not remove it
00189                  * again, the programmer must explicitly unlink(2) it.
00190                  */
00191                 i18n("the socket file already exists, and it should "
00192                 "not; when you are done with AF_UNIX sockets you must "
00193                 "deliberately unlink(2) the socket file, it does not "
00194                 "happen automatically")
00195             );
00196             break;
00197         }
00198         explain_buffer_eaddrinuse(sb, fildes);
00199         break;
00200 
00201     case EBADF:
00202         explain_buffer_ebadf(sb, fildes, "fildes");
00203         break;
00204 
00205     case EAFNOSUPPORT:
00206         explain_buffer_eafnosupport
00207         (
00208             sb,
00209             fildes,
00210             "fildes",
00211             sock_addr,
00212             "sock_addr"
00213         );
00214         break;
00215 
00216     case EINVAL:
00217         if (sock_addr->sa_family == AF_UNIX)
00218         {
00219             if (explain_fildes_to_address_family(fildes) == AF_UNIX)
00220             {
00221                 explain_buffer_einval_too_small
00222                 (
00223                     sb,
00224                     "sock_addr_size",
00225                     sock_addr_size
00226                 );
00227             }
00228             else
00229             {
00230                 explain_buffer_eafnosupport
00231                 (
00232                     sb,
00233                     fildes,
00234                     "fildes",
00235                     sock_addr,
00236                     "sock_addr"
00237                 );
00238             }
00239         }
00240         else
00241         {
00242             the_socket_is_already_bound(sb, fildes);
00243         }
00244         break;
00245 
00246     case ENOTSOCK:
00247         explain_buffer_enotsock(sb, fildes, "fildes");
00248         break;
00249 
00250     case EADDRNOTAVAIL:
00251         /* FIXME: which is it? differentiate between these two cases */
00252         explain_string_buffer_puts
00253         (
00254             sb,
00255             /*
00256              * xgettext: This message is used to explain an EADDRNOTAVAIL
00257              * error reported by a bind(2) system call, in the case where
00258              * the requested network address was not local or a nonexistent
00259              * interface was requested.
00260              */
00261             i18n("the requested network address was not local or a "
00262             "nonexistent interface was requested")
00263         );
00264 
00265 #ifdef SO_BINDTODEVICE
00266         {
00267             char            name[IFNAMSIZ + 1];
00268             socklen_t       namsiz;
00269 
00270             /*
00271              * This is only useful for AF_INET and AF_INET6,
00272              * AF_PACKET is different.
00273              */
00274             namsiz = sizeof(name);
00275             if
00276             (
00277                 !getsockopt(fildes, SOL_SOCKET, SO_BINDTODEVICE, name, &namsiz)
00278             &&
00279                 namsiz
00280             &&
00281                 name[0]
00282             )
00283             {
00284                 explain_string_buffer_puts(sb, " (");
00285                 explain_string_buffer_puts_quoted(sb, name);
00286                 explain_string_buffer_putc(sb, ')');
00287             }
00288         }
00289 #endif
00290         break;
00291 
00292     case EFAULT:
00293         explain_buffer_efault(sb, "sock_addr");
00294         break;
00295 
00296     case ELOOP:
00297         if (sock_addr->sa_family == AF_UNIX)
00298         {
00299             struct sockaddr_un *saddr;
00300             explain_final_t final_component;
00301 
00302             explain_final_sock_init(&final_component);
00303             saddr = (struct sockaddr_un *)sock_addr;
00304 
00305             explain_buffer_eloop
00306             (
00307                 sb,
00308                 saddr->sun_path,
00309                 "sock_addr->sun_path",
00310                 &final_component
00311             );
00312         }
00313         break;
00314 
00315     case ENAMETOOLONG:
00316         if (sock_addr->sa_family == AF_UNIX)
00317         {
00318             struct sockaddr_un *saddr;
00319             explain_final_t final_component;
00320 
00321             explain_final_sock_init(&final_component);
00322             saddr = (struct sockaddr_un *)sock_addr;
00323 
00324             explain_buffer_enametoolong
00325             (
00326                 sb,
00327                 saddr->sun_path,
00328                 "sock_addr->sun_path",
00329                 &final_component
00330             );
00331         }
00332         break;
00333 
00334     case ENOENT:
00335         if (sock_addr->sa_family == AF_UNIX)
00336         {
00337             struct sockaddr_un *saddr;
00338             explain_final_t final_component;
00339 
00340             explain_final_sock_init(&final_component);
00341             saddr = (struct sockaddr_un *)sock_addr;
00342 
00343             explain_buffer_enoent
00344             (
00345                 sb,
00346                 saddr->sun_path,
00347                 "sock_addr->sun_path",
00348                 &final_component
00349             );
00350         }
00351         break;
00352 
00353     case ENOMEM:
00354         explain_buffer_enomem_kernel(sb);
00355         break;
00356 
00357     case ENOTDIR:
00358         if (sock_addr->sa_family == AF_UNIX)
00359         {
00360             struct sockaddr_un *saddr;
00361             explain_final_t final_component;
00362 
00363             explain_final_sock_init(&final_component);
00364             saddr = (struct sockaddr_un *)sock_addr;
00365 
00366             explain_buffer_enotdir
00367             (
00368                 sb,
00369                 saddr->sun_path,
00370                 "sock_addr->sun_path",
00371                 &final_component
00372             );
00373         }
00374         break;
00375 
00376     case EROFS:
00377         if (sock_addr->sa_family == AF_UNIX)
00378         {
00379             struct sockaddr_un *saddr;
00380 
00381             saddr = (struct sockaddr_un *)sock_addr;
00382             explain_buffer_erofs(sb, saddr->sun_path, "sock_addr->sun_path");
00383         }
00384         break;
00385 
00386     default:
00387         explain_buffer_errno_generic(sb, errnum, "bind");
00388         break;
00389     }
00390 }
00391 
00392 
00393 void
00394 explain_buffer_errno_bind(explain_string_buffer_t *sb, int errnum,
00395     int fildes, const struct sockaddr *sock_addr, int sock_addr_size)
00396 {
00397     explain_explanation_t exp;
00398 
00399     explain_explanation_init(&exp, errnum);
00400     explain_buffer_errno_bind_system_call
00401     (
00402         &exp.system_call_sb,
00403         errnum,
00404         fildes,
00405         sock_addr,
00406         sock_addr_size
00407     );
00408     explain_buffer_errno_bind_explanation
00409     (
00410         &exp.explanation_sb,
00411         errnum,
00412         fildes,
00413         sock_addr,
00414         sock_addr_size
00415     );
00416     explain_explanation_assemble(&exp, sb);
00417 }
00418 
00419 
00420 /* vim: set ts=8 sw=4 et : */