getservbyname_r.c 1003 B

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. #define _GNU_SOURCE
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <netdb.h>
  5. #include <inttypes.h>
  6. #include <errno.h>
  7. #include <string.h>
  8. int getservbyname_r(const char *name, const char *prots,
  9. struct servent *se, char *buf, size_t buflen, struct servent **res)
  10. {
  11. struct addrinfo *ai, hint = { .ai_family = AF_INET };
  12. int i;
  13. /* Align buffer */
  14. i = (uintptr_t)buf & sizeof(char *)-1;
  15. if (!i) i = sizeof(char *);
  16. if (buflen < 3*sizeof(char *)-i) {
  17. errno = ERANGE;
  18. return -1;
  19. }
  20. buf += sizeof(char *)-i;
  21. buflen -= sizeof(char *)-i;
  22. if (!strcmp(prots, "tcp")) hint.ai_protocol = IPPROTO_TCP;
  23. else if (!strcmp(prots, "udp")) hint.ai_protocol = IPPROTO_UDP;
  24. else return -1;
  25. if (getaddrinfo(0, name, &hint, &ai) < 0) return -1;
  26. se->s_name = (char *)name;
  27. se->s_aliases = (void *)buf;
  28. se->s_aliases[0] = se->s_name;
  29. se->s_aliases[1] = 0;
  30. se->s_port = ((struct sockaddr_in *)ai->ai_addr)->sin_port;
  31. se->s_proto = (char *)prots;
  32. freeaddrinfo(ai);
  33. *res = se;
  34. return 0;
  35. }