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