summaryrefslogtreecommitdiff
path: root/libmailutils/cidr/fromstr.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmailutils/cidr/fromstr.c')
-rw-r--r--libmailutils/cidr/fromstr.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/libmailutils/cidr/fromstr.c b/libmailutils/cidr/fromstr.c
new file mode 100644
index 000000000..4e7a56f80
--- /dev/null
+++ b/libmailutils/cidr/fromstr.c
@@ -0,0 +1,128 @@
1/* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18#ifdef HAVE_CONFIG_H
19# include <config.h>
20#endif
21#include <string.h>
22#include <stdlib.h>
23#include <arpa/inet.h>
24#include <mailutils/cidr.h>
25#include <mailutils/errno.h>
26#include <mailutils/sockaddr.h>
27
28static void
29masklen_to_netmask (unsigned char *buf, size_t len, size_t masklen)
30{
31 int i, cnt;
32
33 cnt = masklen / 8;
34 for (i = 0; i < cnt; i++)
35 buf[i] = 0xff;
36 if (i == MU_INADDR_BYTES)
37 return;
38 cnt = 8 - masklen % 8;
39 buf[i++] = (0xff >> cnt) << cnt;
40 for (; i < MU_INADDR_BYTES; i++)
41 buf[i] = 0;
42}
43
44int
45mu_cidr_from_string (struct mu_cidr *pcidr, const char *str)
46{
47 int rc;
48 char ipbuf[41];
49 struct mu_cidr cidr;
50 char *p;
51 size_t len;
52 union
53 {
54 struct in_addr in;
55#ifdef MAILUTILS_IPV6
56 struct in6_addr in6;
57#endif
58 } inaddr;
59
60 p = strchr (str, '/');
61 if (p)
62 len = p - str;
63 else
64 len = strlen (str);
65
66 if (len > sizeof (ipbuf))
67 return MU_ERR_BUFSPACE;
68
69 memcpy (ipbuf, str, len);
70 ipbuf[len] = 0;
71
72 if (mu_str_is_ipv4 (ipbuf))
73 cidr.family = AF_INET;
74#ifdef MAILUTILS_IPV6
75 else if (mu_str_is_ipv6 (ipbuf))
76 cidr.family = AF_INET6;
77#endif
78 else
79 return MU_ERR_FAMILY;
80
81 rc = inet_pton (cidr.family, ipbuf, &inaddr);
82 if (rc == -1)
83 return MU_ERR_FAMILY;
84 else if (rc == 0)
85 return MU_ERR_NONAME;
86 else if (rc != 1)
87 return MU_ERR_FAILURE;
88
89 cidr.len = _mu_inaddr_to_bytes (cidr.family, &inaddr, cidr.address);
90 if (cidr.len == 0)
91 return MU_ERR_FAMILY;
92
93 if (p)
94 {
95 char *end;
96 unsigned long masklen;
97
98 p++;
99
100 masklen = strtoul (p, &end, 10);
101 if (*end == 0)
102 masklen_to_netmask (cidr.netmask, cidr.len, masklen);
103 else if ((cidr.family == AF_INET && mu_str_is_ipv4 (p))
104#ifdef MAILUTILS_IPV6
105 || (cidr.family == AF_INET6 && mu_str_is_ipv6 (ipbuf))
106#endif
107 )
108 {
109 rc = inet_pton (cidr.family, p, &inaddr);
110 if (rc == -1)
111 return MU_ERR_FAMILY;
112 else if (rc == 0)
113 return MU_ERR_NONAME;
114 else if (rc != 1)
115 return MU_ERR_FAILURE;
116
117 _mu_inaddr_to_bytes (cidr.family, &inaddr, cidr.netmask);
118 }
119 else
120 return MU_ERR_FAMILY;
121 }
122 else
123 masklen_to_netmask (cidr.netmask, cidr.len, cidr.len * 8);
124
125 memcpy (pcidr, &cidr, sizeof (*pcidr));
126 return 0;
127}
128

Return to:

Send suggestions and report system problems to the System administrator.