interface.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /*
  2. Unix SMB/Netbios implementation.
  3. Version 1.9.
  4. multiple interface handling
  5. Copyright (C) Andrew Tridgell 1992-1998
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. */
  18. #include "includes.h"
  19. extern int DEBUGLEVEL;
  20. struct in_addr ipzero;
  21. struct in_addr allones_ip;
  22. struct in_addr loopback_ip;
  23. static struct in_addr default_ip;
  24. static struct in_addr default_bcast;
  25. static struct in_addr default_nmask;
  26. static BOOL got_ip=False;
  27. static BOOL got_bcast=False;
  28. static BOOL got_nmask=False;
  29. static struct interface *local_interfaces = NULL;
  30. struct interface *last_iface;
  31. #define ALLONES ((uint32)0xFFFFFFFF)
  32. #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
  33. /****************************************************************************
  34. calculate the default netmask for an address
  35. ****************************************************************************/
  36. static void default_netmask(struct in_addr *inm, struct in_addr *iad)
  37. {
  38. /*
  39. ** Guess a netmask based on the class of the IP address given.
  40. */
  41. switch((ntohl(iad->s_addr) & 0xE0000000)) {
  42. case 0x00000000: /* Class A addr */
  43. case 0x20000000:
  44. case 0x40000000:
  45. case 0x60000000:
  46. inm->s_addr = htonl(0xFF000000);
  47. break;
  48. case 0x80000000: /* Class B addr */
  49. case 0xA0000000:
  50. inm->s_addr = htonl(0xFFFF0000);
  51. break;
  52. case 0xC0000000: /* Class C addr */
  53. inm->s_addr = htonl(0xFFFFFF00);
  54. break;
  55. default: /* ??? */
  56. inm->s_addr = htonl(0xFFFFFFF0);
  57. }
  58. }
  59. /****************************************************************************
  60. get the broadcast address for our address
  61. (troyer@saifr00.ateng.az.honeywell.com)
  62. ****************************************************************************/
  63. static void get_broadcast(struct in_addr *if_ipaddr,
  64. struct in_addr *if_bcast,
  65. struct in_addr *if_nmask)
  66. {
  67. uint32 nm;
  68. short onbc;
  69. short offbc;
  70. /* get a default netmask and broadcast */
  71. default_netmask(if_nmask, if_ipaddr);
  72. get_netmask(if_ipaddr, if_nmask);
  73. /* sanity check on the netmask */
  74. nm = ntohl(if_nmask->s_addr);
  75. onbc = 0;
  76. offbc = 0;
  77. while((onbc + offbc) < 32) {
  78. if(nm & 0x80000000) {
  79. onbc++;
  80. if(offbc) {
  81. /* already found an off bit, so mask
  82. is wrong */
  83. onbc = 34;
  84. }
  85. } else {
  86. offbc++;
  87. }
  88. nm <<= 1;
  89. }
  90. if ((onbc < 8)||(onbc == 34)) {
  91. DEBUG(0,("Impossible netmask %s - using defaults\n",
  92. inet_ntoa(*if_nmask)));
  93. default_netmask(if_nmask, if_ipaddr);
  94. }
  95. /* derive the broadcast assuming a 1's broadcast, as this is what
  96. all MS operating systems do, we have to comply even if the unix
  97. box is setup differently */
  98. if_bcast->s_addr = MKBCADDR(if_ipaddr->s_addr, if_nmask->s_addr);
  99. DEBUG(4,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
  100. }
  101. /****************************************************************************
  102. load a list of network interfaces
  103. ****************************************************************************/
  104. static void interpret_interfaces(char *s, struct interface **interfaces,
  105. const char *description)
  106. {
  107. char *ptr;
  108. fstring token;
  109. struct interface *iface;
  110. struct in_addr ip;
  111. ptr = s;
  112. ipzero = *interpret_addr2("0.0.0.0");
  113. allones_ip = *interpret_addr2("255.255.255.255");
  114. loopback_ip = *interpret_addr2("127.0.0.1");
  115. while (next_token(&ptr,token,NULL,sizeof(token))) {
  116. /* parse it into an IP address/netmasklength pair */
  117. char *p = strchr(token,'/');
  118. if (p) *p++ = 0;
  119. ip = *interpret_addr2(token);
  120. /* maybe we already have it listed */
  121. {
  122. struct interface *i;
  123. for (i=(*interfaces);i;i=i->next)
  124. if (ip_equal(ip,i->ip)) break;
  125. if (i) continue;
  126. }
  127. iface = (struct interface *)malloc(sizeof(*iface));
  128. if (!iface) return;
  129. iface->ip = ip;
  130. if (p) {
  131. if (strlen(p) > 2)
  132. iface->nmask = *interpret_addr2(p);
  133. else
  134. iface->nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
  135. } else {
  136. default_netmask(&iface->nmask,&iface->ip);
  137. }
  138. iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
  139. iface->next = NULL;
  140. if (!(*interfaces)) {
  141. (*interfaces) = iface;
  142. } else {
  143. last_iface->next = iface;
  144. }
  145. last_iface = iface;
  146. DEBUG(2,("Added %s ip=%s ",description,inet_ntoa(iface->ip)));
  147. DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
  148. DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));
  149. }
  150. if (*interfaces) return;
  151. /* setup a default interface */
  152. iface = (struct interface *)malloc(sizeof(*iface));
  153. if (!iface) return;
  154. iface->next = NULL;
  155. if (got_ip) {
  156. iface->ip = default_ip;
  157. } else {
  158. get_myname(NULL,&iface->ip);
  159. }
  160. if (got_bcast) {
  161. iface->bcast = default_bcast;
  162. } else {
  163. get_broadcast(&iface->ip,&iface->bcast,&iface->nmask);
  164. }
  165. if (got_nmask) {
  166. iface->nmask = default_nmask;
  167. iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
  168. }
  169. if (iface->bcast.s_addr != MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr)) {
  170. DEBUG(2,("Warning: inconsistant interface %s\n",inet_ntoa(iface->ip)));
  171. }
  172. iface->next = NULL;
  173. (*interfaces) = last_iface = iface;
  174. DEBUG(2,("Added interface ip=%s ",inet_ntoa(iface->ip)));
  175. DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
  176. DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));
  177. }
  178. /****************************************************************************
  179. load the remote and local interfaces
  180. ****************************************************************************/
  181. void load_interfaces(void)
  182. {
  183. /* add the machine's interfaces to local interface structure*/
  184. interpret_interfaces(lp_interfaces(), &local_interfaces,"interface");
  185. }
  186. /****************************************************************************
  187. override the defaults
  188. **************************************************************************/
  189. void iface_set_default(char *ip,char *bcast,char *nmask)
  190. {
  191. if (ip) {
  192. got_ip = True;
  193. default_ip = *interpret_addr2(ip);
  194. }
  195. if (bcast) {
  196. got_bcast = True;
  197. default_bcast = *interpret_addr2(bcast);
  198. }
  199. if (nmask) {
  200. got_nmask = True;
  201. default_nmask = *interpret_addr2(nmask);
  202. }
  203. }
  204. /****************************************************************************
  205. check if an IP is one of mine
  206. **************************************************************************/
  207. BOOL ismyip(struct in_addr ip)
  208. {
  209. struct interface *i;
  210. for (i=local_interfaces;i;i=i->next)
  211. if (ip_equal(i->ip,ip)) return True;
  212. return False;
  213. }
  214. /****************************************************************************
  215. check if a packet is from a local (known) net
  216. **************************************************************************/
  217. BOOL is_local_net(struct in_addr from)
  218. {
  219. struct interface *i;
  220. for (i=local_interfaces;i;i=i->next)
  221. if((from.s_addr & i->nmask.s_addr) == (i->ip.s_addr & i->nmask.s_addr))
  222. return True;
  223. return False;
  224. }
  225. /****************************************************************************
  226. how many interfaces do we have
  227. **************************************************************************/
  228. int iface_count(void)
  229. {
  230. int ret = 0;
  231. struct interface *i;
  232. for (i=local_interfaces;i;i=i->next)
  233. ret++;
  234. return ret;
  235. }
  236. /****************************************************************************
  237. True if we have two or more interfaces.
  238. **************************************************************************/
  239. BOOL we_are_multihomed(void)
  240. {
  241. static int multi = -1;
  242. if(multi == -1)
  243. multi = (iface_count() > 1 ? True : False);
  244. return multi;
  245. }
  246. /****************************************************************************
  247. return the Nth interface
  248. **************************************************************************/
  249. struct interface *get_interface(int n)
  250. {
  251. struct interface *i;
  252. for (i=local_interfaces;i && n;i=i->next)
  253. n--;
  254. if (i) return i;
  255. return NULL;
  256. }
  257. /****************************************************************************
  258. return IP of the Nth interface
  259. **************************************************************************/
  260. struct in_addr *iface_n_ip(int n)
  261. {
  262. struct interface *i;
  263. for (i=local_interfaces;i && n;i=i->next)
  264. n--;
  265. if (i) return &i->ip;
  266. return NULL;
  267. }
  268. /****************************************************************************
  269. Try and find an interface that matches an ip. If we cannot, return NULL
  270. **************************************************************************/
  271. static struct interface *iface_find(struct in_addr ip)
  272. {
  273. struct interface *i;
  274. if (zero_ip(ip)) return local_interfaces;
  275. for (i=local_interfaces;i;i=i->next)
  276. if (same_net(i->ip,ip,i->nmask)) return i;
  277. return NULL;
  278. }
  279. /****************************************************************************
  280. this function provides a simple hash of the configured interfaces. It is
  281. used to detect a change in interfaces to tell us whether to discard
  282. the current wins.dat file.
  283. Note that the result is independent of the order of the interfaces
  284. **************************************************************************/
  285. unsigned iface_hash(void)
  286. {
  287. unsigned ret = 0;
  288. struct interface *i;
  289. for (i=local_interfaces;i;i=i->next) {
  290. unsigned x1 = (unsigned)str_checksum(inet_ntoa(i->ip));
  291. unsigned x2 = (unsigned)str_checksum(inet_ntoa(i->nmask));
  292. ret ^= (x1 ^ x2);
  293. }
  294. return ret;
  295. }
  296. /* these 3 functions return the ip/bcast/nmask for the interface
  297. most appropriate for the given ip address. If they can't find
  298. an appropriate interface they return the requested field of the
  299. first known interface. */
  300. struct in_addr *iface_bcast(struct in_addr ip)
  301. {
  302. struct interface *i = iface_find(ip);
  303. return(i ? &i->bcast : &local_interfaces->bcast);
  304. }
  305. struct in_addr *iface_ip(struct in_addr ip)
  306. {
  307. struct interface *i = iface_find(ip);
  308. return(i ? &i->ip : &local_interfaces->ip);
  309. }