Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 891276 Details for
Bug 1093162
undefined behavior in mountd causes segfault when built by newer gcc compilers
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
add_name function
client.c (text/plain), 16.47 KB, created by
Jeff Layton
on 2014-04-30 19:03:31 UTC
(
hide
)
Description:
add_name function
Filename:
MIME Type:
Creator:
Jeff Layton
Created:
2014-04-30 19:03:31 UTC
Size:
16.47 KB
patch
obsolete
>/* > * support/export/client.c > * > * Maintain list of nfsd clients. > * > * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> > */ > >#ifdef HAVE_CONFIG_H >#include <config.h> >#endif > >#include <sys/types.h> >#include <netinet/in.h> >#include <arpa/inet.h> >#include <stdlib.h> >#include <string.h> >#include <ctype.h> >#include <netdb.h> >#include <errno.h> > >#include "sockaddr.h" >#include "misc.h" >#include "nfslib.h" >#include "exportfs.h" > >/* netgroup stuff never seems to be defined in any header file. Linux is > * not alone in this. > */ >#if !defined(__GLIBC__) || __GLIBC__ < 2 >extern int innetgr(char *netgr, char *host, char *, char *); >#endif > >static char *add_name(char *old, const char *add); > >nfs_client *clientlist[MCL_MAXTYPES] = { NULL, }; > > >static void >init_addrlist(nfs_client *clp, const struct addrinfo *ai) >{ > int i; > > if (ai == NULL) > return; > > for (i = 0; (ai != NULL) && (i < NFSCLNT_ADDRMAX); i++) { > set_addrlist(clp, i, ai->ai_addr); > ai = ai->ai_next; > } > > clp->m_naddr = i; >} > >static void >client_free(nfs_client *clp) >{ > free(clp->m_hostname); > free(clp); >} > >static int >init_netmask4(nfs_client *clp, const char *slash) >{ > struct sockaddr_in sin = { > .sin_family = AF_INET, > }; > uint32_t shift; > > /* > * Decide what kind of netmask was specified. If there's > * no '/' present, assume the netmask is all ones. If > * there is a '/' and at least one '.', look for a spelled- > * out netmask. Otherwise, assume it was a prefixlen. > */ > if (slash == NULL) > shift = 0; > else { > unsigned long prefixlen; > > if (strchr(slash + 1, '.') != NULL) { > if (inet_pton(AF_INET, slash + 1, > &sin.sin_addr.s_addr) == 0) > goto out_badmask; > set_addrlist_in(clp, 1, &sin); > return 1; > } else { > char *endptr; > > prefixlen = strtoul(slash + 1, &endptr, 10); > if (*endptr != '\0' && prefixlen != ULONG_MAX && > errno != ERANGE) > goto out_badprefix; > } > if (prefixlen > 32) > goto out_badprefix; > shift = 32 - (uint32_t)prefixlen; > } > > /* > * Now construct the full netmask bitmask in a sockaddr_in, > * and plant it in the nfs_client record. > */ > sin.sin_addr.s_addr = htonl((uint32_t)~0 << shift); > set_addrlist_in(clp, 1, &sin); > > return 1; > >out_badmask: > xlog(L_ERROR, "Invalid netmask `%s' for %s", slash + 1, clp->m_hostname); > return 0; > >out_badprefix: > xlog(L_ERROR, "Invalid prefix `%s' for %s", slash + 1, clp->m_hostname); > return 0; >} > >#ifdef IPV6_SUPPORTED >static int >init_netmask6(nfs_client *clp, const char *slash) >{ > struct sockaddr_in6 sin6 = { > .sin6_family = AF_INET6, > }; > unsigned long prefixlen; > uint32_t shift; > int i; > > /* > * Decide what kind of netmask was specified. If there's > * no '/' present, assume the netmask is all ones. If > * there is a '/' and at least one ':', look for a spelled- > * out netmask. Otherwise, assume it was a prefixlen. > */ > if (slash == NULL) > prefixlen = 128; > else { > if (strchr(slash + 1, ':') != NULL) { > if (!inet_pton(AF_INET6, slash + 1, &sin6.sin6_addr)) > goto out_badmask; > set_addrlist_in6(clp, 1, &sin6); > return 1; > } else { > char *endptr; > > prefixlen = strtoul(slash + 1, &endptr, 10); > if (*endptr != '\0' && prefixlen != ULONG_MAX && > errno != ERANGE) > goto out_badprefix; > } > if (prefixlen > 128) > goto out_badprefix; > } > > /* > * Now construct the full netmask bitmask in a sockaddr_in6, > * and plant it in the nfs_client record. > */ > for (i = 0; prefixlen > 32; i++) { > sin6.sin6_addr.s6_addr32[i] = 0xffffffff; > prefixlen -= 32; > } > shift = 32 - (uint32_t)prefixlen; > sin6.sin6_addr.s6_addr32[i] = htonl((uint32_t)~0 << shift); > set_addrlist_in6(clp, 1, &sin6); > > return 1; > >out_badmask: > xlog(L_ERROR, "Invalid netmask `%s' for %s", slash + 1, clp->m_hostname); > return 0; > >out_badprefix: > xlog(L_ERROR, "Invalid prefix `%s' for %s", slash + 1, clp->m_hostname); > return 0; >} >#else /* IPV6_SUPPORTED */ >static int >init_netmask6(nfs_client *UNUSED(clp), const char *UNUSED(slash)) >{ > return 0; >} >#endif /* IPV6_SUPPORTED */ > >/* > * Parse the network mask for M_SUBNETWORK type clients. > * > * Return TRUE if successful, or FALSE if some error occurred. > */ >static int >init_subnetwork(nfs_client *clp) >{ > struct addrinfo *ai; > sa_family_t family; > int result = 0; > char *slash; > > slash = strchr(clp->m_hostname, '/'); > if (slash != NULL) { > *slash = '\0'; > ai = host_pton(clp->m_hostname); > *slash = '/'; > } else > ai = host_pton(clp->m_hostname); > if (ai == NULL) { > xlog(L_ERROR, "Invalid IP address %s", clp->m_hostname); > return result; > } > > set_addrlist(clp, 0, ai->ai_addr); > family = ai->ai_addr->sa_family; > > freeaddrinfo(ai); > > switch (family) { > case AF_INET: > result = init_netmask4(clp, slash); > break; > case AF_INET6: > result = init_netmask6(clp, slash); > break; > default: > xlog(L_ERROR, "Unsupported address family for %s", > clp->m_hostname); > } > > return result; >} > >static int >client_init(nfs_client *clp, const char *hname, const struct addrinfo *ai) >{ > clp->m_hostname = strdup(hname); > if (clp->m_hostname == NULL) > return 0; > > clp->m_exported = 0; > clp->m_count = 0; > clp->m_naddr = 0; > > if (clp->m_type == MCL_SUBNETWORK) > return init_subnetwork(clp); > > init_addrlist(clp, ai); > return 1; >} > >static void >client_add(nfs_client *clp) >{ > nfs_client **cpp; > > cpp = &clientlist[clp->m_type]; > while (*cpp != NULL) > cpp = &((*cpp)->m_next); > clp->m_next = NULL; > *cpp = clp; >} > >/** > * client_lookup - look for @hname in our list of cached nfs_clients > * @hname: '\0'-terminated ASCII string containing hostname to look for > * @canonical: if set, @hname is known to be canonical DNS name > * > * Returns pointer to a matching or freshly created nfs_client. NULL > * is returned if some problem occurs. > */ >nfs_client * >client_lookup(char *hname, int canonical) >{ > nfs_client *clp = NULL; > int htype; > struct addrinfo *ai = NULL; > > htype = client_gettype(hname); > > if (htype == MCL_FQDN && !canonical) { > ai = host_addrinfo(hname); > if (!ai) { > xlog(L_ERROR, "Failed to resolve %s", hname); > goto out; > } > hname = ai->ai_canonname; > > for (clp = clientlist[htype]; clp; clp = clp->m_next) > if (client_check(clp, ai)) > break; > } else { > for (clp = clientlist[htype]; clp; clp = clp->m_next) { > if (strcasecmp(hname, clp->m_hostname)==0) > break; > } > } > > if (clp == NULL) { > clp = calloc(1, sizeof(*clp)); > if (clp == NULL) > goto out; > clp->m_type = htype; > if (!client_init(clp, hname, NULL)) { > client_free(clp); > clp = NULL; > goto out; > } > client_add(clp); > } > > if (htype == MCL_FQDN && clp->m_naddr == 0) > init_addrlist(clp, ai); > >out: > freeaddrinfo(ai); > return clp; >} > >/** > * client_dup - create a copy of an nfs_client > * @clp: pointer to nfs_client to copy > * @ai: pointer to addrinfo used to initialize the new client's addrlist > * > * Returns a dynamically allocated nfs_client if successful, or > * NULL if some problem occurs. Caller must free the returned > * nfs_client with free(3). > */ >nfs_client * >client_dup(const nfs_client *clp, const struct addrinfo *ai) >{ > nfs_client *new; > > new = (nfs_client *)malloc(sizeof(*new)); > if (new == NULL) > return NULL; > memcpy(new, clp, sizeof(*new)); > new->m_type = MCL_FQDN; > new->m_hostname = NULL; > > if (!client_init(new, ai->ai_canonname, ai)) { > client_free(new); > return NULL; > } > client_add(new); > return new; >} > >/** > * client_release - drop a reference to an nfs_client record > * > */ >void >client_release(nfs_client *clp) >{ > if (clp->m_count <= 0) > xlog(L_FATAL, "client_free: m_count <= 0!"); > clp->m_count--; >} > >/** > * client_freeall - deallocate all nfs_client records > * > */ >void >client_freeall(void) >{ > nfs_client *clp, **head; > int i; > > for (i = 0; i < MCL_MAXTYPES; i++) { > head = clientlist + i; > while (*head) { > *head = (clp = *head)->m_next; > client_free(clp); > } > } >} > >/** > * client_resolve - look up an IP address > * @sap: pointer to socket address to resolve > * > * Returns an addrinfo structure, or NULL if some problem occurred. > * Caller must free the result with freeaddrinfo(3). > */ >struct addrinfo * >client_resolve(const struct sockaddr *sap) >{ > struct addrinfo *ai = NULL; > > if (clientlist[MCL_WILDCARD] || clientlist[MCL_NETGROUP]) > ai = host_reliable_addrinfo(sap); > if (ai == NULL) > ai = host_numeric_addrinfo(sap); > > return ai; >} > >/** > * client_compose - Make a list of cached hostnames that match an IP address > * @ai: pointer to addrinfo containing IP address information to match > * > * Gather all known client hostnames that match the IP address, and sort > * the result into a comma-separated list. > * > * Returns a '\0'-terminated ASCII string containing a comma-separated > * sorted list of client hostnames, or NULL if no client records matched > * the IP address or memory could not be allocated. Caller must free the > * returned string with free(3). > */ >char * >client_compose(const struct addrinfo *ai) >{ > char *name = NULL; > int i; > > for (i = 0 ; i < MCL_MAXTYPES; i++) { > nfs_client *clp; > for (clp = clientlist[i]; clp ; clp = clp->m_next) { > if (!client_check(clp, ai)) > continue; > name = add_name(name, clp->m_hostname); > } > } > return name; >} > >/** > * client_member - check if @name is contained in the list @client > * @client: '\0'-terminated ASCII string containing > * comma-separated list of hostnames > * @name: '\0'-terminated ASCII string containing hostname to look for > * > * Returns 1 if @name was found in @client, otherwise zero is returned. > */ >int >client_member(const char *client, const char *name) >{ > size_t l = strlen(name); > > while (*client) { > if (strncmp(client, name, l) == 0 && > (client[l] == ',' || client[l] == '\0')) > return 1; > client = strchr(client, ','); > if (client == NULL) > return 0; > client++; > } > return 0; >} > >static int >name_cmp(const char *a, const char *b) >{ > /* compare strings a and b, but only upto ',' in a */ > while (*a && *b && *a != ',' && *a == *b) > a++, b++; > if (!*b && (!*a || *a == ',')) > return 0; > if (!*b) return 1; > if (!*a || *a == ',') return -1; > return *a - *b; >} > >static char * >add_name(char *old, const char *add) >{ > size_t len = strlen(add) + 2; > char *new; > char *cp; > if (old) len += strlen(old); > > new = malloc(len); > if (!new) { > free(old); > return NULL; > } > cp = old; > while (cp && *cp && name_cmp(cp, add) < 0) { > /* step cp forward over a name */ > char *e = strchr(cp, ','); > if (e) > cp = e+1; > else > cp = cp + strlen(cp); > } > strncpy(new, old, cp-old); > new[cp-old] = 0; > if (cp != old && !*cp) > strcat(new, ","); > strcat(new, add); > if (cp && *cp) { > strcat(new, ","); > strcat(new, cp); > } > free(old); > return new; >} > >/* > * Check each address listed in @ai against each address > * stored in @clp. Return 1 if a match is found, otherwise > * zero. > */ >static int >check_fqdn(const nfs_client *clp, const struct addrinfo *ai) >{ > int i; > > for (; ai; ai = ai->ai_next) > for (i = 0; i < clp->m_naddr; i++) > if (nfs_compare_sockaddr(ai->ai_addr, > get_addrlist(clp, i))) > return 1; > > return 0; >} > >static _Bool >mask_match(const uint32_t a, const uint32_t b, const uint32_t m) >{ > return ((a ^ b) & m) == 0; >} > >static int >check_subnet_v4(const struct sockaddr_in *address, > const struct sockaddr_in *mask, const struct addrinfo *ai) >{ > for (; ai; ai = ai->ai_next) { > struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr; > > if (sin->sin_family != AF_INET) > continue; > > if (mask_match(address->sin_addr.s_addr, > sin->sin_addr.s_addr, > mask->sin_addr.s_addr)) > return 1; > } > return 0; >} > >#ifdef IPV6_SUPPORTED >static int >check_subnet_v6(const struct sockaddr_in6 *address, > const struct sockaddr_in6 *mask, const struct addrinfo *ai) >{ > for (; ai; ai = ai->ai_next) { > struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr; > > if (sin6->sin6_family != AF_INET6) > continue; > > if (mask_match(address->sin6_addr.s6_addr32[0], > sin6->sin6_addr.s6_addr32[0], > mask->sin6_addr.s6_addr32[0]) && > mask_match(address->sin6_addr.s6_addr32[1], > sin6->sin6_addr.s6_addr32[1], > mask->sin6_addr.s6_addr32[1]) && > mask_match(address->sin6_addr.s6_addr32[2], > sin6->sin6_addr.s6_addr32[2], > mask->sin6_addr.s6_addr32[2]) && > mask_match(address->sin6_addr.s6_addr32[3], > sin6->sin6_addr.s6_addr32[3], > mask->sin6_addr.s6_addr32[3])) > return 1; > } > return 0; >} >#else /* !IPV6_SUPPORTED */ >static int >check_subnet_v6(const struct sockaddr_in6 *UNUSED(address), > const struct sockaddr_in6 *UNUSED(mask), > const struct addrinfo *UNUSED(ai)) >{ > return 0; >} >#endif /* !IPV6_SUPPORTED */ > >/* > * Check each address listed in @ai against the subnetwork or > * host address stored in @clp. Return 1 if an address in @hp > * matches the host address stored in @clp, otherwise zero. > */ >static int >check_subnetwork(const nfs_client *clp, const struct addrinfo *ai) >{ > switch (get_addrlist(clp, 0)->sa_family) { > case AF_INET: > return check_subnet_v4(get_addrlist_in(clp, 0), > get_addrlist_in(clp, 1), ai); > case AF_INET6: > return check_subnet_v6(get_addrlist_in6(clp, 0), > get_addrlist_in6(clp, 1), ai); > } > > return 0; >} > >/* > * Check if a wildcard nfs_client record matches the canonical name > * or the aliases of a host. Return 1 if a match is found, otherwise > * zero. > */ >static int >check_wildcard(const nfs_client *clp, const struct addrinfo *ai) >{ > char *cname = clp->m_hostname; > char *hname = ai->ai_canonname; > struct hostent *hp; > char **ap; > > if (wildmat(hname, cname)) > return 1; > > /* See if hname aliases listed in /etc/hosts or nis[+] > * match the requested wildcard */ > hp = gethostbyname(hname); > if (hp != NULL) { > for (ap = hp->h_aliases; *ap; ap++) > if (wildmat(*ap, cname)) > return 1; > } > > return 0; >} > >/* > * Check if @ai's hostname or aliases fall in a given netgroup. > * Return 1 if @ai represents a host in the netgroup, otherwise > * zero. > */ >#ifdef HAVE_INNETGR >static int >check_netgroup(const nfs_client *clp, const struct addrinfo *ai) >{ > const char *netgroup = clp->m_hostname + 1; > struct addrinfo *tmp = NULL; > struct hostent *hp; > char *dot, *hname; > int i, match; > > match = 0; > > hname = strdup(ai->ai_canonname); > if (hname == NULL) { > xlog(D_GENERAL, "%s: no memory for strdup", __func__); > goto out; > } > > /* First, try to match the hostname without > * splitting off the domain */ > if (innetgr(netgroup, hname, NULL, NULL)) { > match = 1; > goto out; > } > > /* See if hname aliases listed in /etc/hosts or nis[+] > * match the requested netgroup */ > hp = gethostbyname(hname); > if (hp != NULL) { > for (i = 0; hp->h_aliases[i]; i++) > if (innetgr(netgroup, hp->h_aliases[i], NULL, NULL)) { > match = 1; > goto out; > } > } > > /* If hname happens to be an IP address, convert it > * to a the canonical DNS name bound to this address. */ > tmp = host_pton(hname); > if (tmp != NULL) { > char *cname = host_canonname(tmp->ai_addr); > freeaddrinfo(tmp); > > /* The resulting FQDN may be in our netgroup. */ > if (cname != NULL) { > free(hname); > hname = cname; > if (innetgr(netgroup, hname, NULL, NULL)) { > match = 1; > goto out; > } > } > } > > /* Okay, strip off the domain (if we have one) */ > dot = strchr(hname, '.'); > if (dot == NULL) > goto out; > > *dot = '\0'; > match = innetgr(netgroup, hname, NULL, NULL); > >out: > free(hname); > return match; >} >#else /* !HAVE_INNETGR */ >static int >check_netgroup(__attribute__((unused)) const nfs_client *clp, > __attribute__((unused)) const struct addrinfo *ai) >{ > return 0; >} >#endif /* !HAVE_INNETGR */ > >/** > * client_check - check if IP address information matches a cached nfs_client > * @clp: pointer to a cached nfs_client record > * @ai: pointer to addrinfo to compare it with > * > * Returns 1 if the address information matches the cached nfs_client, > * otherwise zero. > */ >int >client_check(const nfs_client *clp, const struct addrinfo *ai) >{ > switch (clp->m_type) { > case MCL_FQDN: > return check_fqdn(clp, ai); > case MCL_SUBNETWORK: > return check_subnetwork(clp, ai); > case MCL_WILDCARD: > return check_wildcard(clp, ai); > case MCL_NETGROUP: > return check_netgroup(clp, ai); > case MCL_ANONYMOUS: > return 1; > case MCL_GSS: > return 0; > default: > xlog(D_GENERAL, "%s: unrecognized client type: %d", > __func__, clp->m_type); > } > > return 0; >} > >/** > * client_gettype - determine type of nfs_client given an identifier > * @ident: '\0'-terminated ASCII string containing a client identifier > * > * Returns the type of nfs_client record that would be used for > * this client. > */ >int >client_gettype(char *ident) >{ > char *sp; > > if (ident[0] == '\0' || strcmp(ident, "*")==0) > return MCL_ANONYMOUS; > if (strncmp(ident, "gss/", 4) == 0) > return MCL_GSS; > if (ident[0] == '@') { >#ifndef HAVE_INNETGR > xlog(L_WARNING, "netgroup support not compiled in"); >#endif > return MCL_NETGROUP; > } > for (sp = ident; *sp; sp++) { > if (*sp == '*' || *sp == '?' || *sp == '[') > return MCL_WILDCARD; > if (*sp == '/') > return MCL_SUBNETWORK; > if (*sp == '\\' && sp[1]) > sp++; > } > > return MCL_FQDN; >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 1093162
: 891276