]> Pileus Git - ~andy/fetchmail/blob - servport.c
Minor bug fixes for socket.c
[~andy/fetchmail] / servport.c
1 /** \file servport.c Resolve service name to port number.
2  * \author Matthias Andree
3  * \date 2005 - 2006
4  *
5  * Copyright (C) 2005 by Matthias Andree
6  * For license terms, see the file COPYING in this directory.
7  */
8 #include "fetchmail.h"
9 #include "getaddrinfo.h"
10 #include "i18n.h"
11
12 #include <errno.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/types.h>
16 #include <netdb.h>
17 #if defined(HAVE_NETINET_IN_H)
18 #include <netinet/in.h>
19 #endif
20 #ifdef HAVE_ARPA_INET_H
21 #include <arpa/inet.h>
22 #endif
23 #include <sys/socket.h>
24
25 int servport(const char *service) {
26     int port, e;
27     unsigned long u;
28     char *end;
29
30     if (service == 0)
31         return -1;
32
33     /*
34      * Check if the service is a number. If so, convert it.
35      * If it isn't a number, call getservbyname to resolve it.
36      */
37     errno = 0;
38     u = strtoul(service, &end, 10);
39     if (errno || end[strspn(end, POSIX_space)] != '\0') {
40         struct addrinfo hints, *res;
41
42         /* hardcode kpop to port 1109 as per fetchmail(1)
43          * manual page, it's not a IANA registered service */
44         if (strcmp(service, "kpop") == 0)
45             return 1109;
46
47         memset(&hints, 0, sizeof hints);
48         hints.ai_family = AF_UNSPEC;
49         hints.ai_socktype = SOCK_STREAM;
50         hints.ai_protocol = IPPROTO_TCP;
51         e = fm_getaddrinfo(NULL, service, &hints, &res);
52         if (e) {
53             report(stderr, GT_("getaddrinfo(NULL, \"%s\") error: %s\n"),
54                     service, gai_strerror(e));
55             goto err;
56         } else {
57             switch(res->ai_addr->sa_family) {
58                 case AF_INET:
59                     port = ntohs(((struct sockaddr_in *)res->ai_addr)->sin_port);
60                 break;
61 #ifdef AF_INET6
62                 case AF_INET6:
63                     port = ntohs(((struct sockaddr_in6 *)res->ai_addr)->sin6_port);
64                 break;
65 #endif
66                 default:
67                     fm_freeaddrinfo(res);
68                     goto err;
69             }
70             fm_freeaddrinfo(res);
71         }
72     } else {
73         if (u == 0 || u > 65535)
74             goto err;
75         port = u;
76     }
77
78     return port;
79 err:
80     report(stderr, GT_("Cannot resolve service %s to port number.\n"), service);
81     report(stderr, GT_("Please specify the service as decimal port number.\n"));
82     return -1;
83 }
84 /* end of servport.c */