utils.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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. char *cp;
  104. unsigned char *ap = (unsigned char *) addr->data;
  105. int i;
  106. memset(addr, 0, sizeof(*addr));
  107. if (strcmp(name, bb_str_default) == 0 ||
  108. strcmp(name, "all") == 0 || strcmp(name, "any") == 0) {
  109. addr->family = family;
  110. addr->bytelen = (family == AF_INET6 ? 16 : 4);
  111. addr->bitlen = -1;
  112. return 0;
  113. }
  114. if (strchr(name, ':')) {
  115. addr->family = AF_INET6;
  116. if (family != AF_UNSPEC && family != AF_INET6)
  117. return -1;
  118. if (inet_pton(AF_INET6, name, addr->data) <= 0)
  119. return -1;
  120. addr->bytelen = 16;
  121. addr->bitlen = -1;
  122. return 0;
  123. }
  124. addr->family = AF_INET;
  125. if (family != AF_UNSPEC && family != AF_INET)
  126. return -1;
  127. addr->bytelen = 4;
  128. addr->bitlen = -1;
  129. for (cp = name, i = 0; *cp; cp++) {
  130. if (*cp <= '9' && *cp >= '0') {
  131. ap[i] = 10 * ap[i] + (*cp - '0');
  132. continue;
  133. }
  134. if (*cp == '.' && ++i <= 3)
  135. continue;
  136. return -1;
  137. }
  138. return 0;
  139. }
  140. int get_prefix_1(inet_prefix * dst, char *arg, int family)
  141. {
  142. int err;
  143. int plen;
  144. char *slash;
  145. memset(dst, 0, sizeof(*dst));
  146. if (strcmp(arg, bb_str_default) == 0 || strcmp(arg, "any") == 0) {
  147. dst->family = family;
  148. dst->bytelen = 0;
  149. dst->bitlen = 0;
  150. return 0;
  151. }
  152. slash = strchr(arg, '/');
  153. if (slash)
  154. *slash = '\0';
  155. err = get_addr_1(dst, arg, family);
  156. if (err == 0) {
  157. switch (dst->family) {
  158. case AF_INET6:
  159. dst->bitlen = 128;
  160. break;
  161. default:
  162. case AF_INET:
  163. dst->bitlen = 32;
  164. }
  165. if (slash) {
  166. if (get_integer(&plen, slash + 1, 0) || plen > dst->bitlen) {
  167. err = -1;
  168. goto done;
  169. }
  170. dst->bitlen = plen;
  171. }
  172. }
  173. done:
  174. if (slash)
  175. *slash = '/';
  176. return err;
  177. }
  178. int get_addr(inet_prefix * dst, char *arg, int family)
  179. {
  180. if (family == AF_PACKET) {
  181. bb_error_msg_and_die("\"%s\" may be inet address, but it is not allowed in this context", arg);
  182. }
  183. if (get_addr_1(dst, arg, family)) {
  184. bb_error_msg_and_die("an inet address is expected rather than \"%s\"", arg);
  185. }
  186. return 0;
  187. }
  188. int get_prefix(inet_prefix * dst, char *arg, int family)
  189. {
  190. if (family == AF_PACKET) {
  191. bb_error_msg_and_die("\"%s\" may be inet address, but it is not allowed in this context", arg);
  192. }
  193. if (get_prefix_1(dst, arg, family)) {
  194. bb_error_msg_and_die("an inet address is expected rather than \"%s\"", arg);
  195. }
  196. return 0;
  197. }
  198. uint32_t get_addr32(char *name)
  199. {
  200. inet_prefix addr;
  201. if (get_addr_1(&addr, name, AF_INET)) {
  202. bb_error_msg_and_die("an IP address is expected rather than \"%s\"", name);
  203. }
  204. return addr.data[0];
  205. }
  206. void incomplete_command(void)
  207. {
  208. bb_error_msg_and_die("command line is not complete, try option \"help\"");
  209. }
  210. void invarg(const char *arg, const char *opt)
  211. {
  212. bb_error_msg_and_die(bb_msg_invalid_arg, arg, opt);
  213. }
  214. void duparg(const char *key, const char *arg)
  215. {
  216. bb_error_msg_and_die("duplicate \"%s\": \"%s\" is the second value", key, arg);
  217. }
  218. void duparg2(const char *key, const char *arg)
  219. {
  220. bb_error_msg_and_die("either \"%s\" is duplicate, or \"%s\" is garbage", key, arg);
  221. }
  222. int inet_addr_match(inet_prefix * a, inet_prefix * b, int bits)
  223. {
  224. uint32_t *a1 = a->data;
  225. uint32_t *a2 = b->data;
  226. int words = bits >> 0x05;
  227. bits &= 0x1f;
  228. if (words)
  229. if (memcmp(a1, a2, words << 2))
  230. return -1;
  231. if (bits) {
  232. uint32_t w1, w2;
  233. uint32_t mask;
  234. w1 = a1[words];
  235. w2 = a2[words];
  236. mask = htonl((0xffffffff) << (0x20 - bits));
  237. if ((w1 ^ w2) & mask)
  238. return 1;
  239. }
  240. return 0;
  241. }
  242. const char *rt_addr_n2a(int af, int ATTRIBUTE_UNUSED len,
  243. void *addr, char *buf, int buflen)
  244. {
  245. switch (af) {
  246. case AF_INET:
  247. case AF_INET6:
  248. return inet_ntop(af, addr, buf, buflen);
  249. default:
  250. return "???";
  251. }
  252. }
  253. const char *format_host(int af, int len, void *addr, char *buf, int buflen)
  254. {
  255. #ifdef RESOLVE_HOSTNAMES
  256. if (resolve_hosts) {
  257. struct hostent *h_ent;
  258. if (len <= 0) {
  259. switch (af) {
  260. case AF_INET:
  261. len = 4;
  262. break;
  263. case AF_INET6:
  264. len = 16;
  265. break;
  266. default:;
  267. }
  268. }
  269. if (len > 0) {
  270. h_ent = gethostbyaddr(addr, len, af);
  271. if (h_ent != NULL) {
  272. safe_strncpy(buf, h_ent->h_name, buflen);
  273. return buf;
  274. }
  275. }
  276. }
  277. #endif
  278. return rt_addr_n2a(af, len, addr, buf, buflen);
  279. }