1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
/*
* conversion from protocol/port string to protocol and port
*
* Copyright (C) 2002 Mario Strasser <mast@gmx.net>,
* Zuercher Hochschule Winterthur,
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "jambuf.h"
#include "ip_protoport.h"
#include "constants.h" /* for zero() */
#include "chunk.h" /* for clone_bytes_as_string() */
#include "lswlog.h" /* for pexpect() */
const ip_protoport unset_protoport;
/*
* ttoprotoport - converts from protocol/port string to protocol and
* port
*/
err_t ttoprotoport(const char *src, ip_protoport *protoport)
{
err_t err;
zero(protoport);
/* get the length of the string */
size_t src_len = strlen(src);
/* locate delimiter '/' between protocol and port */
char *end = strchr(src, '/');
const char *service_name;
shunk_t proto_name;
if (end != NULL) {
/* PROT/PORT */
proto_name = shunk2(src, end - src);
service_name = end + 1;
} else if (streq(src, "%any")) {
/* %any */
proto_name = shunk1("unknown");
service_name = src + src_len; /*NUL*/
} else {
/* PROTO */
proto_name = shunk2(src, src_len);
service_name = src + src_len; /*NUL*/
}
/* extract protocol by trying to resolve it by name */
const struct ip_protocol *protocol;
err = ttoprotocol(proto_name, &protocol);
if (err != NULL) {
return err;
}
/* is there a port wildcard? */
ip_port port;
bool port_wildcard;
if (service_name[0] == '\0') {
/* allow N/ and N; different to N/%any */
port = unset_port;
port_wildcard = false;
} else if (streq(service_name, "%any")) {
if (protocol->ipproto == 0) {
return "port wildcard (%any) requires a valid protocol";
}
port = unset_port;
port_wildcard = true;
} else {
/* Port 0-65535 is different to %any */
err = ttoport(shunk1(service_name), &port);
if (err != NULL) {
return err;
}
if (protocol->ipproto == 0 && port.hport != 0) {
return "protocol 0 must have 0 port";
}
port_wildcard = false;
}
protoport->is_set = true;
protoport->ipproto = protocol->ipproto;
protoport->has_port_wildcard = port_wildcard;
protoport->hport = port.hport;
return NULL;
}
size_t jam_protoport(struct jambuf *buf, const ip_protoport *protoport)
{
if (protoport == NULL) {
return jam(buf, "<null-protoport>");
}
if (!protoport->is_set) {
return jam(buf, "<unset-protoport>");
}
if (protoport->ipproto == 0) {
pexpect(protoport->has_port_wildcard == false);
pexpect(protoport->hport == 0);
return jam_string(buf, "%any");
}
size_t s = 0;
s += jam(buf, "%s/", protocol_from_ipproto(protoport->ipproto)->name);
if (protoport->has_port_wildcard) {
pexpect(protoport->hport == 0);
s += jam_string(buf, "%any");
} else {
/* 0 implies 0-65535 */
s += jam(buf, "%u", protoport->hport);
}
return s;
}
const char *str_protoport(const ip_protoport *protoport, protoport_buf *buf)
{
struct jambuf jambuf = ARRAY_AS_JAMBUF(buf->buf);
jam_protoport(&jambuf, protoport);
return buf->buf;
}
|