getport.c revision 161357
1/*	$FreeBSD: head/contrib/ipfilter/lib/getport.c 161357 2006-08-16 12:23:02Z guido $	*/
2
3#include "ipf.h"
4
5int getport(fr, name, port)
6frentry_t *fr;
7char *name;
8u_short *port;
9{
10	struct protoent *p;
11	struct servent *s;
12	u_short p1;
13
14	if (fr == NULL || fr->fr_type != FR_T_IPF) {
15		s = getservbyname(name, NULL);
16		if (s != NULL) {
17			*port = s->s_port;
18			return 0;
19		}
20		return -1;
21	}
22
23	/*
24	 * Some people will use port names in rules without specifying
25	 * either TCP or UDP because it is implied by the group head.
26	 * If we don't know the protocol, then the best we can do here is
27	 * to take either only the TCP or UDP mapping (if one or the other
28	 * is missing) or make sure both of them agree.
29	 */
30	if (fr->fr_proto == 0) {
31		s = getservbyname(name, "tcp");
32		if (s != NULL)
33			p1 = s->s_port;
34		else
35			p1 = 0;
36		s = getservbyname(name, "udp");
37		if (s != NULL) {
38			if (p1 != s->s_port)
39				return -1;
40		}
41		if ((p1 == 0) && (s == NULL))
42			return -1;
43		if (p1)
44			*port = p1;
45		else
46			*port = s->s_port;
47		return 0;
48	}
49
50	if ((fr->fr_flx & FI_TCPUDP) != 0) {
51		/*
52		 * If a rule is "tcp/udp" then check that both TCP and UDP
53		 * mappings for this protocol name match ports.
54		 */
55		s = getservbyname(name, "tcp");
56		if (s == NULL)
57			return -1;
58		p1 = s->s_port;
59		s = getservbyname(name, "udp");
60		if (s == NULL || s->s_port != p1)
61			return -1;
62		*port = p1;
63		return 0;
64	}
65
66	p = getprotobynumber(fr->fr_proto);
67	s = getservbyname(name, p ? p->p_name : NULL);
68	if (s != NULL) {
69		*port = s->s_port;
70		return 0;
71	}
72	return -1;
73}
74