1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #include <sys/types.h>
  27 #include <sys/ksynch.h>
  28 #include <sys/errno.h>
  29 #include <sys/debug.h>
  30 #include <sys/cmn_err.h>
  31 #include <sys/kmem.h>
  32 #include <sys/errno.h>
  33 
  34 #ifdef _SunOS_2_6
  35 /*
  36  * on 2.6 both dki_lock.h and rpc/types.h define bool_t so we
  37  * define enum_t here as it is all we need from rpc/types.h
  38  * anyway and make it look like we included it. Yuck.
  39  */
  40 #define _RPC_TYPES_H
  41 typedef int enum_t;
  42 #else
  43 #ifndef DS_DDICT
  44 #include <rpc/types.h>
  45 #endif
  46 #endif /* _SunOS_2_6 */
  47 
  48 #include <sys/nsc_thread.h>
  49 #include <sys/nsctl/nsctl.h>
  50 #include "rdc_io.h"
  51 #include "rdc_ioctl.h"
  52 #include "rdc_prot.h"
  53 
  54 /*
  55  * Initialize a netbuf suitable for
  56  * describing an address
  57  */
  58 
  59 void
  60 init_rdc_netbuf(struct netbuf *nbuf)
  61 {
  62         nbuf->buf = kmem_zalloc(RDC_MAXADDR, KM_SLEEP);
  63         nbuf->maxlen = RDC_MAXADDR;
  64         nbuf->len = 0;
  65 }
  66 
  67 /*
  68  * Free a netbuf
  69  */
  70 
  71 void
  72 free_rdc_netbuf(struct netbuf *nbuf)
  73 {
  74         if (!(nbuf) || !(nbuf->buf)) {
  75 #ifdef DEBUG
  76                 cmn_err(CE_PANIC, "Null netbuf in free_rdc_netbuf");
  77 #endif
  78                 return;
  79         }
  80         kmem_free(nbuf->buf, nbuf->maxlen);
  81         nbuf->buf = NULL;
  82         nbuf->maxlen = 0;
  83         nbuf->len = 0;
  84 }
  85 
  86 
  87 /*
  88  * Duplicate a netbuf, must be followed by a free_rdc_netbuf().
  89  */
  90 void
  91 dup_rdc_netbuf(const struct netbuf *from, struct netbuf *to)
  92 {
  93         init_rdc_netbuf(to);
  94         to->len = from->len;
  95 
  96         if (from->len > to->maxlen) {
  97                 cmn_err(CE_WARN, "!dup_rdc_netbuf: from->len %d, to->maxlen %d",
  98                     from->len, to->maxlen);
  99         }
 100 
 101         bcopy(from->buf, to->buf, (size_t)from->len);
 102 }
 103 
 104 
 105 #ifdef DEBUG
 106 void
 107 rdc_print_svinfo(rdc_srv_t *svp, char *str)
 108 {
 109         int i;
 110 
 111         if (svp == NULL)
 112                 return;
 113 
 114         cmn_err(CE_NOTE, "!rdc %s servinfo: %p\n", str, (void *) svp);
 115 
 116         if (svp->ri_knconf != NULL) {
 117                 cmn_err(CE_NOTE, "!knconf: semantics %d",
 118                     svp->ri_knconf->knc_semantics);
 119                 cmn_err(CE_NOTE, "!     protofmly %s",
 120                     svp->ri_knconf->knc_protofmly);
 121                 cmn_err(CE_NOTE, "!     proto     %s",
 122                     svp->ri_knconf->knc_proto);
 123                 cmn_err(CE_NOTE, "!     rdev      %lx",
 124                     svp->ri_knconf->knc_rdev);
 125         }
 126 
 127         for (i = 0; i < svp->ri_addr.len; i++)
 128                 printf("%u ", svp->ri_addr.buf[i]);
 129 
 130         cmn_err(CE_NOTE, "!\naddr:      len %d buf %p\n",
 131             svp->ri_addr.len, (void *) svp->ri_addr.buf);
 132         cmn_err(CE_NOTE, "!host:        %s\n", svp->ri_hostname);
 133 }
 134 #endif /* DEBUG */
 135 
 136 /*
 137  * Initialize an rdc servinfo
 138  * Contains all the protocol we need to do a client rpc
 139  * A chain of rdc_srv_t indicates a one to many
 140  */
 141 
 142 rdc_srv_t *
 143 rdc_create_svinfo(char *host, struct netbuf *svaddr, struct knetconfig *conf)
 144 {
 145         rdc_srv_t *nvp;
 146         int hlen = strlen(host) + 1;
 147 
 148         if (conf == NULL) {
 149                 return (NULL);
 150         }
 151 
 152         if (host == NULL) {
 153                 return (NULL);
 154         }
 155 
 156         nvp = kmem_zalloc(sizeof (*nvp), KM_SLEEP);
 157         nvp->ri_knconf = kmem_alloc(sizeof (*nvp->ri_knconf), KM_SLEEP);
 158         nvp->ri_hostname = kmem_zalloc(hlen, KM_SLEEP);
 159 
 160         if (nvp == NULL || nvp->ri_hostname == NULL || nvp->ri_knconf == NULL) {
 161                 rdc_destroy_svinfo(nvp);
 162                 return (NULL);
 163         }
 164 
 165         nvp->ri_hostnamelen = hlen;
 166 
 167         bcopy((void *)conf, (void *)nvp->ri_knconf, sizeof (*nvp->ri_knconf));
 168         nvp->ri_knconf->knc_protofmly = kmem_zalloc(KNC_STRSIZE + 1, KM_SLEEP);
 169         nvp->ri_knconf->knc_proto = kmem_zalloc(KNC_STRSIZE + 1, KM_SLEEP);
 170 
 171         if (nvp->ri_knconf->knc_protofmly == NULL ||
 172             nvp->ri_knconf->knc_proto == NULL) {
 173                 rdc_destroy_svinfo(nvp);
 174                 return (NULL);
 175 
 176         }
 177 
 178         (void) strncpy(nvp->ri_knconf->knc_protofmly, conf->knc_protofmly,
 179             KNC_STRSIZE);
 180         (void) strncpy(nvp->ri_knconf->knc_proto, conf->knc_proto, KNC_STRSIZE);
 181 
 182         dup_rdc_netbuf(svaddr, &nvp->ri_addr);
 183 
 184         nvp->ri_secdata = NULL;              /* For now */
 185         (void) strncpy(nvp->ri_hostname, host, hlen);
 186 #ifdef DEBUG_IP
 187         rdc_print_svinfo(nvp, "!create");
 188 #endif
 189         return (nvp);
 190 }
 191 
 192 void
 193 rdc_destroy_svinfo(rdc_srv_t *svp)
 194 {
 195         if (svp == NULL)
 196                 return;
 197 
 198         if (svp->ri_addr.buf && svp->ri_addr.maxlen)
 199                 free_rdc_netbuf(&(svp->ri_addr));
 200 
 201         if (svp->ri_knconf->knc_protofmly)
 202                 kmem_free(svp->ri_knconf->knc_protofmly, KNC_STRSIZE + 1);
 203 
 204         if (svp->ri_knconf->knc_proto)
 205                 kmem_free(svp->ri_knconf->knc_proto, KNC_STRSIZE + 1);
 206 
 207         if (svp->ri_knconf)
 208                 kmem_free(svp->ri_knconf, sizeof (*svp->ri_knconf));
 209 
 210         kmem_free(svp, sizeof (*svp));
 211 }
 212 
 213 /*
 214  * rdc_netbuf_toint
 215  * Returns oldsytle ipv4 RDC ver 3 addresses for RPC protocol from netbuf
 216  * Note: This would never be called in the case of IPv6 and a program
 217  * mismatch ie ver 3 to ver 4
 218  */
 219 int
 220 rdc_netbuf_toint(struct netbuf *nb)
 221 {
 222         int ret;
 223         if (nb->len > RDC_MAXADDR)
 224                 cmn_err(CE_NOTE, "!rdc_netbuf_toint: bad size %d", nb->len);
 225 
 226         switch (nb->len) {
 227                 case 4:
 228                         bcopy(nb->buf, (char *)&ret, sizeof (int));
 229                         return (ret);
 230 
 231                 case 8:
 232                 case 16:
 233                 case 32:
 234                         bcopy(&nb->buf[4], (char *)&ret, sizeof (int));
 235                         return (ret);
 236 
 237                 default:
 238                         cmn_err(CE_NOTE, "!rdc_netbuf_toint: size %d", nb->len);
 239                 }
 240         return (0);
 241 }