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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Main startup code for SMB/NETBIOS and some utility routines 30 * for the NETBIOS layer. 31 */ 32 33 #include <synch.h> 34 #include <unistd.h> 35 #include <syslog.h> 36 #include <string.h> 37 #include <strings.h> 38 #include <sys/socket.h> 39 40 #include <smbns_netbios.h> 41 42 netbios_status_t nb_status; 43 44 static pthread_t smb_nbns_thr; /* name service */ 45 static pthread_t smb_nbds_thr; /* dgram service */ 46 static pthread_t smb_nbts_thr; /* timer */ 47 static pthread_t smb_nbbs_thr; /* browser */ 48 49 static void *smb_netbios_timer(void *); 50 51 void 52 smb_netbios_chg_status(uint32_t status, int set) 53 { 54 (void) mutex_lock(&nb_status.mtx); 55 if (set) 56 nb_status.state |= status; 57 else 58 nb_status.state &= ~status; 59 (void) cond_broadcast(&nb_status.cv); 60 (void) mutex_unlock(&nb_status.mtx); 61 } 62 63 void 64 smb_netbios_shutdown(void) 65 { 66 smb_netbios_chg_status(NETBIOS_SHUTTING_DOWN, 1); 67 68 (void) pthread_join(smb_nbts_thr, 0); 69 (void) pthread_join(smb_nbbs_thr, 0); 70 (void) pthread_join(smb_nbns_thr, 0); 71 (void) pthread_join(smb_nbds_thr, 0); 72 73 nb_status.state = NETBIOS_SHUT_DOWN; 74 } 75 76 int 77 smb_netbios_start(void) 78 { 79 int rc; 80 mutex_t *mp; 81 cond_t *cvp; 82 83 /* Startup Netbios named; port 137 */ 84 rc = pthread_create(&smb_nbns_thr, 0, 85 smb_netbios_name_service_daemon, 0); 86 if (rc) 87 return (-1); 88 89 mp = &nb_status.mtx; 90 cvp = &nb_status.cv; 91 92 (void) mutex_lock(mp); 93 while (!(nb_status.state & (NETBIOS_NAME_SVC_RUNNING | 94 NETBIOS_NAME_SVC_FAILED))) { 95 (void) cond_wait(cvp, mp); 96 } 97 98 if (nb_status.state & NETBIOS_NAME_SVC_FAILED) { 99 (void) mutex_unlock(mp); 100 smb_netbios_shutdown(); 101 return (-1); 102 } 103 (void) mutex_unlock(mp); 104 105 smb_netbios_name_config(); 106 107 /* Startup Netbios datagram service; port 138 */ 108 rc = pthread_create(&smb_nbds_thr, 0, 109 smb_netbios_datagram_service_daemon, 0); 110 if (rc != 0) { 111 smb_netbios_shutdown(); 112 return (-1); 113 } 114 115 (void) mutex_lock(mp); 116 while (!(nb_status.state & (NETBIOS_DATAGRAM_SVC_RUNNING | 117 NETBIOS_DATAGRAM_SVC_FAILED))) { 118 (void) cond_wait(cvp, mp); 119 } 120 121 if (nb_status.state & NETBIOS_DATAGRAM_SVC_FAILED) { 122 (void) mutex_unlock(mp); 123 smb_netbios_shutdown(); 124 return (-1); 125 } 126 (void) mutex_unlock(mp); 127 128 /* Startup Netbios browser service */ 129 rc = pthread_create(&smb_nbbs_thr, 0, smb_browser_daemon, 0); 130 if (rc) { 131 smb_netbios_shutdown(); 132 return (-1); 133 } 134 135 /* Startup Our internal, 1 second resolution, timer */ 136 rc = pthread_create(&smb_nbts_thr, 0, smb_netbios_timer, 0); 137 if (rc != 0) { 138 smb_netbios_shutdown(); 139 return (-1); 140 } 141 142 (void) mutex_lock(mp); 143 while (!(nb_status.state & (NETBIOS_TIMER_RUNNING | 144 NETBIOS_TIMER_FAILED))) { 145 (void) cond_wait(cvp, mp); 146 } 147 148 if (nb_status.state & NETBIOS_TIMER_FAILED) { 149 (void) mutex_unlock(mp); 150 smb_netbios_shutdown(); 151 return (-1); 152 } 153 (void) mutex_unlock(mp); 154 155 return (0); 156 } 157 158 /*ARGSUSED*/ 159 static void * 160 smb_netbios_timer(void *arg) 161 { 162 static unsigned int ticks = 0; 163 164 smb_netbios_chg_status(NETBIOS_TIMER_RUNNING, 1); 165 166 while ((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) { 167 (void) sleep(1); 168 ticks++; 169 170 if ((nb_status.state & NETBIOS_DATAGRAM_SVC_RUNNING) == 0) 171 break; 172 173 if ((nb_status.state & NETBIOS_NAME_SVC_RUNNING) == 0) 174 break; 175 176 smb_netbios_datagram_tick(); 177 smb_netbios_name_tick(); 178 179 /* every 10 minutes */ 180 if ((ticks % 600) == 0) 181 smb_netbios_cache_clean(); 182 } 183 184 nb_status.state &= ~NETBIOS_TIMER_RUNNING; 185 if ((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) { 186 /* either name or datagram service has failed */ 187 smb_netbios_shutdown(); 188 } 189 190 return (0); 191 } 192 193 int 194 smb_first_level_name_encode(struct name_entry *name, 195 unsigned char *out, int max_out) 196 { 197 return (netbios_first_level_name_encode(name->name, name->scope, 198 out, max_out)); 199 } 200 201 int 202 smb_first_level_name_decode(unsigned char *in, struct name_entry *name) 203 { 204 return (netbios_first_level_name_decode((char *)in, (char *)name->name, 205 (char *)name->scope)); 206 } 207 208 /* 209 * smb_encode_netbios_name 210 * 211 * Set up the name and scope fields in the destination name_entry structure. 212 * The name is padded with spaces to 15 bytes. The suffix is copied into the 213 * last byte, i.e. "netbiosname <suffix>". The scope is copied and folded 214 * to uppercase. 215 */ 216 void 217 smb_encode_netbios_name(unsigned char *name, char suffix, unsigned char *scope, 218 struct name_entry *dest) 219 { 220 smb_tonetbiosname((char *)name, (char *)dest->name, suffix); 221 222 if (scope) { 223 (void) strlcpy((char *)dest->scope, (const char *)scope, 224 sizeof (dest->scope)); 225 } else { 226 (void) smb_config_getstr(SMB_CI_NBSCOPE, (char *)dest->scope, 227 sizeof (dest->scope)); 228 } 229 230 (void) utf8_strupr((char *)dest->scope); 231 } 232 233 void 234 smb_init_name_struct(unsigned char *name, char suffix, unsigned char *scope, 235 uint32_t ipaddr, unsigned short port, uint32_t attr, 236 uint32_t addr_attr, struct name_entry *dest) 237 { 238 bzero(dest, sizeof (struct name_entry)); 239 smb_encode_netbios_name(name, suffix, scope, dest); 240 241 switch (smb_node_type) { 242 case 'H': 243 dest->attributes = attr | NAME_ATTR_OWNER_TYPE_HNODE; 244 break; 245 case 'M': 246 dest->attributes = attr | NAME_ATTR_OWNER_TYPE_MNODE; 247 break; 248 case 'P': 249 dest->attributes = attr | NAME_ATTR_OWNER_TYPE_PNODE; 250 break; 251 case 'B': 252 default: 253 dest->attributes = attr | NAME_ATTR_OWNER_TYPE_BNODE; 254 break; 255 } 256 257 dest->addr_list.refresh_ttl = dest->addr_list.ttl = 258 TO_SECONDS(DEFAULT_TTL); 259 260 dest->addr_list.sin.sin_family = AF_INET; 261 dest->addr_list.sinlen = sizeof (dest->addr_list.sin); 262 dest->addr_list.sin.sin_addr.s_addr = ipaddr; 263 dest->addr_list.sin.sin_port = port; 264 dest->addr_list.attributes = addr_attr; 265 dest->addr_list.forw = dest->addr_list.back = &dest->addr_list; 266 } 267