Version 1.8.0.1
[socat.git] / xio-ip4.c
blobcdd218be9f4bc81f16a662bb46c0e3054adebabe
1 /* source: xio-ip4.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains the source for IP4 related functions */
7 #include "xiosysincludes.h"
9 #if WITH_IP4
11 #include "xioopen.h"
12 #include "xio-socket.h"
13 #include "xio-ip.h"
14 #include "xio-ip4.h"
17 int xioparsenetwork_ip4(
18 const char *rangename,
19 struct xiorange *range,
20 const int ai_flags[2])
22 struct in_addr *netaddr_in = &range->netaddr.ip4.sin_addr;
23 struct in_addr *netmask_in = &range->netmask.ip4.sin_addr;
24 char *rangename1; /* a copy of rangename with writing allowed */
25 char *delimpos; /* absolute address of delimiter */
26 unsigned int bits; /* netmask bits */
27 union sockaddr_union sau;
28 socklen_t socklen = sizeof(sau);
29 int rc;
31 if ((rangename1 = strdup(rangename)) == NULL) {
32 Error1("strdup(\"%s\"): out of memory", rangename);
33 return STAT_RETRYLATER;
36 if (delimpos = strchr(rangename1, '/')) {
37 char *endptr;
38 bits = strtoul(delimpos+1, &endptr, 10);
39 if (! ((*(delimpos+1) != '\0') && (*endptr == '\0'))) {
40 Error1("not a valid IPv4 netmask in \"%s\"", rangename);
41 bits = 32; /* most secure selection */
42 } else if (bits > 32) {
43 Error1("IPv4 netmask \"%s\" is too large", rangename);
44 bits = 32;
46 if (bits <= 0) {
47 netmask_in->s_addr = 0;
48 } else {
49 netmask_in->s_addr = htonl((0xffffffff << (32-bits)));
51 } else if (delimpos = strchr(rangename1, ':')) {
52 if ((rc = xioresolve(delimpos+1, NULL, PF_INET, 0, 0,
53 &sau, &socklen, ai_flags))
54 != STAT_OK) {
55 return rc;
57 netmask_in->s_addr = sau.ip4.sin_addr.s_addr;
58 } else {
59 Error1("xioparsenetwork_ip4(\"%s\",,): missing netmask delimiter", rangename);
60 free(rangename1);
61 return STAT_NORETRY;
64 *delimpos = 0;
65 if ((rc = xioresolve(rangename1, NULL, PF_INET, 0, 0,
66 &sau, &socklen, ai_flags))
67 != STAT_OK) {
68 return rc;
70 netaddr_in->s_addr = sau.ip4.sin_addr.s_addr;
72 free(rangename1);
73 return STAT_OK;
76 /* check if peer address is within permitted range.
77 return >= 0 if so. */
78 int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange *range) {
79 struct in_addr *netaddr_in = &range->netaddr.ip4.sin_addr;
80 struct in_addr *netmask_in = &range->netmask.ip4.sin_addr;
81 char addrbuf[256], maskbuf[256];
82 char peername[256];
84 /* is provided client address valid? */
85 if (pa->sin_addr.s_addr == 0) {
86 Warn("invalid client address 0.0.0.0");
87 return -1;
89 /* client address restriction */
90 Debug2("permitted client subnet: %s:%s",
91 inet4addr_info(ntohl(netaddr_in->s_addr), addrbuf, sizeof(addrbuf)),
92 inet4addr_info(ntohl(netmask_in->s_addr), maskbuf, sizeof(maskbuf)));
93 Debug1("client address is 0x%08x",
94 ntohl(pa->sin_addr.s_addr));
95 Debug1("masked address is 0x%08x",
96 ntohl(pa->sin_addr.s_addr & netmask_in->s_addr));
97 if ((pa->sin_addr.s_addr & netmask_in->s_addr)
98 != netaddr_in->s_addr) {
99 Debug1("client address %s is not permitted",
100 sockaddr_inet4_info(pa, peername, sizeof(peername)));
101 return -1;
103 return 0;
106 /* returns information that can be used for constructing an environment
107 variable describing the socket address.
108 if idx is 0, this function writes "ADDR" into namebuff and the IP address
109 into valuebuff, and returns 1 (which means that one more info is there).
110 if idx is 1, it writes "PORT" into namebuff and the port number into
111 valuebuff, and returns 0 (no more info)
112 namelen and valuelen contain the max. allowed length of output chars in the
113 respective buffer.
114 on error this function returns -1.
117 xiosetsockaddrenv_ip4(int idx, char *namebuff, size_t namelen,
118 char *valuebuff, size_t valuelen,
119 struct sockaddr_in *sa, int ipproto) {
120 switch (idx) {
121 case 0:
122 strcpy(namebuff, "ADDR");
123 inet4addr_info(ntohl(sa->sin_addr.s_addr), valuebuff, valuelen);
124 switch (ipproto) {
125 case IPPROTO_TCP:
126 case IPPROTO_UDP:
127 #ifdef IPPROTO_SCTP
128 case IPPROTO_SCTP:
129 #endif
130 return 1; /* there is port information to also be retrieved */
131 default:
132 return 0; /* no port info coming */
134 case 1:
135 strcpy(namebuff, "PORT");
136 snprintf(valuebuff, valuelen, "%u", ntohs(sa->sin_port));
137 return 0;
139 return -1;
142 #endif /* WITH_IP4 */