1145519Sdarrenr/* $FreeBSD: releng/10.3/contrib/ipfilter/lib/getport.c 255332 2013-09-06 23:11:19Z cy $ */ 2145510Sdarrenr 3170268Sdarrenr/* 4255332Scy * Copyright (C) 2012 by Darren Reed. 5255332Scy * 6255332Scy * See the IPFILTER.LICENCE file for details on licencing. 7255332Scy * 8255332Scy * $Id$ 9255332Scy */ 10170268Sdarrenr 11145510Sdarrenr#include "ipf.h" 12255332Scy#include <ctype.h> 13145510Sdarrenr 14255332Scyint getport(fr, name, port, proto) 15255332Scy frentry_t *fr; 16255332Scy char *name, *proto; 17255332Scy u_short *port; 18145510Sdarrenr{ 19145510Sdarrenr struct protoent *p; 20145510Sdarrenr struct servent *s; 21145510Sdarrenr u_short p1; 22145510Sdarrenr 23145510Sdarrenr if (fr == NULL || fr->fr_type != FR_T_IPF) { 24255332Scy s = getservbyname(name, proto); 25145510Sdarrenr if (s != NULL) { 26145510Sdarrenr *port = s->s_port; 27145510Sdarrenr return 0; 28145510Sdarrenr } 29255332Scy 30255332Scy if (ISDIGIT(*name)) { 31255332Scy int portval = atoi(name); 32255332Scy if (portval < 0 || portval > 65535) 33255332Scy return -1; 34255332Scy *port = htons((u_short)portval); 35255332Scy return 0; 36255332Scy } 37145510Sdarrenr return -1; 38145510Sdarrenr } 39145510Sdarrenr 40161357Sguido /* 41161357Sguido * Some people will use port names in rules without specifying 42161357Sguido * either TCP or UDP because it is implied by the group head. 43161357Sguido * If we don't know the protocol, then the best we can do here is 44161357Sguido * to take either only the TCP or UDP mapping (if one or the other 45161357Sguido * is missing) or make sure both of them agree. 46161357Sguido */ 47161357Sguido if (fr->fr_proto == 0) { 48161357Sguido s = getservbyname(name, "tcp"); 49161357Sguido if (s != NULL) 50161357Sguido p1 = s->s_port; 51161357Sguido else 52161357Sguido p1 = 0; 53161357Sguido s = getservbyname(name, "udp"); 54161357Sguido if (s != NULL) { 55161357Sguido if (p1 != s->s_port) 56161357Sguido return -1; 57161357Sguido } 58161357Sguido if ((p1 == 0) && (s == NULL)) 59161357Sguido return -1; 60161357Sguido if (p1) 61161357Sguido *port = p1; 62161357Sguido else 63161357Sguido *port = s->s_port; 64161357Sguido return 0; 65161357Sguido } 66161357Sguido 67145510Sdarrenr if ((fr->fr_flx & FI_TCPUDP) != 0) { 68145510Sdarrenr /* 69145510Sdarrenr * If a rule is "tcp/udp" then check that both TCP and UDP 70145510Sdarrenr * mappings for this protocol name match ports. 71145510Sdarrenr */ 72145510Sdarrenr s = getservbyname(name, "tcp"); 73145510Sdarrenr if (s == NULL) 74145510Sdarrenr return -1; 75145510Sdarrenr p1 = s->s_port; 76145510Sdarrenr s = getservbyname(name, "udp"); 77145510Sdarrenr if (s == NULL || s->s_port != p1) 78145510Sdarrenr return -1; 79145510Sdarrenr *port = p1; 80145510Sdarrenr return 0; 81145510Sdarrenr } 82145510Sdarrenr 83145510Sdarrenr p = getprotobynumber(fr->fr_proto); 84145510Sdarrenr s = getservbyname(name, p ? p->p_name : NULL); 85145510Sdarrenr if (s != NULL) { 86145510Sdarrenr *port = s->s_port; 87145510Sdarrenr return 0; 88145510Sdarrenr } 89145510Sdarrenr return -1; 90145510Sdarrenr} 91