OLD | NEW |
(Empty) | |
| 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 |
| 9 int getservbyport_r(int port, const char *prots, |
| 10 struct servent *se, char *buf, size_t buflen, struct servent **res) |
| 11 { |
| 12 int i; |
| 13 struct sockaddr_in sin = { |
| 14 .sin_family = AF_INET, |
| 15 .sin_port = port, |
| 16 }; |
| 17 |
| 18 if (!prots) { |
| 19 int r = getservbyport_r(port, "tcp", se, buf, buflen, res); |
| 20 if (r) r = getservbyport_r(port, "udp", se, buf, buflen, res); |
| 21 return r; |
| 22 } |
| 23 |
| 24 /* Align buffer */ |
| 25 i = (uintptr_t)buf & sizeof(char *)-1; |
| 26 if (!i) i = sizeof(char *); |
| 27 if (buflen < 3*sizeof(char *)-i) |
| 28 return ERANGE; |
| 29 buf += sizeof(char *)-i; |
| 30 buflen -= sizeof(char *)-i; |
| 31 |
| 32 if (strcmp(prots, "tcp") && strcmp(prots, "udp")) return EINVAL; |
| 33 |
| 34 se->s_port = port; |
| 35 se->s_proto = (char *)prots; |
| 36 se->s_aliases = (void *)buf; |
| 37 buf += 2*sizeof(char *); |
| 38 buflen -= 2*sizeof(char *); |
| 39 se->s_aliases[1] = 0; |
| 40 se->s_aliases[0] = se->s_name = buf; |
| 41 |
| 42 switch (getnameinfo((void *)&sin, sizeof sin, 0, 0, buf, buflen, |
| 43 strcmp(prots, "udp") ? 0 : NI_DGRAM)) { |
| 44 case EAI_MEMORY: |
| 45 case EAI_SYSTEM: |
| 46 return ENOMEM; |
| 47 default: |
| 48 return ENOENT; |
| 49 case 0: |
| 50 break; |
| 51 } |
| 52 |
| 53 *res = se; |
| 54 return 0; |
| 55 } |
OLD | NEW |