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 */