1 /* 2 * Copyright (c) 2000-2001, Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Boris Popov. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: nb_name.c,v 1.2 2001/08/22 03:31:36 bp Exp $ 33 */ 34 35 #include <sys/param.h> 36 #include <sys/endian.h> 37 #include <sys/socket.h> 38 39 #include <ctype.h> 40 #include <err.h> 41 #include <errno.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 46 #include <netsmb/netbios.h> 47 #include <netsmb/smb_lib.h> 48 #include <netsmb/nb_lib.h> 49 50 int 51 nb_snballoc(int namelen, struct sockaddr_nb **dst) 52 { 53 struct sockaddr_nb *snb; 54 int slen; 55 56 slen = namelen + sizeof(*snb) - sizeof(snb->snb_name); 57 snb = malloc(slen); 58 if (snb == NULL) 59 return ENOMEM; 60 bzero(snb, slen); 61 snb->snb_family = AF_NETBIOS; 62 snb->snb_len = slen; 63 *dst = snb; 64 return 0; 65 } 66 67 void 68 nb_snbfree(struct sockaddr *snb) 69 { 70 free(snb); 71 } 72 73 /* 74 * Create a full NETBIOS address 75 */ 76 int 77 nb_sockaddr(struct sockaddr *peer, struct nb_name *np, 78 struct sockaddr_nb **dst) 79 80 { 81 struct sockaddr_nb *snb; 82 int nmlen, error; 83 84 if (peer && (peer->sa_family != AF_INET && peer->sa_family != AF_IPX)) 85 return EPROTONOSUPPORT; 86 nmlen = nb_name_len(np); 87 if (nmlen < NB_ENCNAMELEN) 88 return EINVAL; 89 error = nb_snballoc(nmlen, &snb); 90 if (error) 91 return error; 92 if (nmlen != nb_name_encode(np, snb->snb_name)) 93 printf("a bug somewhere in the nb_name* code\n"); 94 if (peer) 95 memcpy(&snb->snb_tran, peer, peer->sa_len); 96 *dst = snb; 97 return 0; 98 } 99 100 int 101 nb_name_len(struct nb_name *np) 102 { 103 u_char *name; 104 int len, sclen; 105 106 len = 1 + NB_ENCNAMELEN; 107 if (np->nn_scope == NULL) 108 return len + 1; 109 sclen = 0; 110 for (name = np->nn_scope; *name; name++) { 111 if (*name == '.') { 112 sclen = 0; 113 } else { 114 if (sclen < NB_MAXLABLEN) { 115 sclen++; 116 len++; 117 } 118 } 119 } 120 return len + 1; 121 } 122 123 int 124 nb_encname_len(const char *str) 125 { 126 const u_char *cp = (const u_char *)str; 127 int len, blen; 128 129 if ((cp[0] & 0xc0) == 0xc0) 130 return -1; /* first two bytes are offset to name */ 131 132 len = 1; 133 for (;;) { 134 blen = *cp; 135 if (blen++ == 0) 136 break; 137 len += blen; 138 cp += blen; 139 } 140 return len; 141 } 142 143 static inline void 144 nb_char_encode(u_char **ptr, u_char c, int n) 145 { 146 147 while (n--) { 148 *(*ptr)++ = 0x41 + (c >> 4); 149 *(*ptr)++ = 0x41 + (c & 0x0f); 150 } 151 } 152 153 int 154 nb_name_encode(struct nb_name *np, u_char *dst) 155 { 156 u_char *name, *plen; 157 u_char *cp = dst; 158 int i, lblen; 159 160 *cp++ = NB_ENCNAMELEN; 161 name = np->nn_name; 162 if (name[0] == '*' && name[1] == 0) { 163 nb_char_encode(&cp, '*', 1); 164 nb_char_encode(&cp, ' ', NB_NAMELEN - 1); 165 } else { 166 for (i = 0; i < NB_NAMELEN - 1; i++) 167 if (*name != 0) 168 nb_char_encode(&cp, toupper(*name++), 1); 169 else 170 nb_char_encode(&cp, ' ', 1); 171 nb_char_encode(&cp, np->nn_type, 1); 172 } 173 *cp = 0; 174 if (np->nn_scope == NULL) 175 return nb_encname_len(dst); 176 plen = cp++; 177 lblen = 0; 178 for (name = np->nn_scope; ; name++) { 179 if (*name == '.' || *name == 0) { 180 *plen = lblen; 181 plen = cp++; 182 *plen = 0; 183 if (*name == 0) 184 break; 185 } else { 186 if (lblen < NB_MAXLABLEN) { 187 *cp++ = *name; 188 lblen++; 189 } 190 } 191 } 192 return nb_encname_len(dst); 193 } 194 195