github.com/afumu/libc@v0.0.6/musl/src/network/getservbyport_r.c (about) 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 #include <stdlib.h> 9 10 int getservbyport_r(int port, const char *prots, 11 struct servent *se, char *buf, size_t buflen, struct servent **res) 12 { 13 int i; 14 struct sockaddr_in sin = { 15 .sin_family = AF_INET, 16 .sin_port = port, 17 }; 18 19 if (!prots) { 20 int r = getservbyport_r(port, "tcp", se, buf, buflen, res); 21 if (r) r = getservbyport_r(port, "udp", se, buf, buflen, res); 22 return r; 23 } 24 *res = 0; 25 26 /* Align buffer */ 27 i = (uintptr_t)buf & sizeof(char *)-1; 28 if (!i) i = sizeof(char *); 29 if (buflen < 3*sizeof(char *)-i) 30 return ERANGE; 31 buf += sizeof(char *)-i; 32 buflen -= sizeof(char *)-i; 33 34 if (strcmp(prots, "tcp") && strcmp(prots, "udp")) return EINVAL; 35 36 se->s_port = port; 37 se->s_proto = (char *)prots; 38 se->s_aliases = (void *)buf; 39 buf += 2*sizeof(char *); 40 buflen -= 2*sizeof(char *); 41 se->s_aliases[1] = 0; 42 se->s_aliases[0] = se->s_name = buf; 43 44 switch (getnameinfo((void *)&sin, sizeof sin, 0, 0, buf, buflen, 45 strcmp(prots, "udp") ? 0 : NI_DGRAM)) { 46 case EAI_MEMORY: 47 case EAI_SYSTEM: 48 return ENOMEM; 49 default: 50 return ENOENT; 51 case 0: 52 break; 53 } 54 55 /* A numeric port string is not a service record. */ 56 if (strtol(buf, 0, 10)==ntohs(port)) return ENOENT; 57 58 *res = se; 59 return 0; 60 }