1 /* 2 * Copyright (c) 2000, 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_net.c,v 1.8 2004/03/19 01:49:47 lindak Exp $ 33 */ 34 35 #pragma ident "%Z%%M% %I% %E% SMI" 36 37 #include <sys/param.h> 38 #include <sys/socket.h> 39 #include <sys/ioctl.h> 40 #include <sys/sockio.h> 41 #include <net/if.h> 42 #include <ctype.h> 43 #include <netdb.h> 44 #include <errno.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <strings.h> 48 #include <stdio.h> 49 #include <unistd.h> 50 51 #include <err.h> 52 53 #include <netsmb/netbios.h> 54 #include <netsmb/smb_lib.h> 55 #include <netsmb/nb_lib.h> 56 57 int 58 nb_getlocalname(char *name, size_t maxlen) 59 { 60 char buf[1024], *cp; 61 62 if (gethostname(buf, sizeof (buf)) != 0) 63 return (errno); 64 cp = strchr(buf, '.'); 65 if (cp) 66 *cp = 0; 67 strlcpy(name, buf, maxlen); 68 return (0); 69 } 70 71 int 72 nb_resolvehost_in(const char *name, struct sockaddr **dest) 73 { 74 struct hostent *h; 75 struct sockaddr_in *sinp; 76 in_addr_t addr; 77 struct in_addr in; 78 int len; 79 char **p; 80 81 82 h = gethostbyname(name); 83 if (!h) { 84 #ifdef DEBUG 85 warnx("can't get server address `%s': ", name); 86 #endif 87 return (ENETDOWN); 88 } 89 if (h->h_addrtype != AF_INET) { 90 #ifdef DEBUG 91 warnx("address for `%s' is not in the AF_INET family", name); 92 #endif 93 return (EAFNOSUPPORT); 94 } 95 if (h->h_length != 4) { 96 #ifdef DEBUG 97 warnx("address for `%s' has invalid length", name); 98 #endif 99 return (EAFNOSUPPORT); 100 } 101 len = sizeof (struct sockaddr_in); 102 sinp = malloc(len); 103 if (sinp == NULL) 104 return (ENOMEM); 105 bzero(sinp, len); 106 /* 107 * There is no sin_len in sockaddr_in structure on Solaris. 108 * sinp->sin_len = len; 109 */ 110 sinp->sin_family = h->h_addrtype; 111 memcpy(&sinp->sin_addr.s_addr, *h->h_addr_list,\ 112 sizeof (sinp->sin_addr.s_addr)); 113 sinp->sin_port = htons(SMB_TCP_PORT); 114 *dest = (struct sockaddr *)sinp; 115 return (0); 116 } 117 118 #ifdef NOT_DEFINED 119 int 120 nb_enum_if(struct nb_ifdesc **iflist) { 121 struct lifconf ifc; 122 struct lifreq *ifrqp; 123 struct nb_ifdesc *ifd; 124 struct in_addr iaddr, imask; 125 struct lifnum ifn; 126 char *ifrdata, *iname; 127 int s, rdlen, ifcnt, error, iflags, i; 128 129 *iflist = NULL; 130 s = socket(AF_INET, SOCK_DGRAM, 0); 131 if (s == -1) 132 return (errno); 133 134 /* Get number of interfaces. */ 135 ifn.lifn_family = AF_INET; 136 ifn.lifn_flags = 0; 137 ifn.lifn_count = 0; 138 if (ioctl(s, SIOCGLIFNUM, &ifn) != 0) { 139 error = errno; 140 goto bad; 141 } 142 143 rdlen = ifn.lifn_count * sizeof (struct lifreq); 144 ifrdata = malloc(rdlen); 145 if (ifrdata == NULL) { 146 error = ENOMEM; 147 goto bad; 148 } 149 ifc.lifc_flags = 0; 150 ifc.lifc_family = AF_INET; 151 ifc.lifc_len = rdlen; 152 ifc.lifc_buf = ifrdata; 153 if (ioctl(s, SIOCGLIFCONF, &ifc) != 0) { 154 error = errno; 155 goto bad; 156 } 157 ifrqp = ifc.lifc_req; 158 ifcnt = ifc.lifc_len / sizeof (struct lifreq); 159 error = 0; 160 for (i = 0; i < ifcnt; i++, ifrqp++) { 161 /* XXX for now, avoid IP6 broadcast performance costs */ 162 if (ifrqp->lifr_addr.ss_family != AF_INET) 163 continue; 164 if (ioctl(s, SIOCGLIFFLAGS, ifrqp) != 0) 165 continue; 166 iflags = ifrqp->lifr_flags; 167 if ((iflags & IFF_UP) == 0 || (iflags & IFF_BROADCAST) == 0) 168 continue; 169 170 if (ioctl(s, SIOCGLIFADDR, ifrqp) != 0 || 171 ifrqp->lifr_addr.ss_family != AF_INET) { 172 continue; 173 } 174 iname = ifrqp->lifr_name; 175 if (strlen(iname) >= sizeof (ifd->id_name)) 176 continue; 177 iaddr = (*(struct sockaddr_in *)&ifrqp->lifr_addr).sin_addr; 178 179 if (ioctl(s, SIOCGLIFNETMASK, ifrqp) != 0) 180 continue; 181 imask = ((struct sockaddr_in *)&ifrqp->lifr_addr)->sin_addr; 182 183 ifd = malloc(sizeof (struct nb_ifdesc)); 184 if (ifd == NULL) 185 return (ENOMEM); 186 bzero(ifd, sizeof (struct nb_ifdesc)); 187 strcpy(ifd->id_name, iname); 188 ifd->id_flags = iflags; 189 ifd->id_addr = iaddr; 190 ifd->id_mask = imask; 191 ifd->id_next = *iflist; 192 *iflist = ifd; 193 } 194 bad: 195 free(ifrdata); 196 close(s); 197 return (error); 198 } 199 200 /*ARGSUSED*/ 201 int 202 nbns_resolvename(const char *name, struct sockaddr **dest) 203 { 204 printf("NetBIOS name resolver is not included in this distribution.\n"); 205 printf("Please use '-I' option to specify an IP address of server.\n"); 206 return (EHOSTUNREACH); 207 } 208 209 int 210 nb_hostlookup(struct nb_name *np, const char *server, const char *hint, 211 struct sockaddr_nb **dst) 212 { 213 struct sockaddr_nb *snb; 214 int error; 215 216 error = nb_sockaddr(NULL, np, &snb); 217 if (error) 218 return (error); 219 do { 220 if (hint) { 221 error = nb_resolvehost_in(host, snb); 222 if (error) 223 break; 224 } else { 225 error = nb_resolvename(server); 226 } 227 } while (0); 228 if (!error) { 229 *dst = snb; 230 } else 231 nb_snbfree(snb); 232 return (error); 233 } 234 #endif 235