lib/interface.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    multiple interface handling
00004    Copyright (C) Andrew Tridgell 1992-1998
00005    
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 #include "includes.h"
00022 
00023 static struct iface_struct *probed_ifaces;
00024 static int total_probed;
00025 
00026 struct in_addr allones_ip;
00027 struct in_addr loopback_ip;
00028 
00029 static struct interface *local_interfaces;
00030 
00031 #define ALLONES  ((uint32)0xFFFFFFFF)
00032 #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
00033 #define MKNETADDR(_IP, _NM) (_IP & _NM)
00034 
00035 /****************************************************************************
00036 Try and find an interface that matches an ip. If we cannot, return NULL
00037   **************************************************************************/
00038 static struct interface *iface_find(struct in_addr ip, BOOL CheckMask)
00039 {
00040         struct interface *i;
00041         if (is_zero_ip(ip)) return local_interfaces;
00042 
00043         for (i=local_interfaces;i;i=i->next)
00044                 if (CheckMask) {
00045                         if (same_net(i->ip,ip,i->nmask)) return i;
00046                 } else if ((i->ip).s_addr == ip.s_addr) return i;
00047 
00048         return NULL;
00049 }
00050 
00051 
00052 /****************************************************************************
00053 add an interface to the linked list of interfaces
00054 ****************************************************************************/
00055 static void add_interface(struct in_addr ip, struct in_addr nmask)
00056 {
00057         struct interface *iface;
00058         if (iface_find(ip, False)) {
00059                 DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip)));
00060                 return;
00061         }
00062 
00063 #if !defined(__s390__)
00064         if (ip_equal(nmask, allones_ip)) {
00065                 DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip)));
00066                 return;
00067         }
00068 #endif
00069 
00070         iface = SMB_MALLOC_P(struct interface);
00071         if (!iface) return;
00072         
00073         ZERO_STRUCTPN(iface);
00074 
00075         iface->ip = ip;
00076         iface->nmask = nmask;
00077         iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
00078 
00079         DLIST_ADD(local_interfaces, iface);
00080 
00081         DEBUG(2,("added interface ip=%s ",inet_ntoa(iface->ip)));
00082         DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
00083         DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));             
00084 }
00085 
00086 
00087 
00088 /****************************************************************************
00089 interpret a single element from a interfaces= config line 
00090 
00091 This handles the following different forms:
00092 
00093 1) wildcard interface name
00094 2) DNS name
00095 3) IP/masklen
00096 4) ip/mask
00097 5) bcast/mask
00098 ****************************************************************************/
00099 static void interpret_interface(char *token)
00100 {
00101         struct in_addr ip, nmask;
00102         char *p;
00103         int i, added=0;
00104 
00105         zero_ip(&ip);
00106         zero_ip(&nmask);
00107         
00108         /* first check if it is an interface name */
00109         for (i=0;i<total_probed;i++) {
00110                 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
00111                         add_interface(probed_ifaces[i].ip,
00112                                       probed_ifaces[i].netmask);
00113                         added = 1;
00114                 }
00115         }
00116         if (added) return;
00117 
00118         /* maybe it is a DNS name */
00119         p = strchr_m(token,'/');
00120         if (!p) {
00121                 ip = *interpret_addr2(token);
00122                 for (i=0;i<total_probed;i++) {
00123                         if (ip.s_addr == probed_ifaces[i].ip.s_addr &&
00124                             !ip_equal(allones_ip, probed_ifaces[i].netmask)) {
00125                                 add_interface(probed_ifaces[i].ip,
00126                                               probed_ifaces[i].netmask);
00127                                 return;
00128                         }
00129                 }
00130                 DEBUG(2,("can't determine netmask for %s\n", token));
00131                 return;
00132         }
00133 
00134         /* parse it into an IP address/netmasklength pair */
00135         *p = 0;
00136         ip = *interpret_addr2(token);
00137         *p++ = '/';
00138 
00139         if (strlen(p) > 2) {
00140                 nmask = *interpret_addr2(p);
00141         } else {
00142                 nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
00143         }
00144 
00145         /* maybe the first component was a broadcast address */
00146         if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) ||
00147             ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) {
00148                 for (i=0;i<total_probed;i++) {
00149                         if (same_net(ip, probed_ifaces[i].ip, nmask)) {
00150                                 add_interface(probed_ifaces[i].ip, nmask);
00151                                 return;
00152                         }
00153                 }
00154                 DEBUG(2,("Can't determine ip for broadcast address %s\n", token));
00155                 return;
00156         }
00157 
00158         add_interface(ip, nmask);
00159 }
00160 
00161 
00162 /****************************************************************************
00163 load the list of network interfaces
00164 ****************************************************************************/
00165 void load_interfaces(void)
00166 {
00167         const char **ptr;
00168         int i;
00169         struct iface_struct ifaces[MAX_INTERFACES];
00170 
00171         ptr = lp_interfaces();
00172 
00173         allones_ip = *interpret_addr2("255.255.255.255");
00174         loopback_ip = *interpret_addr2("127.0.0.1");
00175 
00176         SAFE_FREE(probed_ifaces);
00177 
00178         /* dump the current interfaces if any */
00179         while (local_interfaces) {
00180                 struct interface *iface = local_interfaces;
00181                 DLIST_REMOVE(local_interfaces, local_interfaces);
00182                 ZERO_STRUCTPN(iface);
00183                 SAFE_FREE(iface);
00184         }
00185 
00186         /* probe the kernel for interfaces */
00187         total_probed = get_interfaces(ifaces, MAX_INTERFACES);
00188 
00189         if (total_probed > 0) {
00190                 probed_ifaces = (struct iface_struct *)memdup(ifaces, sizeof(ifaces[0])*total_probed);
00191                 if (!probed_ifaces) {
00192                         DEBUG(0,("ERROR: memdup failed\n"));
00193                         exit(1);
00194                 }
00195         }
00196 
00197         /* if we don't have a interfaces line then use all broadcast capable 
00198            interfaces except loopback */
00199         if (!ptr || !*ptr || !**ptr) {
00200                 if (total_probed <= 0) {
00201                         DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n"));
00202                         exit(1);
00203                 }
00204                 for (i=0;i<total_probed;i++) {
00205                         if (
00206 #if !defined(__s390__)
00207                             probed_ifaces[i].netmask.s_addr != allones_ip.s_addr &&
00208 #endif
00209                             probed_ifaces[i].ip.s_addr != loopback_ip.s_addr) {
00210                                 add_interface(probed_ifaces[i].ip, 
00211                                               probed_ifaces[i].netmask);
00212                         }
00213                 }
00214                 return;
00215         }
00216 
00217         if (ptr) {
00218                 while (*ptr) {
00219                         char *ptr_cpy = SMB_STRDUP(*ptr);
00220                         if (ptr_cpy) {
00221                                 interpret_interface(ptr_cpy);
00222                                 free(ptr_cpy);
00223                         }
00224                         ptr++;
00225                 }
00226         }
00227 
00228         if (!local_interfaces) {
00229                 DEBUG(0,("WARNING: no network interfaces found\n"));
00230         }
00231 }
00232 
00233 
00234 void gfree_interfaces(void)
00235 {
00236         while (local_interfaces) {
00237                 struct interface *iface = local_interfaces;
00238                 DLIST_REMOVE(local_interfaces, local_interfaces);
00239                 ZERO_STRUCTPN(iface);
00240                 SAFE_FREE(iface);
00241         }
00242 
00243         SAFE_FREE(probed_ifaces);
00244 }
00245 
00246 /****************************************************************************
00247 return True if the list of probed interfaces has changed
00248 ****************************************************************************/
00249 BOOL interfaces_changed(void)
00250 {
00251         int n;
00252         struct iface_struct ifaces[MAX_INTERFACES];
00253 
00254         n = get_interfaces(ifaces, MAX_INTERFACES);
00255 
00256         if ((n > 0 )&& (n != total_probed ||
00257             memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
00258                 return True;
00259         }
00260         
00261         return False;
00262 }
00263 
00264 
00265 /****************************************************************************
00266   check if an IP is one of mine
00267   **************************************************************************/
00268 BOOL ismyip(struct in_addr ip)
00269 {
00270         struct interface *i;
00271         for (i=local_interfaces;i;i=i->next)
00272                 if (ip_equal(i->ip,ip)) return True;
00273         return False;
00274 }
00275 
00276 /****************************************************************************
00277   check if a packet is from a local (known) net
00278   **************************************************************************/
00279 BOOL is_local_net(struct in_addr from)
00280 {
00281         struct interface *i;
00282         for (i=local_interfaces;i;i=i->next) {
00283                 if((from.s_addr & i->nmask.s_addr) == 
00284                    (i->ip.s_addr & i->nmask.s_addr))
00285                         return True;
00286         }
00287         return False;
00288 }
00289 
00290 /****************************************************************************
00291   how many interfaces do we have
00292   **************************************************************************/
00293 int iface_count(void)
00294 {
00295         int ret = 0;
00296         struct interface *i;
00297 
00298         for (i=local_interfaces;i;i=i->next)
00299                 ret++;
00300         return ret;
00301 }
00302 
00303 /****************************************************************************
00304   how many non-loopback interfaces do we have
00305   **************************************************************************/
00306 int iface_count_nl(void)
00307 {
00308         int ret = 0;
00309         struct interface *i;
00310 
00311         for (i=local_interfaces;i;i=i->next) {
00312                 if (ip_equal(i->ip, loopback_ip)) {
00313                         continue;
00314                 }
00315                 ret++;
00316         }
00317         return ret;
00318 }
00319 
00320 /****************************************************************************
00321   return the Nth interface
00322   **************************************************************************/
00323 struct interface *get_interface(int n)
00324 { 
00325         struct interface *i;
00326   
00327         for (i=local_interfaces;i && n;i=i->next)
00328                 n--;
00329 
00330         if (i) return i;
00331         return NULL;
00332 }
00333 
00334 /****************************************************************************
00335   return IP of the Nth interface
00336   **************************************************************************/
00337 struct in_addr *iface_n_ip(int n)
00338 {
00339         struct interface *i;
00340   
00341         for (i=local_interfaces;i && n;i=i->next)
00342                 n--;
00343 
00344         if (i) return &i->ip;
00345         return NULL;
00346 }
00347 
00348 /****************************************************************************
00349   return bcast of the Nth interface
00350   **************************************************************************/
00351 struct in_addr *iface_n_bcast(int n)
00352 {
00353         struct interface *i;
00354   
00355         for (i=local_interfaces;i && n;i=i->next)
00356                 n--;
00357 
00358         if (i) return &i->bcast;
00359         return NULL;
00360 }
00361 
00362 
00363 /* these 3 functions return the ip/bcast/nmask for the interface
00364    most appropriate for the given ip address. If they can't find
00365    an appropriate interface they return the requested field of the
00366    first known interface. */
00367 
00368 struct in_addr *iface_ip(struct in_addr ip)
00369 {
00370         struct interface *i = iface_find(ip, True);
00371         return(i ? &i->ip : &local_interfaces->ip);
00372 }
00373 
00374 /*
00375   return True if a IP is directly reachable on one of our interfaces
00376 */
00377 BOOL iface_local(struct in_addr ip)
00378 {
00379         return iface_find(ip, True) ? True : False;
00380 }

Sambaに対してSat Aug 29 21:22:58 2009に生成されました。  doxygen 1.4.7