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

/nmap-6.01/libdnet-stripped/src/route-linux.c

#
C | 283 lines | 223 code | 52 blank | 8 comment | 49 complexity | 452025e045afba99ea36114ca071f42f MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-2.1, BSD-3-Clause
  1. /*
  2. * route-linux.c
  3. *
  4. * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
  5. *
  6. * $Id: route-linux.c 619 2006-01-15 07:33:29Z dugsong $
  7. */
  8. #include "config.h"
  9. #include <sys/types.h>
  10. #include <sys/ioctl.h>
  11. #include <sys/socket.h>
  12. #include <sys/uio.h>
  13. #include <asm/types.h>
  14. #include <netinet/in.h>
  15. #include <linux/netlink.h>
  16. #include <linux/rtnetlink.h>
  17. #include <net/route.h>
  18. #include <ctype.h>
  19. #include <errno.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <unistd.h>
  24. #include "dnet.h"
  25. #define ADDR_ISHOST(a) (((a)->addr_type == ADDR_TYPE_IP && \
  26. (a)->addr_bits == IP_ADDR_BITS) || \
  27. ((a)->addr_type == ADDR_TYPE_IP6 && \
  28. (a)->addr_bits == IP6_ADDR_BITS))
  29. #define PROC_ROUTE_FILE "/proc/net/route"
  30. #define PROC_IPV6_ROUTE_FILE "/proc/net/ipv6_route"
  31. struct route_handle {
  32. int fd;
  33. int nlfd;
  34. };
  35. route_t *
  36. route_open(void)
  37. {
  38. struct sockaddr_nl snl;
  39. route_t *r;
  40. if ((r = calloc(1, sizeof(*r))) != NULL) {
  41. r->fd = r->nlfd = -1;
  42. if ((r->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
  43. return (route_close(r));
  44. if ((r->nlfd = socket(AF_NETLINK, SOCK_RAW,
  45. NETLINK_ROUTE)) < 0)
  46. return (route_close(r));
  47. memset(&snl, 0, sizeof(snl));
  48. snl.nl_family = AF_NETLINK;
  49. if (bind(r->nlfd, (struct sockaddr *)&snl, sizeof(snl)) < 0)
  50. return (route_close(r));
  51. }
  52. return (r);
  53. }
  54. int
  55. route_add(route_t *r, const struct route_entry *entry)
  56. {
  57. struct rtentry rt;
  58. struct addr dst;
  59. memset(&rt, 0, sizeof(rt));
  60. rt.rt_flags = RTF_UP | RTF_GATEWAY;
  61. if (ADDR_ISHOST(&entry->route_dst)) {
  62. rt.rt_flags |= RTF_HOST;
  63. memcpy(&dst, &entry->route_dst, sizeof(dst));
  64. } else
  65. addr_net(&entry->route_dst, &dst);
  66. if (addr_ntos(&dst, &rt.rt_dst) < 0 ||
  67. addr_ntos(&entry->route_gw, &rt.rt_gateway) < 0 ||
  68. addr_btos(entry->route_dst.addr_bits, &rt.rt_genmask) < 0)
  69. return (-1);
  70. return (ioctl(r->fd, SIOCADDRT, &rt));
  71. }
  72. int
  73. route_delete(route_t *r, const struct route_entry *entry)
  74. {
  75. struct rtentry rt;
  76. struct addr dst;
  77. memset(&rt, 0, sizeof(rt));
  78. rt.rt_flags = RTF_UP;
  79. if (ADDR_ISHOST(&entry->route_dst)) {
  80. rt.rt_flags |= RTF_HOST;
  81. memcpy(&dst, &entry->route_dst, sizeof(dst));
  82. } else
  83. addr_net(&entry->route_dst, &dst);
  84. if (addr_ntos(&dst, &rt.rt_dst) < 0 ||
  85. addr_btos(entry->route_dst.addr_bits, &rt.rt_genmask) < 0)
  86. return (-1);
  87. return (ioctl(r->fd, SIOCDELRT, &rt));
  88. }
  89. int
  90. route_get(route_t *r, struct route_entry *entry)
  91. {
  92. static int seq;
  93. struct nlmsghdr *nmsg;
  94. struct rtmsg *rmsg;
  95. struct rtattr *rta;
  96. struct sockaddr_nl snl;
  97. struct iovec iov;
  98. struct msghdr msg;
  99. u_char buf[512];
  100. int i, af, alen;
  101. switch (entry->route_dst.addr_type) {
  102. case ADDR_TYPE_IP:
  103. af = AF_INET;
  104. alen = IP_ADDR_LEN;
  105. break;
  106. case ADDR_TYPE_IP6:
  107. af = AF_INET6;
  108. alen = IP6_ADDR_LEN;
  109. break;
  110. default:
  111. errno = EINVAL;
  112. return (-1);
  113. }
  114. memset(buf, 0, sizeof(buf));
  115. nmsg = (struct nlmsghdr *)buf;
  116. nmsg->nlmsg_len = NLMSG_LENGTH(sizeof(*nmsg)) + RTA_LENGTH(alen);
  117. nmsg->nlmsg_flags = NLM_F_REQUEST;
  118. nmsg->nlmsg_type = RTM_GETROUTE;
  119. nmsg->nlmsg_seq = ++seq;
  120. rmsg = (struct rtmsg *)(nmsg + 1);
  121. rmsg->rtm_family = af;
  122. rmsg->rtm_dst_len = entry->route_dst.addr_bits;
  123. rta = RTM_RTA(rmsg);
  124. rta->rta_type = RTA_DST;
  125. rta->rta_len = RTA_LENGTH(alen);
  126. /* XXX - gross hack for default route */
  127. if (af == AF_INET && entry->route_dst.addr_ip == IP_ADDR_ANY) {
  128. i = htonl(0x60060606);
  129. memcpy(RTA_DATA(rta), &i, alen);
  130. } else
  131. memcpy(RTA_DATA(rta), entry->route_dst.addr_data8, alen);
  132. memset(&snl, 0, sizeof(snl));
  133. snl.nl_family = AF_NETLINK;
  134. iov.iov_base = nmsg;
  135. iov.iov_len = nmsg->nlmsg_len;
  136. memset(&msg, 0, sizeof(msg));
  137. msg.msg_name = &snl;
  138. msg.msg_namelen = sizeof(snl);
  139. msg.msg_iov = &iov;
  140. msg.msg_iovlen = 1;
  141. if (sendmsg(r->nlfd, &msg, 0) < 0)
  142. return (-1);
  143. iov.iov_base = buf;
  144. iov.iov_len = sizeof(buf);
  145. if ((i = recvmsg(r->nlfd, &msg, 0)) <= 0)
  146. return (-1);
  147. if (nmsg->nlmsg_len < (int)sizeof(*nmsg) || nmsg->nlmsg_len > i ||
  148. nmsg->nlmsg_seq != seq) {
  149. errno = EINVAL;
  150. return (-1);
  151. }
  152. if (nmsg->nlmsg_type == NLMSG_ERROR)
  153. return (-1);
  154. i -= NLMSG_LENGTH(sizeof(*nmsg));
  155. while (RTA_OK(rta, i)) {
  156. if (rta->rta_type == RTA_GATEWAY) {
  157. entry->route_gw.addr_type = entry->route_dst.addr_type;
  158. memcpy(entry->route_gw.addr_data8, RTA_DATA(rta), alen);
  159. entry->route_gw.addr_bits = alen * 8;
  160. return (0);
  161. }
  162. rta = RTA_NEXT(rta, i);
  163. }
  164. errno = ESRCH;
  165. return (-1);
  166. }
  167. int
  168. route_loop(route_t *r, route_handler callback, void *arg)
  169. {
  170. FILE *fp;
  171. struct route_entry entry;
  172. char buf[BUFSIZ];
  173. int ret = 0;
  174. if ((fp = fopen(PROC_ROUTE_FILE, "r")) != NULL) {
  175. char ifbuf[16];
  176. int i, iflags, refcnt, use, metric, mss, win, irtt;
  177. uint32_t mask;
  178. while (fgets(buf, sizeof(buf), fp) != NULL) {
  179. i = sscanf(buf, "%16s %X %X %X %d %d %d %X %d %d %d\n",
  180. ifbuf, &entry.route_dst.addr_ip,
  181. &entry.route_gw.addr_ip, &iflags, &refcnt, &use,
  182. &metric, &mask, &mss, &win, &irtt);
  183. if (i < 10 || !(iflags & RTF_UP))
  184. continue;
  185. entry.route_dst.addr_type = entry.route_gw.addr_type =
  186. ADDR_TYPE_IP;
  187. if (addr_mtob(&mask, IP_ADDR_LEN,
  188. &entry.route_dst.addr_bits) < 0)
  189. continue;
  190. entry.route_gw.addr_bits = IP_ADDR_BITS;
  191. if ((ret = callback(&entry, arg)) != 0)
  192. break;
  193. }
  194. fclose(fp);
  195. }
  196. if (ret == 0 && (fp = fopen(PROC_IPV6_ROUTE_FILE, "r")) != NULL) {
  197. char s[33], d[8][5], n[8][5];
  198. u_int slen, dlen;
  199. while (fgets(buf, sizeof(buf), fp) != NULL) {
  200. sscanf(buf, "%04s%04s%04s%04s%04s%04s%04s%04s %02x "
  201. "%32s %02x %04s%04s%04s%04s%04s%04s%04s%04s ",
  202. d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
  203. &dlen, s, &slen,
  204. n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]);
  205. snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s/%d",
  206. d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
  207. dlen);
  208. addr_aton(buf, &entry.route_dst);
  209. snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s/%d",
  210. n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7],
  211. IP6_ADDR_BITS);
  212. addr_aton(buf, &entry.route_gw);
  213. if ((ret = callback(&entry, arg)) != 0)
  214. break;
  215. }
  216. fclose(fp);
  217. }
  218. return (ret);
  219. }
  220. route_t *
  221. route_close(route_t *r)
  222. {
  223. if (r != NULL) {
  224. if (r->fd >= 0)
  225. close(r->fd);
  226. if (r->nlfd >= 0)
  227. close(r->nlfd);
  228. free(r);
  229. }
  230. return (NULL);
  231. }