utils.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * utils.c
  4. *
  5. * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  6. *
  7. * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  8. *
  9. * Changes:
  10. *
  11. * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses
  12. */
  13. #include "libbb.h"
  14. #include "utils.h"
  15. #include "inet_common.h"
  16. int get_integer(int *val, char *arg, int base)
  17. {
  18. long res;
  19. char *ptr;
  20. if (!arg || !*arg)
  21. return -1;
  22. res = strtol(arg, &ptr, base);
  23. if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
  24. return -1;
  25. *val = res;
  26. return 0;
  27. }
  28. //XXX: FIXME: use some libbb function instead
  29. int get_unsigned(unsigned *val, char *arg, int base)
  30. {
  31. unsigned long res;
  32. char *ptr;
  33. if (!arg || !*arg)
  34. return -1;
  35. res = strtoul(arg, &ptr, base);
  36. if (!ptr || ptr == arg || *ptr || res > UINT_MAX)
  37. return -1;
  38. *val = res;
  39. return 0;
  40. }
  41. int get_u32(uint32_t * val, char *arg, int base)
  42. {
  43. unsigned long res;
  44. char *ptr;
  45. if (!arg || !*arg)
  46. return -1;
  47. res = strtoul(arg, &ptr, base);
  48. if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL)
  49. return -1;
  50. *val = res;
  51. return 0;
  52. }
  53. int get_u16(uint16_t * val, char *arg, int base)
  54. {
  55. unsigned long res;
  56. char *ptr;
  57. if (!arg || !*arg)
  58. return -1;
  59. res = strtoul(arg, &ptr, base);
  60. if (!ptr || ptr == arg || *ptr || res > 0xFFFF)
  61. return -1;
  62. *val = res;
  63. return 0;
  64. }
  65. int get_u8(uint8_t * val, char *arg, int base)
  66. {
  67. unsigned long res;
  68. char *ptr;
  69. if (!arg || !*arg)
  70. return -1;
  71. res = strtoul(arg, &ptr, base);
  72. if (!ptr || ptr == arg || *ptr || res > 0xFF)
  73. return -1;
  74. *val = res;
  75. return 0;
  76. }
  77. int get_s16(int16_t * val, char *arg, int base)
  78. {
  79. long res;
  80. char *ptr;
  81. if (!arg || !*arg)
  82. return -1;
  83. res = strtol(arg, &ptr, base);
  84. if (!ptr || ptr == arg || *ptr || res > 0x7FFF || res < -0x8000)
  85. return -1;
  86. *val = res;
  87. return 0;
  88. }
  89. int get_s8(int8_t * val, char *arg, int base)
  90. {
  91. long res;
  92. char *ptr;
  93. if (!arg || !*arg)
  94. return -1;
  95. res = strtol(arg, &ptr, base);
  96. if (!ptr || ptr == arg || *ptr || res > 0x7F || res < -0x80)
  97. return -1;
  98. *val = res;
  99. return 0;
  100. }
  101. int get_addr_1(inet_prefix * addr, char *name, int family)
  102. {
  103. memset(addr, 0, sizeof(*addr));
  104. if (strcmp(name, bb_str_default) == 0 ||
  105. strcmp(name, "all") == 0 || strcmp(name, "any") == 0) {
  106. addr->family = family;
  107. addr->bytelen = (family == AF_INET6 ? 16 : 4);
  108. addr->bitlen = -1;
  109. return 0;
  110. }
  111. if (strchr(name, ':')) {
  112. addr->family = AF_INET6;
  113. if (family != AF_UNSPEC && family != AF_INET6)
  114. return -1;
  115. if (inet_pton(AF_INET6, name, addr->data) <= 0)
  116. return -1;
  117. addr->bytelen = 16;
  118. addr->bitlen = -1;
  119. return 0;
  120. }
  121. addr->family = AF_INET;
  122. if (family != AF_UNSPEC && family != AF_INET)
  123. return -1;
  124. if (inet_pton(AF_INET, name, addr->data) <= 0)
  125. return -1;
  126. addr->bytelen = 4;
  127. addr->bitlen = -1;
  128. return 0;
  129. }
  130. int get_prefix_1(inet_prefix * dst, char *arg, int family)
  131. {
  132. int err;
  133. unsigned plen;
  134. char *slash;
  135. memset(dst, 0, sizeof(*dst));
  136. if (strcmp(arg, bb_str_default) == 0 || strcmp(arg, "any") == 0) {
  137. dst->family = family;
  138. dst->bytelen = 0;
  139. dst->bitlen = 0;
  140. return 0;
  141. }
  142. slash = strchr(arg, '/');
  143. if (slash)
  144. *slash = '\0';
  145. err = get_addr_1(dst, arg, family);
  146. if (err == 0) {
  147. dst->bitlen = (dst->family == AF_INET6) ? 128 : 32;
  148. if (slash) {
  149. inet_prefix netmask_pfx;
  150. netmask_pfx.family = AF_UNSPEC;
  151. if ((get_unsigned(&plen, slash + 1, 0) || plen > dst->bitlen)
  152. && (get_addr_1(&netmask_pfx, slash + 1, family)))
  153. err = -1;
  154. else if (netmask_pfx.family == AF_INET) {
  155. /* fill in prefix length of dotted quad */
  156. uint32_t mask = ntohl(netmask_pfx.data[0]);
  157. uint32_t host = ~mask;
  158. /* a valid netmask must be 2^n - 1 */
  159. if (!(host & (host + 1))) {
  160. for (plen = 0; mask; mask <<= 1)
  161. ++plen;
  162. if (plen >= 0 && plen <= dst->bitlen) {
  163. dst->bitlen = plen;
  164. /* dst->flags |= PREFIXLEN_SPECIFIED; */
  165. } else
  166. err = -1;
  167. } else
  168. err = -1;
  169. } else {
  170. /* plain prefix */
  171. dst->bitlen = plen;
  172. }
  173. }
  174. }
  175. if (slash)
  176. *slash = '/';
  177. return err;
  178. }
  179. int get_addr(inet_prefix * dst, char *arg, int family)
  180. {
  181. if (family == AF_PACKET) {
  182. bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "address");
  183. }
  184. if (get_addr_1(dst, arg, family)) {
  185. bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "address", arg);
  186. }
  187. return 0;
  188. }
  189. int get_prefix(inet_prefix * dst, char *arg, int family)
  190. {
  191. if (family == AF_PACKET) {
  192. bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "prefix");
  193. }
  194. if (get_prefix_1(dst, arg, family)) {
  195. bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "prefix", arg);
  196. }
  197. return 0;
  198. }
  199. uint32_t get_addr32(char *name)
  200. {
  201. inet_prefix addr;
  202. if (get_addr_1(&addr, name, AF_INET)) {
  203. bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "IP", "address", name);
  204. }
  205. return addr.data[0];
  206. }
  207. void incomplete_command(void)
  208. {
  209. bb_error_msg_and_die("command line is not complete, try option \"help\"");
  210. }
  211. void invarg(const char *arg, const char *opt)
  212. {
  213. bb_error_msg_and_die(bb_msg_invalid_arg, arg, opt);
  214. }
  215. void duparg(const char *key, const char *arg)
  216. {
  217. bb_error_msg_and_die("duplicate \"%s\": \"%s\" is the second value", key, arg);
  218. }
  219. void duparg2(const char *key, const char *arg)
  220. {
  221. bb_error_msg_and_die("either \"%s\" is duplicate, or \"%s\" is garbage", key, arg);
  222. }
  223. int inet_addr_match(inet_prefix * a, inet_prefix * b, int bits)
  224. {
  225. uint32_t *a1 = a->data;
  226. uint32_t *a2 = b->data;
  227. int words = bits >> 0x05;
  228. bits &= 0x1f;
  229. if (words)
  230. if (memcmp(a1, a2, words << 2))
  231. return -1;
  232. if (bits) {
  233. uint32_t w1, w2;
  234. uint32_t mask;
  235. w1 = a1[words];
  236. w2 = a2[words];
  237. mask = htonl((0xffffffff) << (0x20 - bits));
  238. if ((w1 ^ w2) & mask)
  239. return 1;
  240. }
  241. return 0;
  242. }
  243. const char *rt_addr_n2a(int af, int UNUSED_PARAM len,
  244. void *addr, char *buf, int buflen)
  245. {
  246. switch (af) {
  247. case AF_INET:
  248. case AF_INET6:
  249. return inet_ntop(af, addr, buf, buflen);
  250. default:
  251. return "???";
  252. }
  253. }
  254. const char *format_host(int af, int len, void *addr, char *buf, int buflen)
  255. {
  256. #ifdef RESOLVE_HOSTNAMES
  257. if (resolve_hosts) {
  258. struct hostent *h_ent;
  259. if (len <= 0) {
  260. switch (af) {
  261. case AF_INET:
  262. len = 4;
  263. break;
  264. case AF_INET6:
  265. len = 16;
  266. break;
  267. default:;
  268. }
  269. }
  270. if (len > 0) {
  271. h_ent = gethostbyaddr(addr, len, af);
  272. if (h_ent != NULL) {
  273. safe_strncpy(buf, h_ent->h_name, buflen);
  274. return buf;
  275. }
  276. }
  277. }
  278. #endif
  279. return rt_addr_n2a(af, len, addr, buf, buflen);
  280. }