1*13885a66Sdarrenr /* $NetBSD: getport.c,v 1.2 2012/07/22 14:27:36 darrenr Exp $ */
2bc4097aaSchristos
3bc4097aaSchristos /*
4c9d5dc6cSdarrenr * Copyright (C) 2012 by Darren Reed.
5bc4097aaSchristos *
6bc4097aaSchristos * See the IPFILTER.LICENCE file for details on licencing.
7bc4097aaSchristos *
8*13885a66Sdarrenr * Id: getport.c,v 1.1.1.2 2012/07/22 13:44:38 darrenr Exp $
9bc4097aaSchristos */
10bc4097aaSchristos
11bc4097aaSchristos #include "ipf.h"
12bc4097aaSchristos #include <ctype.h>
13bc4097aaSchristos
getport(fr,name,port,proto)14bc4097aaSchristos int getport(fr, name, port, proto)
15bc4097aaSchristos frentry_t *fr;
16bc4097aaSchristos char *name, *proto;
17bc4097aaSchristos u_short *port;
18bc4097aaSchristos {
19bc4097aaSchristos struct protoent *p;
20bc4097aaSchristos struct servent *s;
21bc4097aaSchristos u_short p1;
22bc4097aaSchristos
23bc4097aaSchristos if (fr == NULL || fr->fr_type != FR_T_IPF) {
24bc4097aaSchristos s = getservbyname(name, proto);
25bc4097aaSchristos if (s != NULL) {
26bc4097aaSchristos *port = s->s_port;
27bc4097aaSchristos return 0;
28bc4097aaSchristos }
29bc4097aaSchristos
30bc4097aaSchristos if (ISDIGIT(*name)) {
31bc4097aaSchristos int portval = atoi(name);
32bc4097aaSchristos if (portval < 0 || portval > 65535)
33bc4097aaSchristos return -1;
34bc4097aaSchristos *port = htons((u_short)portval);
35bc4097aaSchristos return 0;
36bc4097aaSchristos }
37bc4097aaSchristos return -1;
38bc4097aaSchristos }
39bc4097aaSchristos
40bc4097aaSchristos /*
41bc4097aaSchristos * Some people will use port names in rules without specifying
42bc4097aaSchristos * either TCP or UDP because it is implied by the group head.
43bc4097aaSchristos * If we don't know the protocol, then the best we can do here is
44bc4097aaSchristos * to take either only the TCP or UDP mapping (if one or the other
45bc4097aaSchristos * is missing) or make sure both of them agree.
46bc4097aaSchristos */
47bc4097aaSchristos if (fr->fr_proto == 0) {
48bc4097aaSchristos s = getservbyname(name, "tcp");
49bc4097aaSchristos if (s != NULL)
50bc4097aaSchristos p1 = s->s_port;
51bc4097aaSchristos else
52bc4097aaSchristos p1 = 0;
53bc4097aaSchristos s = getservbyname(name, "udp");
54bc4097aaSchristos if (s != NULL) {
55bc4097aaSchristos if (p1 != s->s_port)
56bc4097aaSchristos return -1;
57bc4097aaSchristos }
58bc4097aaSchristos if ((p1 == 0) && (s == NULL))
59bc4097aaSchristos return -1;
60bc4097aaSchristos if (p1)
61bc4097aaSchristos *port = p1;
62bc4097aaSchristos else
63bc4097aaSchristos *port = s->s_port;
64bc4097aaSchristos return 0;
65bc4097aaSchristos }
66bc4097aaSchristos
67bc4097aaSchristos if ((fr->fr_flx & FI_TCPUDP) != 0) {
68bc4097aaSchristos /*
69bc4097aaSchristos * If a rule is "tcp/udp" then check that both TCP and UDP
70bc4097aaSchristos * mappings for this protocol name match ports.
71bc4097aaSchristos */
72bc4097aaSchristos s = getservbyname(name, "tcp");
73bc4097aaSchristos if (s == NULL)
74bc4097aaSchristos return -1;
75bc4097aaSchristos p1 = s->s_port;
76bc4097aaSchristos s = getservbyname(name, "udp");
77bc4097aaSchristos if (s == NULL || s->s_port != p1)
78bc4097aaSchristos return -1;
79bc4097aaSchristos *port = p1;
80bc4097aaSchristos return 0;
81bc4097aaSchristos }
82bc4097aaSchristos
83bc4097aaSchristos p = getprotobynumber(fr->fr_proto);
84bc4097aaSchristos s = getservbyname(name, p ? p->p_name : NULL);
85bc4097aaSchristos if (s != NULL) {
86bc4097aaSchristos *port = s->s_port;
87bc4097aaSchristos return 0;
88bc4097aaSchristos }
89bc4097aaSchristos return -1;
90bc4097aaSchristos }
91