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