PageRenderTime 29ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/source4/lib/socket/interface.c

https://github.com/wimberosa/samba
C | 541 lines | 369 code | 70 blank | 102 comment | 82 complexity | 9f079ea5189c67d4977354296c9ec831 MD5 | raw file
  1. /*
  2. Unix SMB/CIFS implementation.
  3. multiple interface handling
  4. Copyright (C) Andrew Tridgell 1992-2005
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "includes.h"
  17. #include "system/network.h"
  18. #include "param/param.h"
  19. #include "lib/socket/netif.h"
  20. #include "../lib/util/util_net.h"
  21. #include "../lib/util/dlinklist.h"
  22. /* used for network interfaces */
  23. struct interface {
  24. struct interface *next, *prev;
  25. char *name;
  26. int flags;
  27. struct sockaddr_storage ip;
  28. struct sockaddr_storage netmask;
  29. struct sockaddr_storage bcast;
  30. const char *ip_s;
  31. const char *bcast_s;
  32. const char *nmask_s;
  33. };
  34. #define ALLONES ((uint32_t)0xFFFFFFFF)
  35. /*
  36. address construction based on a patch from fred@datalync.com
  37. */
  38. #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
  39. #define MKNETADDR(_IP, _NM) (_IP & _NM)
  40. /****************************************************************************
  41. Try and find an interface that matches an ip. If we cannot, return NULL
  42. **************************************************************************/
  43. static struct interface *iface_list_find(struct interface *interfaces,
  44. const struct sockaddr *ip,
  45. bool check_mask)
  46. {
  47. struct interface *i;
  48. if (is_address_any(ip)) {
  49. return interfaces;
  50. }
  51. for (i=interfaces;i;i=i->next) {
  52. if (check_mask) {
  53. if (same_net(ip, (struct sockaddr *)&i->ip, (struct sockaddr *)&i->netmask)) {
  54. return i;
  55. }
  56. } else if (sockaddr_equal((struct sockaddr *)&i->ip, ip)) {
  57. return i;
  58. }
  59. }
  60. return NULL;
  61. }
  62. /****************************************************************************
  63. add an interface to the linked list of interfaces
  64. ****************************************************************************/
  65. static void add_interface(TALLOC_CTX *mem_ctx, const struct iface_struct *ifs, struct interface **interfaces,
  66. bool enable_ipv6)
  67. {
  68. char addr[INET6_ADDRSTRLEN];
  69. struct interface *iface;
  70. if (iface_list_find(*interfaces, (const struct sockaddr *)&ifs->ip, false)) {
  71. DEBUG(3,("add_interface: not adding duplicate interface %s\n",
  72. print_sockaddr(addr, sizeof(addr), &ifs->ip) ));
  73. return;
  74. }
  75. if (ifs->ip.ss_family == AF_INET &&
  76. !(ifs->flags & (IFF_BROADCAST|IFF_LOOPBACK))) {
  77. DEBUG(3,("not adding non-broadcast interface %s\n",
  78. ifs->name ));
  79. return;
  80. }
  81. if (!enable_ipv6 && ifs->ip.ss_family != AF_INET) {
  82. return;
  83. }
  84. iface = talloc(*interfaces == NULL ? mem_ctx : *interfaces, struct interface);
  85. if (iface == NULL)
  86. return;
  87. ZERO_STRUCTPN(iface);
  88. iface->name = talloc_strdup(iface, ifs->name);
  89. if (!iface->name) {
  90. SAFE_FREE(iface);
  91. return;
  92. }
  93. iface->flags = ifs->flags;
  94. iface->ip = ifs->ip;
  95. iface->netmask = ifs->netmask;
  96. iface->bcast = ifs->bcast;
  97. /* keep string versions too, to avoid people tripping over the implied
  98. static in inet_ntoa() */
  99. print_sockaddr(addr, sizeof(addr), &iface->ip);
  100. DEBUG(4,("added interface %s ip=%s ",
  101. iface->name, addr));
  102. iface->ip_s = talloc_strdup(iface, addr);
  103. print_sockaddr(addr, sizeof(addr),
  104. &iface->bcast);
  105. DEBUG(4,("bcast=%s ", addr));
  106. iface->bcast_s = talloc_strdup(iface, addr);
  107. print_sockaddr(addr, sizeof(addr),
  108. &iface->netmask);
  109. DEBUG(4,("netmask=%s\n", addr));
  110. iface->nmask_s = talloc_strdup(iface, addr);
  111. /*
  112. this needs to be a ADD_END, as some tests (such as the
  113. spoolss notify test) depend on the interfaces ordering
  114. */
  115. DLIST_ADD_END(*interfaces, iface, NULL);
  116. }
  117. /**
  118. interpret a single element from a interfaces= config line
  119. This handles the following different forms:
  120. 1) wildcard interface name
  121. 2) DNS name
  122. 3) IP/masklen
  123. 4) ip/mask
  124. 5) bcast/mask
  125. **/
  126. static void interpret_interface(TALLOC_CTX *mem_ctx,
  127. const char *token,
  128. struct iface_struct *probed_ifaces,
  129. int total_probed,
  130. struct interface **local_interfaces,
  131. bool enable_ipv6)
  132. {
  133. struct sockaddr_storage ss;
  134. struct sockaddr_storage ss_mask;
  135. struct sockaddr_storage ss_net;
  136. struct sockaddr_storage ss_bcast;
  137. struct iface_struct ifs;
  138. char *p;
  139. int i;
  140. bool added=false;
  141. bool goodaddr = false;
  142. /* first check if it is an interface name */
  143. for (i=0;i<total_probed;i++) {
  144. if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
  145. add_interface(mem_ctx, &probed_ifaces[i],
  146. local_interfaces, enable_ipv6);
  147. added = true;
  148. }
  149. }
  150. if (added) {
  151. return;
  152. }
  153. /* maybe it is a DNS name */
  154. p = strchr_m(token,'/');
  155. if (p == NULL) {
  156. if (!interpret_string_addr(&ss, token, 0)) {
  157. DEBUG(2, ("interpret_interface: Can't find address "
  158. "for %s\n", token));
  159. return;
  160. }
  161. for (i=0;i<total_probed;i++) {
  162. if (sockaddr_equal((struct sockaddr *)&ss, (struct sockaddr *)&probed_ifaces[i].ip)) {
  163. add_interface(mem_ctx, &probed_ifaces[i],
  164. local_interfaces, enable_ipv6);
  165. return;
  166. }
  167. }
  168. DEBUG(2,("interpret_interface: "
  169. "can't determine interface for %s\n",
  170. token));
  171. return;
  172. }
  173. /* parse it into an IP address/netmasklength pair */
  174. *p = 0;
  175. goodaddr = interpret_string_addr(&ss, token, 0);
  176. *p++ = '/';
  177. if (!goodaddr) {
  178. DEBUG(2,("interpret_interface: "
  179. "can't determine interface for %s\n",
  180. token));
  181. return;
  182. }
  183. if (strlen(p) > 2) {
  184. goodaddr = interpret_string_addr(&ss_mask, p, 0);
  185. if (!goodaddr) {
  186. DEBUG(2,("interpret_interface: "
  187. "can't determine netmask from %s\n",
  188. p));
  189. return;
  190. }
  191. } else {
  192. char *endp = NULL;
  193. unsigned long val = strtoul(p, &endp, 0);
  194. if (p == endp || (endp && *endp != '\0')) {
  195. DEBUG(2,("interpret_interface: "
  196. "can't determine netmask value from %s\n",
  197. p));
  198. return;
  199. }
  200. if (!make_netmask(&ss_mask, &ss, val)) {
  201. DEBUG(2,("interpret_interface: "
  202. "can't apply netmask value %lu from %s\n",
  203. val,
  204. p));
  205. return;
  206. }
  207. }
  208. make_bcast(&ss_bcast, &ss, &ss_mask);
  209. make_net(&ss_net, &ss, &ss_mask);
  210. /* Maybe the first component was a broadcast address. */
  211. if (sockaddr_equal((struct sockaddr *)&ss_bcast, (struct sockaddr *)&ss) ||
  212. sockaddr_equal((struct sockaddr *)&ss_net, (struct sockaddr *)&ss)) {
  213. for (i=0;i<total_probed;i++) {
  214. if (same_net((struct sockaddr *)&ss,
  215. (struct sockaddr *)&probed_ifaces[i].ip,
  216. (struct sockaddr *)&ss_mask)) {
  217. /* Temporarily replace netmask on
  218. * the detected interface - user knows
  219. * best.... */
  220. struct sockaddr_storage saved_mask =
  221. probed_ifaces[i].netmask;
  222. probed_ifaces[i].netmask = ss_mask;
  223. DEBUG(2,("interpret_interface: "
  224. "using netmask value %s from "
  225. "config file on interface %s\n",
  226. p,
  227. probed_ifaces[i].name));
  228. add_interface(mem_ctx, &probed_ifaces[i],
  229. local_interfaces, enable_ipv6);
  230. probed_ifaces[i].netmask = saved_mask;
  231. return;
  232. }
  233. }
  234. DEBUG(2,("interpret_interface: Can't determine ip for "
  235. "broadcast address %s\n",
  236. token));
  237. return;
  238. }
  239. /* Just fake up the interface definition. User knows best. */
  240. DEBUG(2,("interpret_interface: Adding interface %s\n",
  241. token));
  242. ZERO_STRUCT(ifs);
  243. (void)strlcpy(ifs.name, token, sizeof(ifs.name));
  244. ifs.flags = IFF_BROADCAST;
  245. ifs.ip = ss;
  246. ifs.netmask = ss_mask;
  247. ifs.bcast = ss_bcast;
  248. add_interface(mem_ctx, &ifs,
  249. local_interfaces, enable_ipv6);
  250. }
  251. /**
  252. load the list of network interfaces
  253. **/
  254. void load_interface_list(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, struct interface **local_interfaces)
  255. {
  256. const char **ptr = lpcfg_interfaces(lp_ctx);
  257. int i;
  258. struct iface_struct *ifaces = NULL;
  259. int total_probed;
  260. bool enable_ipv6 = lpcfg_parm_bool(lp_ctx, NULL, "ipv6", "enable", true);
  261. *local_interfaces = NULL;
  262. /* probe the kernel for interfaces */
  263. total_probed = get_interfaces(mem_ctx, &ifaces);
  264. /* if we don't have a interfaces line then use all interfaces
  265. except loopback */
  266. if (!ptr || !*ptr || !**ptr) {
  267. if (total_probed <= 0) {
  268. DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n"));
  269. }
  270. for (i=0;i<total_probed;i++) {
  271. if (!is_loopback_addr((struct sockaddr *)&ifaces[i].ip)) {
  272. add_interface(mem_ctx, &ifaces[i], local_interfaces, enable_ipv6);
  273. }
  274. }
  275. }
  276. while (ptr && *ptr) {
  277. interpret_interface(mem_ctx, *ptr, ifaces, total_probed, local_interfaces, enable_ipv6);
  278. ptr++;
  279. }
  280. if (!*local_interfaces) {
  281. DEBUG(0,("WARNING: no network interfaces found\n"));
  282. }
  283. talloc_free(ifaces);
  284. }
  285. /**
  286. how many interfaces do we have
  287. **/
  288. int iface_list_count(struct interface *ifaces)
  289. {
  290. int ret = 0;
  291. struct interface *i;
  292. for (i=ifaces;i;i=i->next)
  293. ret++;
  294. return ret;
  295. }
  296. /**
  297. return IP of the Nth interface
  298. **/
  299. const char *iface_list_n_ip(struct interface *ifaces, int n)
  300. {
  301. struct interface *i;
  302. for (i=ifaces;i && n;i=i->next)
  303. n--;
  304. if (i) {
  305. return i->ip_s;
  306. }
  307. return NULL;
  308. }
  309. /**
  310. return the first IPv4 interface address we have registered
  311. **/
  312. const char *iface_list_first_v4(struct interface *ifaces)
  313. {
  314. struct interface *i;
  315. for (i=ifaces; i; i=i->next) {
  316. if (i->ip.ss_family == AF_INET) {
  317. return i->ip_s;
  318. }
  319. }
  320. return NULL;
  321. }
  322. /**
  323. return the first IPv6 interface address we have registered
  324. **/
  325. static const char *iface_list_first_v6(struct interface *ifaces)
  326. {
  327. struct interface *i;
  328. #ifdef HAVE_IPV6
  329. for (i=ifaces; i; i=i->next) {
  330. if (i->ip.ss_family == AF_INET6) {
  331. return i->ip_s;
  332. }
  333. }
  334. #endif
  335. return NULL;
  336. }
  337. /**
  338. check if an interface is IPv4
  339. **/
  340. bool iface_list_n_is_v4(struct interface *ifaces, int n)
  341. {
  342. struct interface *i;
  343. for (i=ifaces;i && n;i=i->next)
  344. n--;
  345. if (i) {
  346. return i->ip.ss_family == AF_INET;
  347. }
  348. return false;
  349. }
  350. /**
  351. return bcast of the Nth interface
  352. **/
  353. const char *iface_list_n_bcast(struct interface *ifaces, int n)
  354. {
  355. struct interface *i;
  356. for (i=ifaces;i && n;i=i->next)
  357. n--;
  358. if (i) {
  359. return i->bcast_s;
  360. }
  361. return NULL;
  362. }
  363. /**
  364. return netmask of the Nth interface
  365. **/
  366. const char *iface_list_n_netmask(struct interface *ifaces, int n)
  367. {
  368. struct interface *i;
  369. for (i=ifaces;i && n;i=i->next)
  370. n--;
  371. if (i) {
  372. return i->nmask_s;
  373. }
  374. return NULL;
  375. }
  376. /**
  377. return the local IP address that best matches a destination IP, or
  378. our first interface if none match
  379. */
  380. const char *iface_list_best_ip(struct interface *ifaces, const char *dest)
  381. {
  382. struct interface *iface;
  383. struct sockaddr_storage ss;
  384. if (!interpret_string_addr(&ss, dest, AI_NUMERICHOST)) {
  385. return iface_list_n_ip(ifaces, 0);
  386. }
  387. iface = iface_list_find(ifaces, (const struct sockaddr *)&ss, true);
  388. if (iface) {
  389. return iface->ip_s;
  390. }
  391. #ifdef HAVE_IPV6
  392. if (ss.ss_family == AF_INET6) {
  393. return iface_list_first_v6(ifaces);
  394. }
  395. #endif
  396. return iface_list_first_v4(ifaces);
  397. }
  398. /**
  399. return true if an IP is one one of our local networks
  400. */
  401. bool iface_list_is_local(struct interface *ifaces, const char *dest)
  402. {
  403. struct sockaddr_storage ss;
  404. if (!interpret_string_addr(&ss, dest, AI_NUMERICHOST)) {
  405. return false;
  406. }
  407. if (iface_list_find(ifaces, (const struct sockaddr *)&ss, true)) {
  408. return true;
  409. }
  410. return false;
  411. }
  412. /**
  413. return true if a IP matches a IP/netmask pair
  414. */
  415. bool iface_list_same_net(const char *ip1, const char *ip2, const char *netmask)
  416. {
  417. struct sockaddr_storage ip1_ss, ip2_ss, nm_ss;
  418. if (!interpret_string_addr(&ip1_ss, ip1, AI_NUMERICHOST)) {
  419. return false;
  420. }
  421. if (!interpret_string_addr(&ip2_ss, ip2, AI_NUMERICHOST)) {
  422. return false;
  423. }
  424. if (!interpret_string_addr(&nm_ss, netmask, AI_NUMERICHOST)) {
  425. return false;
  426. }
  427. return same_net((struct sockaddr *)&ip1_ss,
  428. (struct sockaddr *)&ip2_ss,
  429. (struct sockaddr *)&nm_ss);
  430. }
  431. /**
  432. return the list of wildcard interfaces
  433. this will include the IPv4 0.0.0.0, and may include IPv6 ::
  434. it is overridden by the 'socket address' option in smb.conf
  435. */
  436. const char **iface_list_wildcard(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
  437. {
  438. const char **ret;
  439. const char *socket_address;
  440. /* the user may have configured a specific address */
  441. socket_address = lpcfg_socket_address(lp_ctx);
  442. if (strcmp(socket_address, "") != 0) {
  443. ret = (const char **)str_list_make(mem_ctx, socket_address, NULL);
  444. return ret;
  445. }
  446. ret = (const char **)str_list_make(mem_ctx, "0.0.0.0", NULL);
  447. if (ret == NULL) return NULL;
  448. #ifdef HAVE_IPV6
  449. if (lpcfg_parm_bool(lp_ctx, NULL, "ipv6", "enable", true)) {
  450. struct interface *local_interfaces = NULL;
  451. load_interface_list(ret, lp_ctx, &local_interfaces);
  452. if (iface_list_first_v6(local_interfaces)) {
  453. TALLOC_FREE(local_interfaces);
  454. /*
  455. * only add "::" if we have at least
  456. * one ipv6 interface
  457. */
  458. return str_list_add(ret, "::");
  459. }
  460. TALLOC_FREE(local_interfaces);
  461. }
  462. #endif
  463. return ret;
  464. }