Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  ip.c

  Sprache: C
 

/*-------------------------------------------------------------------------
 *
 * ip.c
 *   IPv6-aware network access.
 *
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *   src/common/ip.c
 *
 * This file and the IPV6 implementation were initially provided by
 * Nigel Kukard <nkukard@lbsd.net>, Linux Based Systems Design
 * http://www.lbsd.net.
 *
 *-------------------------------------------------------------------------
 */


#ifndef FRONTEND
#include "postgres.h"
#else
#include "postgres_fe.h"
#endif

#include <unistd.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/file.h>

#include "common/ip.h"



static int getaddrinfo_unix(const char *path,
        const struct addrinfo *hintsp,
        struct addrinfo **result);

static int getnameinfo_unix(const struct sockaddr_un *sa, int salen,
        char *node, int nodelen,
        char *service, int servicelen,
        int flags);


/*
 * pg_getaddrinfo_all - get address info for Unix, IPv4 and IPv6 sockets
 */

int
pg_getaddrinfo_all(const char *hostname, const char *servname,
       const struct addrinfo *hintp, struct addrinfo **result)
{
 int   rc;

 /* not all versions of getaddrinfo() zero *result on failure */
 *result = NULL;

 if (hintp->ai_family == AF_UNIX)
  return getaddrinfo_unix(servname, hintp, result);

 /* NULL has special meaning to getaddrinfo(). */
 rc = getaddrinfo((!hostname || hostname[0] == '\0') ? NULL : hostname,
      servname, hintp, result);

 return rc;
}


/*
 * pg_freeaddrinfo_all - free addrinfo structures for IPv4, IPv6, or Unix
 *
 * Note: the ai_family field of the original hint structure must be passed
 * so that we can tell whether the addrinfo struct was built by the system's
 * getaddrinfo() routine or our own getaddrinfo_unix() routine.  Some versions
 * of getaddrinfo() might be willing to return AF_UNIX addresses, so it's
 * not safe to look at ai_family in the addrinfo itself.
 */

void
pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
{
 if (hint_ai_family == AF_UNIX)
 {
  /* struct was built by getaddrinfo_unix (see pg_getaddrinfo_all) */
  while (ai != NULL)
  {
   struct addrinfo *p = ai;

   ai = ai->ai_next;
   free(p->ai_addr);
   free(p);
  }
 }
 else
 {
  /* struct was built by getaddrinfo() */
  if (ai != NULL)
   freeaddrinfo(ai);
 }
}


/*
 * pg_getnameinfo_all - get name info for Unix, IPv4 and IPv6 sockets
 *
 * The API of this routine differs from the standard getnameinfo() definition
 * in two ways: first, the addr parameter is declared as sockaddr_storage
 * rather than struct sockaddr, and second, the node and service fields are
 * guaranteed to be filled with something even on failure return.
 */

int
pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen,
       char *node, int nodelen,
       char *service, int servicelen,
       int flags)
{
 int   rc;

 if (addr && addr->ss_family == AF_UNIX)
  rc = getnameinfo_unix((const struct sockaddr_un *) addr, salen,
         node, nodelen,
         service, servicelen,
         flags);
 else
  rc = getnameinfo((const struct sockaddr *) addr, salen,
       node, nodelen,
       service, servicelen,
       flags);

 if (rc != 0)
 {
  if (node)
   strlcpy(node, "???", nodelen);
  if (service)
   strlcpy(service, "???", servicelen);
 }

 return rc;
}


/* -------
 * getaddrinfo_unix - get unix socket info using IPv6-compatible API
 *
 * Bugs: only one addrinfo is set even though hintsp is NULL or
 *    ai_socktype is 0
 *    AI_CANONNAME is not supported.
 * -------
 */

static int
getaddrinfo_unix(const char *path, const struct addrinfo *hintsp,
     struct addrinfo **result)
{
 struct addrinfo hints = {0};
 struct addrinfo *aip;
 struct sockaddr_un *unp;

 *result = NULL;

 if (strlen(path) >= sizeof(unp->sun_path))
  return EAI_FAIL;

 if (hintsp == NULL)
 {
  hints.ai_family = AF_UNIX;
  hints.ai_socktype = SOCK_STREAM;
 }
 else
  memcpy(&hints, hintsp, sizeof(hints));

 if (hints.ai_socktype == 0)
  hints.ai_socktype = SOCK_STREAM;

 if (hints.ai_family != AF_UNIX)
 {
  /* shouldn't have been called */
  return EAI_FAIL;
 }

 aip = calloc(1sizeof(struct addrinfo));
 if (aip == NULL)
  return EAI_MEMORY;

 unp = calloc(1sizeof(struct sockaddr_un));
 if (unp == NULL)
 {
  free(aip);
  return EAI_MEMORY;
 }

 aip->ai_family = AF_UNIX;
 aip->ai_socktype = hints.ai_socktype;
 aip->ai_protocol = hints.ai_protocol;
 aip->ai_next = NULL;
 aip->ai_canonname = NULL;
 *result = aip;

 unp->sun_family = AF_UNIX;
 aip->ai_addr = (struct sockaddr *) unp;
 aip->ai_addrlen = sizeof(struct sockaddr_un);

 strcpy(unp->sun_path, path);

 /*
  * If the supplied path starts with @, replace that with a zero byte for
  * the internal representation.  In that mode, the entire sun_path is the
  * address, including trailing zero bytes.  But we set the address length
  * to only include the length of the original string.  That way the
  * trailing zero bytes won't show up in any network or socket lists of the
  * operating system.  This is just a convention, also followed by other
  * packages.
 */

 if (path[0] == '@')
 {
  unp->sun_path[0] = '\0';
  aip->ai_addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(path);
 }

 return 0;
}

/*
 * Convert an address to a hostname.
 */

static int
getnameinfo_unix(const struct sockaddr_un *sa, int salen,
     char *node, int nodelen,
     char *service, int servicelen,
     int flags)
{
 int   ret;

 /* Invalid arguments. */
 if (sa == NULL || sa->sun_family != AF_UNIX ||
  (node == NULL && service == NULL))
  return EAI_FAIL;

 if (node)
 {
  ret = snprintf(node, nodelen, "%s""[local]");
  if (ret < 0 || ret >= nodelen)
   return EAI_MEMORY;
 }

 if (service)
 {
  /*
   * Check whether it looks like an abstract socket, but it could also
   * just be an empty string.
 */

  if (sa->sun_path[0] == '\0' && sa->sun_path[1] != '\0')
   ret = snprintf(service, servicelen, "@%s", sa->sun_path + 1);
  else
   ret = snprintf(service, servicelen, "%s", sa->sun_path);
  if (ret < 0 || ret >= servicelen)
   return EAI_MEMORY;
 }

 return 0;
}

Messung V0.5 in Prozent
C=80 H=93 G=86

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-08-09) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=738142