lookup_serv.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #include <sys/socket.h>
  2. #include <netinet/in.h>
  3. #include <netdb.h>
  4. #include <ctype.h>
  5. #include <string.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <fcntl.h>
  9. #include <errno.h>
  10. #include "lookup.h"
  11. int __lookup_serv(struct service buf[static MAXSERVS], const char *name, int proto, int socktype, int flags)
  12. {
  13. char line[128];
  14. int cnt = 0;
  15. char *p, *z = "";
  16. unsigned long port = 0;
  17. switch (socktype) {
  18. case SOCK_STREAM:
  19. switch (proto) {
  20. case 0:
  21. proto = IPPROTO_TCP;
  22. case IPPROTO_TCP:
  23. break;
  24. default:
  25. return EAI_SERVICE;
  26. }
  27. break;
  28. case SOCK_DGRAM:
  29. switch (proto) {
  30. case 0:
  31. proto = IPPROTO_UDP;
  32. case IPPROTO_UDP:
  33. break;
  34. default:
  35. return EAI_SERVICE;
  36. }
  37. case 0:
  38. break;
  39. default:
  40. if (name) return EAI_SERVICE;
  41. buf[0].port = 0;
  42. buf[0].proto = proto;
  43. buf[0].socktype = socktype;
  44. return 1;
  45. }
  46. if (name) {
  47. if (!*name) return EAI_SERVICE;
  48. port = strtoul(name, &z, 10);
  49. }
  50. if (!*z) {
  51. if (port > 65535) return EAI_SERVICE;
  52. if (proto != IPPROTO_UDP) {
  53. buf[cnt].port = port;
  54. buf[cnt].socktype = SOCK_STREAM;
  55. buf[cnt++].proto = IPPROTO_TCP;
  56. }
  57. if (proto != IPPROTO_TCP) {
  58. buf[cnt].port = port;
  59. buf[cnt].socktype = SOCK_DGRAM;
  60. buf[cnt++].proto = IPPROTO_UDP;
  61. }
  62. return cnt;
  63. }
  64. if (flags & AI_NUMERICSERV) return EAI_NONAME;
  65. size_t l = strlen(name);
  66. FILE *f = fopen("/etc/services", "rb");
  67. if (!f) switch (errno) {
  68. case ENOENT:
  69. case ENOTDIR:
  70. case EACCES:
  71. return EAI_SERVICE;
  72. default:
  73. return EAI_SYSTEM;
  74. }
  75. while (fgets(line, sizeof line, f) && cnt < MAXSERVS) {
  76. if ((p=strchr(line, '#'))) *p++='\n', *p=0;
  77. /* Find service name */
  78. for(p=line; (p=strstr(p, name)); p++) {
  79. if (p>line && !isspace(p[-1])) continue;
  80. if (p[l] && !isspace(p[l])) continue;
  81. break;
  82. }
  83. if (!p) continue;
  84. /* Skip past canonical name at beginning of line */
  85. for (p=line; *p && !isspace(*p); p++);
  86. port = strtoul(p, &z, 10);
  87. if (port > 65535 || z==p) continue;
  88. if (!strncmp(z, "/udp", 4)) {
  89. if (proto == IPPROTO_TCP) continue;
  90. buf[cnt].port = port;
  91. buf[cnt].socktype = SOCK_DGRAM;
  92. buf[cnt++].proto = IPPROTO_UDP;
  93. }
  94. if (!strncmp(z, "/tcp", 4)) {
  95. if (proto == IPPROTO_UDP) continue;
  96. buf[cnt].port = port;
  97. buf[cnt].socktype = SOCK_STREAM;
  98. buf[cnt++].proto = IPPROTO_TCP;
  99. }
  100. }
  101. fclose(f);
  102. return cnt > 0 ? cnt : EAI_SERVICE;
  103. }