s/qmail  3.3.23
Next generation secure email transport
ip.c
Go to the documentation of this file.
1 #include "fmt.h"
2 #include "scan.h"
3 #include "ip.h"
4 #include "byte.h"
5 #include "str.h"
6 #include "stralloc.h"
7 
23 unsigned int ip4_fmt(char *s,struct ip_address *ip)
24 {
25  unsigned int len;
26  unsigned int i;
27 
28  len = 0;
29  i = fmt_ulong(s,(unsigned long) ip->d[0]); len += i; if (s) s += i;
30  i = fmt_str(s,"."); len += i; if (s) s += i;
31  i = fmt_ulong(s,(unsigned long) ip->d[1]); len += i; if (s) s += i;
32  i = fmt_str(s,"."); len += i; if (s) s += i;
33  i = fmt_ulong(s,(unsigned long) ip->d[2]); len += i; if (s) s += i;
34  i = fmt_str(s,"."); len += i; if (s) s += i;
35  i = fmt_ulong(s,(unsigned long) ip->d[3]); len += i; if (s) s += i;
36  return len;
37 }
38 
47 unsigned int ip4_scan(struct ip_address *ip,char *s)
48 {
49  unsigned int i;
50  unsigned int len;
51  unsigned long u;
52 
53  len = 0;
54  i = scan_ulong(s,&u); if (!i) return 0; if (u > 255) return 0; ip->d[0] = u; s += i; len += i;
55  if (*s != '.') return 0; ++s; ++len;
56  i = scan_ulong(s,&u); if (!i) return 0; if (u > 255) return 0; ip->d[1] = u; s += i; len += i;
57  if (*s != '.') return 0; ++s; ++len;
58  i = scan_ulong(s,&u); if (!i) return 0; if (u > 255) return 0; ip->d[2] = u; s += i; len += i;
59  if (*s != '.') return 0; ++s; ++len;
60  i = scan_ulong(s,&u); if (!i) return 0; if (u > 255) return 0; ip->d[3] = u; s += i; len += i;
61  return len;
62 }
63 
72 unsigned int ip4_scanbracket(struct ip_address *ip,char *s)
73 {
74  unsigned int len;
75 
76  if (*s != '[') return 0;
77  len = ip4_scan(ip,s + 1);
78  if (!len) return 0;
79  if (s[len + 1] != ']') return 0;
80  return len + 2;
81 }
82 
91 unsigned int ip6_fmt(char *s,struct ip6_address *ip)
92 {
93  unsigned int len;
94  unsigned int i;
95  unsigned int temp, temp0;
96  unsigned int compressing;
97  unsigned int compressed;
98  int j;
99  struct ip_address ip4;
100 
101  len = 0;
102  compressing = 0;
103  compressed = 0;
104 
105  for (j = 0; j < 16; j += 2) {
106  if (j == 12 && byte_equal(ip,12,V4mappedprefix)) {
107  for (i = 0; i < 4; i++) {
108  ip4.d[i] = ip->d[i+12];
109  }
110  len += ip4_fmt(s,&ip4);
111  break;
112  }
113 
114  temp = ((unsigned long) (unsigned char) ip->d[j] << 8) +
115  (unsigned long) (unsigned char) ip->d[j+1];
116 
117  temp0 = 0; /* test the following octett [ip.h - 3.b)] */
118  if (!compressing && j < 16)
119  temp0 = ((unsigned long) (unsigned char) ip->d[j+2] << 8) +
120  (unsigned long) (unsigned char) ip->d[j+3];
121 
122  if (temp == 0 && temp0 == 0 && !compressed) {
123  if (!compressing) {
124  compressing = 1;
125  if (j == 0) {
126  if (s) *s++=':';
127  ++len;
128  }
129  }
130  } else {
131  if (compressing) {
132  compressing = 0;
133  ++compressed;
134  if (s) *s++ = ':';
135  ++len;
136  }
137  i = fmt_xlong(s,temp);
138  len += i;
139  if (s) s += i;
140  if (j < 14) {
141  if (s) *s++ = ':';
142  ++len;
143  }
144  }
145  }
146  if (compressing) { *s++ = ':'; ++len; }
147 
148  if (s) *s = 0;
149  return len;
150 }
151 
160 unsigned int ip6_scan(struct ip6_address *ip,char *s)
161 {
162  unsigned int i;
163  unsigned int len = 0;
164  unsigned long u;
165  char suffix[16];
166  int prefixlen = 0;
167  int suffixlen = 0;
168 
169  unsigned int x;
170  struct ip_address ip4;
171 
172  for (x = 0;x < 4;x++) { /* Mapped IPv4 addresses */
173  ip4.d[x] = ip->d[x+12];
174  }
175 
176  if ((i = ip4_scan(&ip4,s))) {
177  const char *c = V4mappedprefix;
178  if (byte_equal(ip4.d,4,V6any)) c = V6any;
179  for (len = 0;len < 12;++len)
180  ip->d[len] = c[len];
181  return i;
182  }
183 
184  for (i = 0;i < 16;i++)
185  ip->d[i] = 0;
186 
187  for (;;) {
188  if (*s == ':') {
189  len++;
190  if (s[1] == ':') { /* Found "::", skip to part 2 */
191  s+=2;
192  len++;
193  break;
194  }
195  s++;
196  }
197  i = scan_xlong(s,&u);
198  if (!i) return 0;
199 
200  if (prefixlen == 12 && s[i] == '.') {
201  /* the last 4 bytes may be written as IPv4 address */
202  i = ip4_scan(&ip4,s);
203  if (i) {
204  /* copy into ip->d+12 from ip4 */
205  for (x = 0;x < 4;x++) {
206  ip->d[x+12] = ip4.d[x];
207  }
208  return i+len;
209  } else
210  return 0;
211  }
212  ip->d[prefixlen++] = (u >> 8);
213  ip->d[prefixlen++] = (u & 255);
214  s += i; len += i;
215 
216  if (prefixlen == 16)
217  return len;
218  }
219 
220 /* part 2, after "::" */
221  for (;;) {
222  if (*s == ':') {
223  if (suffixlen == 0)
224  break;
225  s++;
226  len++;
227  } else if (suffixlen != 0)
228  break;
229  i = scan_xlong(s,&u);
230  if (!i) {
231  len--;
232  break;
233  }
234  if (suffixlen+prefixlen <= 12 && s[i] == '.') {
235  int j = ip4_scan(&ip4,s);
236  if (j) {
237  byte_copy(suffix+suffixlen,4,ip4.d);
238  suffixlen += 4;
239  len += j;
240  break;
241  } else
242  prefixlen = 12-suffixlen; /* make end-of-loop test true */
243  }
244  suffix[suffixlen++] = (u >> 8);
245  suffix[suffixlen++] = (u & 255);
246  s += i; len += i;
247  if (prefixlen+suffixlen == 16)
248  break;
249  }
250  for (i = 0;i < suffixlen;i++)
251  ip->d[16-suffixlen+i] = suffix[i];
252 
253  return len;
254 }
255 
264 unsigned int ip6_scanbracket(struct ip6_address *ip6,char *s)
265 {
266  unsigned int len;
267 
268  if (*s != '[') return 0;
269  len = ip6_scan(ip6,s + 1);
270  if (!len) return 0;
271  if (s[len + 1] != ']') return 0;
272  return len + 2;
273 }
274 
275 static inline int fromhex(unsigned char c) {
276  if (c>='0' && c<='9')
277  return c-'0';
278  else if (c>='A' && c<='F')
279  return c-'A'+10;
280  else if (c>='a' && c<='f')
281  return c-'a'+10;
282  return -1;
283 }
284 
293 unsigned int ip4_bitstring(stralloc *ip4string,struct ip_address *ip4,int prefix)
294 {
295  int i, j;
296  unsigned char number;
297 
298  ip4string->len = 0;
299  if (!stralloc_copys(ip4string,"")) return 1;
300  if (!stralloc_readyplus(ip4string,32)) return 1;
301 
302  for (i = 0; i < 4; i++) {
303  number = (unsigned char) ip4->d[i];
304  if (number > 255) return 2;
305 
306  for (j = 7; j >= 0; j--) {
307  if (number & (1<<j)) {
308  if (!stralloc_cats(ip4string,"1")) return 1;
309  } else {
310  if (!stralloc_cats(ip4string,"0")) return 1;
311  }
312  if (prefix == 0) {
313  if (!stralloc_0(ip4string)) return 1;
314  else return 0;
315  }
316  prefix--;
317  }
318  }
319  if (!stralloc_0(ip4string)) return 1;
320 
321  return 0;
322 }
323 
332 unsigned int ip6_bitstring(stralloc *ip6string,struct ip6_address *ip6,int prefix)
333 {
334  int i, j;
335  unsigned char lowbyte, highbyte;
336 
337  ip6string->len = 0;
338  if (!stralloc_copys(ip6string,"")) return 1;
339  if (!stralloc_readyplus(ip6string,128)) return 1;
340 
341  for (i = 0; i < 16; i++) {
342  lowbyte = (unsigned char) (ip6->d[i]) & 0x0f;
343  highbyte = (unsigned char) (ip6->d[i] >> 4) & 0x0f;
344 
345  for (j = 3; j >= 0; j--) {
346  if (highbyte & (1<<j)) {
347  if (!stralloc_cats(ip6string,"1")) return 1;
348  } else {
349  if (!stralloc_cats(ip6string,"0")) return 1;
350  }
351  if (prefix == 0) {
352  if (!stralloc_0(ip6string)) return 1;
353  else return 0;
354  }
355  prefix--;
356  }
357  for (j = 3; j >= 0; j--) {
358  if (lowbyte & (1<<j)) {
359  if (!stralloc_cats(ip6string,"1")) return 1;
360  } else {
361  if (!stralloc_cats(ip6string,"0")) return 1;
362  }
363  if (prefix == 0) {
364  if (!stralloc_0(ip6string)) return 1;
365  else return 0;
366  }
367  prefix--;
368  }
369  }
370  if (!stralloc_0(ip6string)) return 1;
371 
372  return 0;
373 }
unsigned int ip6_bitstring(stralloc *ip6string, struct ip6_address *ip6, int prefix)
ip6_bitstring parse IPv6 address and represent as char string with length prefix
Definition: ip.c:332
unsigned int fmt_ulong(char *, unsigned long)
int stralloc_readyplus()
void c(char *home, char *subdir, char *file, int uid, int gid, int mode)
Definition: install.c:57
unsigned int scan_xlong(const char *, unsigned long *)
Definition: scan_xlong.c:13
void byte_copy(char *, unsigned int, char *)
Definition: ip.h:12
struct ip_address ip
Definition: dnsptr.c:16
unsigned int ip6_scan(struct ip6_address *ip, char *s)
ip6_scan parse compactified IPv6 address string and convert to ip6_address struct ...
Definition: ip.c:160
unsigned char d[4]
Definition: ip.h:11
#define stralloc_0(sa)
Definition: stralloc.h:19
unsigned int ip4_bitstring(stralloc *ip4string, struct ip_address *ip4, int prefix)
ip4_bitstring parse IPv4 address and represent as char string with length prefix
Definition: ip.c:293
unsigned int fmt_str(char *, char *)
unsigned len
Definition: matchup.c:36
void temp()
Definition: qmail-inject.c:65
unsigned i
Definition: matchup.c:36
Definition: ip.h:11
unsigned x
Definition: matchup.c:36
int j
Definition: qmail-send.c:916
unsigned int scan_ulong(register char *, register unsigned long *)
unsigned int ip4_scan(struct ip_address *ip, char *s)
ip4_scan parse IPv4 address string and convert to ip_address
Definition: ip.c:47
unsigned int ip6_fmt(char *s, struct ip6_address *ip)
ip6_fmt convert IPv6 address to compactified IPv6 address string
Definition: ip.c:91
unsigned int fmt_xlong(char *, unsigned long)
int stralloc_copys(stralloc *, char *)
Definition: stralloc_opys.c:5
unsigned long
Definition: matchup.c:36
int stralloc_cats(stralloc *, char *)
Definition: stralloc_cats.c:5
unsigned int ip4_fmt(char *s, struct ip_address *ip)
ip4_fmt converts IPv4 address to dotted decimal string format
Definition: ip.c:23
unsigned int ip4_scanbracket(struct ip_address *ip, char *s)
ip4_scanbracket parse IPv4 address string enclosed in brackets and convert to ip_address struct ...
Definition: ip.c:72
unsigned int ip6_scanbracket(struct ip6_address *ip6, char *s)
ip6_scanbracket parse IPv6 string address enclosed in brackets
Definition: ip.c:264
unsigned u
Definition: matchup.c:36
struct ip6_address ip6
Definition: dnsptr.c:17
#define byte_equal(s, n, t)
Definition: byte.h:11
unsigned char d[16]
Definition: ip.h:12