]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * ircd-ratbox: A slightly useful ircd. | |
3 | * irc_string.c: IRC string functions. | |
4 | * | |
5 | * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center | |
6 | * Copyright (C) 1996-2002 Hybrid Development Team | |
7 | * Copyright (C) 2002-2005 ircd-ratbox development team | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation; either version 2 of the License, or | |
12 | * (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | |
22 | * USA | |
23 | * | |
24 | * $Id: irc_string.c 678 2006-02-03 20:25:01Z jilles $ | |
25 | */ | |
26 | ||
27 | #include "stdinc.h" | |
28 | #include "sprintf_irc.h" | |
29 | #include "tools.h" | |
30 | #include "irc_string.h" | |
31 | #include "client.h" | |
32 | #include "memory.h" | |
33 | #include "setup.h" | |
34 | ||
35 | #ifndef INADDRSZ | |
36 | #define INADDRSZ 4 | |
37 | #endif | |
38 | ||
39 | #ifdef IPV6 | |
40 | #ifndef IN6ADDRSZ | |
41 | #define IN6ADDRSZ 16 | |
42 | #endif | |
43 | #endif | |
44 | ||
45 | #ifndef INT16SZ | |
46 | #define INT16SZ 2 | |
47 | #endif | |
48 | /* | |
49 | * myctime - This is like standard ctime()-function, but it zaps away | |
50 | * the newline from the end of that string. Also, it takes | |
51 | * the time value as parameter, instead of pointer to it. | |
52 | * Note that it is necessary to copy the string to alternate | |
53 | * buffer (who knows how ctime() implements it, maybe it statically | |
54 | * has newline there and never 'refreshes' it -- zapping that | |
55 | * might break things in other places...) | |
56 | * | |
57 | * | |
58 | * Thu Nov 24 18:22:48 1986 | |
59 | */ | |
60 | const char * | |
61 | myctime(time_t value) | |
62 | { | |
63 | static char buf[32]; | |
64 | char *p; | |
65 | ||
66 | strcpy(buf, ctime(&value)); | |
67 | if((p = strchr(buf, '\n')) != NULL) | |
68 | *p = '\0'; | |
69 | return buf; | |
70 | } | |
71 | ||
72 | ||
73 | /* | |
74 | * clean_string - clean up a string possibly containing garbage | |
75 | * | |
76 | * *sigh* Before the kiddies find this new and exciting way of | |
77 | * annoying opers, lets clean up what is sent to local opers | |
78 | * -Dianora | |
79 | */ | |
80 | char * | |
81 | clean_string(char *dest, const unsigned char *src, size_t len) | |
82 | { | |
83 | char *d = dest; | |
84 | s_assert(0 != dest); | |
85 | s_assert(0 != src); | |
86 | ||
87 | if(dest == NULL || src == NULL) | |
88 | return NULL; | |
89 | ||
90 | len -= 3; /* allow for worst case, '^A\0' */ | |
91 | ||
92 | while(*src && (len > 0)) | |
93 | { | |
94 | if(*src & 0x80) /* if high bit is set */ | |
95 | { | |
96 | *d++ = '.'; | |
97 | --len; | |
98 | } | |
99 | else if(!IsPrint(*src)) /* if NOT printable */ | |
100 | { | |
101 | *d++ = '^'; | |
102 | --len; | |
103 | *d++ = 0x40 + *src; /* turn it into a printable */ | |
104 | } | |
105 | else | |
106 | *d++ = *src; | |
107 | ++src; | |
108 | --len; | |
109 | } | |
110 | *d = '\0'; | |
111 | return dest; | |
112 | } | |
113 | ||
114 | /* | |
115 | * strip_tabs(dst, src, length) | |
116 | * | |
117 | * Copies src to dst, while converting all \t (tabs) into spaces. | |
118 | * | |
119 | * NOTE: jdc: I have a gut feeling there's a faster way to do this. | |
120 | */ | |
121 | char * | |
122 | strip_tabs(char *dest, const unsigned char *src, size_t len) | |
123 | { | |
124 | char *d = dest; | |
125 | /* Sanity check; we don't want anything nasty... */ | |
126 | s_assert(0 != dest); | |
127 | s_assert(0 != src); | |
128 | ||
129 | if(dest == NULL || src == NULL) | |
130 | return NULL; | |
131 | ||
132 | while(*src && (len > 0)) | |
133 | { | |
134 | if(*src == '\t') | |
135 | { | |
136 | *d++ = ' '; /* Translate the tab into a space */ | |
137 | } | |
138 | else | |
139 | { | |
140 | *d++ = *src; /* Copy src to dst */ | |
141 | } | |
142 | ++src; | |
143 | --len; | |
144 | } | |
145 | *d = '\0'; /* Null terminate, thanks and goodbye */ | |
146 | return dest; | |
147 | } | |
148 | ||
149 | /* | |
150 | * strtoken - walk through a string of tokens, using a set of separators | |
151 | * argv 9/90 | |
152 | * | |
153 | */ | |
154 | char * | |
155 | strtoken(char **save, char *str, const char *fs) | |
156 | { | |
157 | char *pos = *save; /* keep last position across calls */ | |
158 | char *tmp; | |
159 | ||
160 | if(str) | |
161 | pos = str; /* new string scan */ | |
162 | ||
163 | while(pos && *pos && strchr(fs, *pos) != NULL) | |
164 | ++pos; /* skip leading separators */ | |
165 | ||
166 | if(!pos || !*pos) | |
167 | return (pos = *save = NULL); /* string contains only sep's */ | |
168 | ||
169 | tmp = pos; /* now, keep position of the token */ | |
170 | ||
171 | while(*pos && strchr(fs, *pos) == NULL) | |
172 | ++pos; /* skip content of the token */ | |
173 | ||
174 | if(*pos) | |
175 | *pos++ = '\0'; /* remove first sep after the token */ | |
176 | else | |
177 | pos = NULL; /* end of string */ | |
178 | ||
179 | *save = pos; | |
180 | return tmp; | |
181 | } | |
182 | ||
183 | static const char base64_table[] = | |
184 | { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', | |
185 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', | |
186 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', | |
187 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', | |
188 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0' | |
189 | }; | |
190 | ||
191 | static const char base64_pad = '='; | |
192 | ||
193 | static const short base64_reverse_table[256] = { | |
194 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
195 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
196 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, | |
197 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, | |
198 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, | |
199 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, | |
200 | -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, | |
201 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, | |
202 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
203 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
204 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
205 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
206 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
207 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
208 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
209 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 | |
210 | }; | |
211 | ||
212 | unsigned char * | |
213 | ircd_base64_encode(const unsigned char *str, int length) | |
214 | { | |
215 | const unsigned char *current = str; | |
216 | unsigned char *p; | |
217 | unsigned char *result; | |
218 | ||
219 | if ((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2))) { | |
220 | return NULL; | |
221 | } | |
222 | ||
223 | result = MyMalloc(((length + 2) / 3) * 5); | |
224 | p = result; | |
225 | ||
226 | while (length > 2) | |
227 | { | |
228 | *p++ = base64_table[current[0] >> 2]; | |
229 | *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)]; | |
230 | *p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)]; | |
231 | *p++ = base64_table[current[2] & 0x3f]; | |
232 | ||
233 | current += 3; | |
234 | length -= 3; | |
235 | } | |
236 | ||
237 | if (length != 0) { | |
238 | *p++ = base64_table[current[0] >> 2]; | |
239 | if (length > 1) { | |
240 | *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)]; | |
241 | *p++ = base64_table[(current[1] & 0x0f) << 2]; | |
242 | *p++ = base64_pad; | |
243 | } else { | |
244 | *p++ = base64_table[(current[0] & 0x03) << 4]; | |
245 | *p++ = base64_pad; | |
246 | *p++ = base64_pad; | |
247 | } | |
248 | } | |
249 | *p = '\0'; | |
250 | return result; | |
251 | } | |
252 | ||
253 | unsigned char * | |
254 | ircd_base64_decode(const unsigned char *str, int length, int *ret) | |
255 | { | |
256 | const unsigned char *current = str; | |
257 | int ch, i = 0, j = 0, k; | |
258 | unsigned char *result; | |
259 | ||
260 | result = MyMalloc(length + 1); | |
261 | ||
262 | while ((ch = *current++) != '\0' && length-- > 0) { | |
263 | if (ch == base64_pad) break; | |
264 | ||
265 | ch = base64_reverse_table[ch]; | |
266 | if (ch < 0) continue; | |
267 | ||
268 | switch(i % 4) { | |
269 | case 0: | |
270 | result[j] = ch << 2; | |
271 | break; | |
272 | case 1: | |
273 | result[j++] |= ch >> 4; | |
274 | result[j] = (ch & 0x0f) << 4; | |
275 | break; | |
276 | case 2: | |
277 | result[j++] |= ch >>2; | |
278 | result[j] = (ch & 0x03) << 6; | |
279 | break; | |
280 | case 3: | |
281 | result[j++] |= ch; | |
282 | break; | |
283 | } | |
284 | i++; | |
285 | } | |
286 | ||
287 | k = j; | |
288 | ||
289 | if (ch == base64_pad) { | |
290 | switch(i % 4) { | |
291 | case 1: | |
292 | free(result); | |
293 | return NULL; | |
294 | case 2: | |
295 | k++; | |
296 | case 3: | |
297 | result[k++] = 0; | |
298 | } | |
299 | } | |
300 | result[j] = '\0'; | |
301 | ||
302 | if(ret) | |
303 | *ret = j; | |
304 | ||
305 | return result; | |
306 | } | |
307 | ||
308 | /* | |
309 | * From: Thomas Helvey <tomh@inxpress.net> | |
310 | */ | |
311 | static const char *IpQuadTab[] = { | |
312 | "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", | |
313 | "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", | |
314 | "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", | |
315 | "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", | |
316 | "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", | |
317 | "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", | |
318 | "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", | |
319 | "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", | |
320 | "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", | |
321 | "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", | |
322 | "100", "101", "102", "103", "104", "105", "106", "107", "108", "109", | |
323 | "110", "111", "112", "113", "114", "115", "116", "117", "118", "119", | |
324 | "120", "121", "122", "123", "124", "125", "126", "127", "128", "129", | |
325 | "130", "131", "132", "133", "134", "135", "136", "137", "138", "139", | |
326 | "140", "141", "142", "143", "144", "145", "146", "147", "148", "149", | |
327 | "150", "151", "152", "153", "154", "155", "156", "157", "158", "159", | |
328 | "160", "161", "162", "163", "164", "165", "166", "167", "168", "169", | |
329 | "170", "171", "172", "173", "174", "175", "176", "177", "178", "179", | |
330 | "180", "181", "182", "183", "184", "185", "186", "187", "188", "189", | |
331 | "190", "191", "192", "193", "194", "195", "196", "197", "198", "199", | |
332 | "200", "201", "202", "203", "204", "205", "206", "207", "208", "209", | |
333 | "210", "211", "212", "213", "214", "215", "216", "217", "218", "219", | |
334 | "220", "221", "222", "223", "224", "225", "226", "227", "228", "229", | |
335 | "230", "231", "232", "233", "234", "235", "236", "237", "238", "239", | |
336 | "240", "241", "242", "243", "244", "245", "246", "247", "248", "249", | |
337 | "250", "251", "252", "253", "254", "255" | |
338 | }; | |
339 | ||
340 | /* | |
341 | * inetntoa - in_addr to string | |
342 | * changed name to remove collision possibility and | |
343 | * so behaviour is guaranteed to take a pointer arg. | |
344 | * -avalon 23/11/92 | |
345 | * inet_ntoa -- returned the dotted notation of a given | |
346 | * internet number | |
347 | * argv 11/90). | |
348 | * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon | |
349 | */ | |
350 | ||
351 | const char * | |
352 | inetntoa(const char *in) | |
353 | { | |
354 | static char buf[16]; | |
355 | char *bufptr = buf; | |
356 | const unsigned char *a = (const unsigned char *) in; | |
357 | const char *n; | |
358 | ||
359 | n = IpQuadTab[*a++]; | |
360 | while(*n) | |
361 | *bufptr++ = *n++; | |
362 | *bufptr++ = '.'; | |
363 | n = IpQuadTab[*a++]; | |
364 | while(*n) | |
365 | *bufptr++ = *n++; | |
366 | *bufptr++ = '.'; | |
367 | n = IpQuadTab[*a++]; | |
368 | while(*n) | |
369 | *bufptr++ = *n++; | |
370 | *bufptr++ = '.'; | |
371 | n = IpQuadTab[*a]; | |
372 | while(*n) | |
373 | *bufptr++ = *n++; | |
374 | *bufptr = '\0'; | |
375 | return buf; | |
376 | } | |
377 | ||
378 | /* | |
379 | * Copyright (c) 1996-1999 by Internet Software Consortium. | |
380 | * | |
381 | * Permission to use, copy, modify, and distribute this software for any | |
382 | * purpose with or without fee is hereby granted, provided that the above | |
383 | * copyright notice and this permission notice appear in all copies. | |
384 | * | |
385 | * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS | |
386 | * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES | |
387 | * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE | |
388 | * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |
389 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR | |
390 | * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | |
391 | * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |
392 | * SOFTWARE. | |
393 | */ | |
394 | ||
395 | #define SPRINTF(x) ((size_t)ircsprintf x) | |
396 | ||
397 | /* | |
398 | * WARNING: Don't even consider trying to compile this on a system where | |
399 | * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. | |
400 | */ | |
401 | ||
402 | static const char *inet_ntop4(const u_char * src, char *dst, unsigned int size); | |
403 | #ifdef IPV6 | |
404 | static const char *inet_ntop6(const u_char * src, char *dst, unsigned int size); | |
405 | #endif | |
406 | ||
407 | /* const char * | |
408 | * inet_ntop4(src, dst, size) | |
409 | * format an IPv4 address | |
410 | * return: | |
411 | * `dst' (as a const) | |
412 | * notes: | |
413 | * (1) uses no statics | |
414 | * (2) takes a u_char* not an in_addr as input | |
415 | * author: | |
416 | * Paul Vixie, 1996. | |
417 | */ | |
418 | static const char * | |
419 | inet_ntop4(const unsigned char *src, char *dst, unsigned int size) | |
420 | { | |
421 | if(size < 16) | |
422 | return NULL; | |
423 | return strcpy(dst, inetntoa((const char *) src)); | |
424 | } | |
425 | ||
426 | /* const char * | |
427 | * inet_ntop6(src, dst, size) | |
428 | * convert IPv6 binary address into presentation (printable) format | |
429 | * author: | |
430 | * Paul Vixie, 1996. | |
431 | */ | |
432 | #ifdef IPV6 | |
433 | static const char * | |
434 | inet_ntop6(const unsigned char *src, char *dst, unsigned int size) | |
435 | { | |
436 | /* | |
437 | * Note that int32_t and int16_t need only be "at least" large enough | |
438 | * to contain a value of the specified size. On some systems, like | |
439 | * Crays, there is no such thing as an integer variable with 16 bits. | |
440 | * Keep this in mind if you think this function should have been coded | |
441 | * to use pointer overlays. All the world's not a VAX. | |
442 | */ | |
443 | char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; | |
444 | struct | |
445 | { | |
446 | int base, len; | |
447 | } | |
448 | best, cur; | |
449 | u_int words[IN6ADDRSZ / INT16SZ]; | |
450 | int i; | |
451 | ||
452 | /* | |
453 | * Preprocess: | |
454 | * Copy the input (bytewise) array into a wordwise array. | |
455 | * Find the longest run of 0x00's in src[] for :: shorthanding. | |
456 | */ | |
457 | memset(words, '\0', sizeof words); | |
458 | for(i = 0; i < IN6ADDRSZ; i += 2) | |
459 | words[i / 2] = (src[i] << 8) | src[i + 1]; | |
460 | best.base = -1; | |
461 | cur.base = -1; | |
462 | for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) | |
463 | { | |
464 | if(words[i] == 0) | |
465 | { | |
466 | if(cur.base == -1) | |
467 | cur.base = i, cur.len = 1; | |
468 | else | |
469 | cur.len++; | |
470 | } | |
471 | else | |
472 | { | |
473 | if(cur.base != -1) | |
474 | { | |
475 | if(best.base == -1 || cur.len > best.len) | |
476 | best = cur; | |
477 | cur.base = -1; | |
478 | } | |
479 | } | |
480 | } | |
481 | if(cur.base != -1) | |
482 | { | |
483 | if(best.base == -1 || cur.len > best.len) | |
484 | best = cur; | |
485 | } | |
486 | if(best.base != -1 && best.len < 2) | |
487 | best.base = -1; | |
488 | ||
489 | /* | |
490 | * Format the result. | |
491 | */ | |
492 | tp = tmp; | |
493 | for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) | |
494 | { | |
495 | /* Are we inside the best run of 0x00's? */ | |
496 | if(best.base != -1 && i >= best.base && i < (best.base + best.len)) | |
497 | { | |
498 | if(i == best.base) | |
499 | { | |
500 | if(i == 0) | |
501 | *tp++ = '0'; | |
502 | *tp++ = ':'; | |
503 | } | |
504 | continue; | |
505 | } | |
506 | /* Are we following an initial run of 0x00s or any real hex? */ | |
507 | if(i != 0) | |
508 | *tp++ = ':'; | |
509 | /* Is this address an encapsulated IPv4? */ | |
510 | if(i == 6 && best.base == 0 && | |
511 | (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) | |
512 | { | |
513 | if(!inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp))) | |
514 | return (NULL); | |
515 | tp += strlen(tp); | |
516 | break; | |
517 | } | |
518 | tp += SPRINTF((tp, "%x", words[i])); | |
519 | } | |
520 | /* Was it a trailing run of 0x00's? */ | |
521 | if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) | |
522 | *tp++ = ':'; | |
523 | *tp++ = '\0'; | |
524 | ||
525 | /* | |
526 | * Check for overflow, copy, and we're done. | |
527 | */ | |
528 | ||
529 | if((unsigned int) (tp - tmp) > size) | |
530 | { | |
531 | return (NULL); | |
532 | } | |
533 | return strcpy(dst, tmp); | |
534 | } | |
535 | #endif | |
536 | ||
537 | int | |
538 | inetpton_sock(const char *src, struct sockaddr *dst) | |
539 | { | |
540 | if(inetpton(AF_INET, src, &((struct sockaddr_in *) dst)->sin_addr)) | |
541 | { | |
542 | ((struct sockaddr_in *) dst)->sin_port = 0; | |
543 | ((struct sockaddr_in *) dst)->sin_family = AF_INET; | |
544 | SET_SS_LEN(*((struct irc_sockaddr_storage *) dst), sizeof(struct sockaddr_in)); | |
545 | return 1; | |
546 | } | |
547 | #ifdef IPV6 | |
548 | else if(inetpton(AF_INET6, src, &((struct sockaddr_in6 *) dst)->sin6_addr)) | |
549 | { | |
550 | ((struct sockaddr_in6 *) dst)->sin6_port = 0; | |
551 | ((struct sockaddr_in6 *) dst)->sin6_family = AF_INET6; | |
552 | SET_SS_LEN(*((struct irc_sockaddr_storage *) dst), sizeof(struct sockaddr_in6)); | |
553 | return 1; | |
554 | } | |
555 | #endif | |
556 | return 0; | |
557 | } | |
558 | ||
559 | const char * | |
560 | inetntop_sock(struct sockaddr *src, char *dst, unsigned int size) | |
561 | { | |
562 | switch (src->sa_family) | |
563 | { | |
564 | case AF_INET: | |
565 | return (inetntop(AF_INET, &((struct sockaddr_in *) src)->sin_addr, dst, size)); | |
566 | break; | |
567 | #ifdef IPV6 | |
568 | case AF_INET6: | |
569 | return (inetntop(AF_INET6, &((struct sockaddr_in6 *) src)->sin6_addr, dst, size)); | |
570 | break; | |
571 | #endif | |
572 | default: | |
573 | return NULL; | |
574 | break; | |
575 | } | |
576 | } | |
577 | ||
578 | /* char * | |
579 | * inetntop(af, src, dst, size) | |
580 | * convert a network format address to presentation format. | |
581 | * return: | |
582 | * pointer to presentation format address (`dst'), or NULL (see errno). | |
583 | * author: | |
584 | * Paul Vixie, 1996. | |
585 | */ | |
586 | const char * | |
587 | inetntop(int af, const void *src, char *dst, unsigned int size) | |
588 | { | |
589 | switch (af) | |
590 | { | |
591 | case AF_INET: | |
592 | return (inet_ntop4(src, dst, size)); | |
593 | #ifdef IPV6 | |
594 | case AF_INET6: | |
595 | if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr *) src) || | |
596 | IN6_IS_ADDR_V4COMPAT((const struct in6_addr *) src)) | |
597 | return (inet_ntop4 | |
598 | ((const unsigned char *) | |
599 | &((const struct in6_addr *) src)->s6_addr[12], dst, size)); | |
600 | else | |
601 | return (inet_ntop6(src, dst, size)); | |
602 | ||
603 | ||
604 | #endif | |
605 | default: | |
606 | return (NULL); | |
607 | } | |
608 | /* NOTREACHED */ | |
609 | } | |
610 | ||
611 | /* | |
612 | * WARNING: Don't even consider trying to compile this on a system where | |
613 | * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. | |
614 | */ | |
615 | ||
616 | /* int | |
617 | * inetpton(af, src, dst) | |
618 | * convert from presentation format (which usually means ASCII printable) | |
619 | * to network format (which is usually some kind of binary format). | |
620 | * return: | |
621 | * 1 if the address was valid for the specified address family | |
622 | * 0 if the address wasn't valid (`dst' is untouched in this case) | |
623 | * -1 if some other error occurred (`dst' is untouched in this case, too) | |
624 | * author: | |
625 | * Paul Vixie, 1996. | |
626 | */ | |
627 | ||
628 | /* int | |
629 | * inet_pton4(src, dst) | |
630 | * like inet_aton() but without all the hexadecimal and shorthand. | |
631 | * return: | |
632 | * 1 if `src' is a valid dotted quad, else 0. | |
633 | * notice: | |
634 | * does not touch `dst' unless it's returning 1. | |
635 | * author: | |
636 | * Paul Vixie, 1996. | |
637 | */ | |
638 | static int | |
639 | inet_pton4(src, dst) | |
640 | const char *src; | |
641 | u_char *dst; | |
642 | { | |
643 | int saw_digit, octets, ch; | |
644 | u_char tmp[INADDRSZ], *tp; | |
645 | ||
646 | saw_digit = 0; | |
647 | octets = 0; | |
648 | *(tp = tmp) = 0; | |
649 | while((ch = *src++) != '\0') | |
650 | { | |
651 | ||
652 | if(ch >= '0' && ch <= '9') | |
653 | { | |
654 | u_int new = *tp * 10 + (ch - '0'); | |
655 | ||
656 | if(new > 255) | |
657 | return (0); | |
658 | *tp = new; | |
659 | if(!saw_digit) | |
660 | { | |
661 | if(++octets > 4) | |
662 | return (0); | |
663 | saw_digit = 1; | |
664 | } | |
665 | } | |
666 | else if(ch == '.' && saw_digit) | |
667 | { | |
668 | if(octets == 4) | |
669 | return (0); | |
670 | *++tp = 0; | |
671 | saw_digit = 0; | |
672 | } | |
673 | else | |
674 | return (0); | |
675 | } | |
676 | if(octets < 4) | |
677 | return (0); | |
678 | memcpy(dst, tmp, INADDRSZ); | |
679 | return (1); | |
680 | } | |
681 | ||
682 | #ifdef IPV6 | |
683 | /* int | |
684 | * inet_pton6(src, dst) | |
685 | * convert presentation level address to network order binary form. | |
686 | * return: | |
687 | * 1 if `src' is a valid [RFC1884 2.2] address, else 0. | |
688 | * notice: | |
689 | * (1) does not touch `dst' unless it's returning 1. | |
690 | * (2) :: in a full address is silently ignored. | |
691 | * credit: | |
692 | * inspired by Mark Andrews. | |
693 | * author: | |
694 | * Paul Vixie, 1996. | |
695 | */ | |
696 | ||
697 | static int | |
698 | inet_pton6(src, dst) | |
699 | const char *src; | |
700 | u_char *dst; | |
701 | { | |
702 | static const char xdigits[] = "0123456789abcdef"; | |
703 | u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp; | |
704 | const char *curtok; | |
705 | int ch, saw_xdigit; | |
706 | u_int val; | |
707 | ||
708 | tp = memset(tmp, '\0', IN6ADDRSZ); | |
709 | endp = tp + IN6ADDRSZ; | |
710 | colonp = NULL; | |
711 | /* Leading :: requires some special handling. */ | |
712 | if(*src == ':') | |
713 | if(*++src != ':') | |
714 | return (0); | |
715 | curtok = src; | |
716 | saw_xdigit = 0; | |
717 | val = 0; | |
718 | while((ch = tolower(*src++)) != '\0') | |
719 | { | |
720 | const char *pch; | |
721 | ||
722 | pch = strchr(xdigits, ch); | |
723 | if(pch != NULL) | |
724 | { | |
725 | val <<= 4; | |
726 | val |= (pch - xdigits); | |
727 | if(val > 0xffff) | |
728 | return (0); | |
729 | saw_xdigit = 1; | |
730 | continue; | |
731 | } | |
732 | if(ch == ':') | |
733 | { | |
734 | curtok = src; | |
735 | if(!saw_xdigit) | |
736 | { | |
737 | if(colonp) | |
738 | return (0); | |
739 | colonp = tp; | |
740 | continue; | |
741 | } | |
742 | else if(*src == '\0') | |
743 | { | |
744 | return (0); | |
745 | } | |
746 | if(tp + INT16SZ > endp) | |
747 | return (0); | |
748 | *tp++ = (u_char) (val >> 8) & 0xff; | |
749 | *tp++ = (u_char) val & 0xff; | |
750 | saw_xdigit = 0; | |
751 | val = 0; | |
752 | continue; | |
753 | } | |
754 | if(*src != '\0' && ch == '.') | |
755 | { | |
756 | if(((tp + INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0) | |
757 | { | |
758 | tp += INADDRSZ; | |
759 | saw_xdigit = 0; | |
760 | break; /* '\0' was seen by inet_pton4(). */ | |
761 | } | |
762 | } | |
763 | else | |
764 | continue; | |
765 | return (0); | |
766 | } | |
767 | if(saw_xdigit) | |
768 | { | |
769 | if(tp + INT16SZ > endp) | |
770 | return (0); | |
771 | *tp++ = (u_char) (val >> 8) & 0xff; | |
772 | *tp++ = (u_char) val & 0xff; | |
773 | } | |
774 | if(colonp != NULL) | |
775 | { | |
776 | /* | |
777 | * Since some memmove()'s erroneously fail to handle | |
778 | * overlapping regions, we'll do the shift by hand. | |
779 | */ | |
780 | const int n = tp - colonp; | |
781 | int i; | |
782 | ||
783 | if(tp == endp) | |
784 | return (0); | |
785 | for(i = 1; i <= n; i++) | |
786 | { | |
787 | endp[-i] = colonp[n - i]; | |
788 | colonp[n - i] = 0; | |
789 | } | |
790 | tp = endp; | |
791 | } | |
792 | if(tp != endp) | |
793 | return (0); | |
794 | memcpy(dst, tmp, IN6ADDRSZ); | |
795 | return (1); | |
796 | } | |
797 | #endif | |
798 | int | |
799 | inetpton(af, src, dst) | |
800 | int af; | |
801 | const char *src; | |
802 | void *dst; | |
803 | { | |
804 | switch (af) | |
805 | { | |
806 | case AF_INET: | |
807 | return (inet_pton4(src, dst)); | |
808 | #ifdef IPV6 | |
809 | case AF_INET6: | |
810 | /* Somebody might have passed as an IPv4 address this is sick but it works */ | |
811 | if(inet_pton4(src, dst)) | |
812 | { | |
813 | char tmp[HOSTIPLEN]; | |
814 | ircsprintf(tmp, "::ffff:%s", src); | |
815 | return (inet_pton6(tmp, dst)); | |
816 | } | |
817 | else | |
818 | return (inet_pton6(src, dst)); | |
819 | #endif | |
820 | default: | |
821 | return (-1); | |
822 | } | |
823 | /* NOTREACHED */ | |
824 | } | |
825 | ||
826 | /* | |
827 | * strlcat and strlcpy were ripped from openssh 2.5.1p2 | |
828 | * They had the following Copyright info: | |
829 | * | |
830 | * | |
831 | * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> | |
832 | * All rights reserved. | |
833 | * | |
834 | * Redistribution and use in source and binary forms, with or without | |
835 | * modification, are permitted provided that the following conditions | |
836 | * are met: | |
837 | * 1. Redistributions of source code must retain the above copyright | |
838 | * notice, this list of conditions and the following disclaimer. | |
839 | * 2. Redistributions in binary form must reproduce the above copyright | |
840 | * notice, this list of conditions and the following disclaimer in the | |
841 | * documentation and/or other materials provided with the distribution. | |
842 | * 3. The name of the author may not be used to endorse or promote products | |
843 | * derived from this software without specific prior written permission. | |
844 | * | |
845 | * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |
846 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |
847 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | |
848 | * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
849 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
850 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
851 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
852 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
853 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
854 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
855 | */ | |
856 | ||
857 | ||
858 | ||
859 | #ifndef HAVE_STRLCAT | |
860 | size_t | |
861 | strlcat(char *dst, const char *src, size_t siz) | |
862 | { | |
863 | char *d = dst; | |
864 | const char *s = src; | |
865 | size_t n = siz, dlen; | |
866 | ||
867 | while(n-- != 0 && *d != '\0') | |
868 | d++; | |
869 | dlen = d - dst; | |
870 | n = siz - dlen; | |
871 | ||
872 | if(n == 0) | |
873 | return (dlen + strlen(s)); | |
874 | while(*s != '\0') | |
875 | { | |
876 | if(n != 1) | |
877 | { | |
878 | *d++ = *s; | |
879 | n--; | |
880 | } | |
881 | s++; | |
882 | } | |
883 | *d = '\0'; | |
884 | return (dlen + (s - src)); /* count does not include NUL */ | |
885 | } | |
886 | #endif | |
887 | ||
888 | #ifndef HAVE_STRLCPY | |
889 | size_t | |
890 | strlcpy(char *dst, const char *src, size_t siz) | |
891 | { | |
892 | char *d = dst; | |
893 | const char *s = src; | |
894 | size_t n = siz; | |
895 | /* Copy as many bytes as will fit */ | |
896 | if(n != 0 && --n != 0) | |
897 | { | |
898 | do | |
899 | { | |
900 | if((*d++ = *s++) == 0) | |
901 | break; | |
902 | } | |
903 | while(--n != 0); | |
904 | } | |
905 | /* Not enough room in dst, add NUL and traverse rest of src */ | |
906 | if(n == 0) | |
907 | { | |
908 | if(siz != 0) | |
909 | *d = '\0'; /* NUL-terminate dst */ | |
910 | while(*s++) | |
911 | ; | |
912 | } | |
913 | ||
914 | return (s - src - 1); /* count does not include NUL */ | |
915 | } | |
916 | #endif | |
917 | ||
918 | char * | |
919 | strip_colour(char *string) | |
920 | { | |
921 | char *c = string; | |
922 | char *c2 = string; | |
923 | char *last_non_space = NULL; | |
924 | /* c is source, c2 is target */ | |
925 | for(; c && *c; c++) | |
926 | switch (*c) | |
927 | { | |
928 | case 3: | |
929 | if(isdigit(c[1])) | |
930 | { | |
931 | c++; | |
932 | if(isdigit(c[1])) | |
933 | c++; | |
934 | if(c[1] == ',' && isdigit(c[2])) | |
935 | { | |
936 | c += 2; | |
937 | if(isdigit(c[1])) | |
938 | c++; | |
939 | } | |
940 | } | |
941 | break; | |
942 | case 2: | |
943 | case 6: | |
944 | case 7: | |
945 | case 22: | |
946 | case 23: | |
947 | case 27: | |
948 | case 31: | |
949 | break; | |
950 | case 32: | |
951 | *c2++ = *c; | |
952 | break; | |
953 | default: | |
954 | *c2++ = *c; | |
955 | last_non_space = c2; | |
956 | break; | |
957 | } | |
958 | *c2 = '\0'; | |
959 | if(last_non_space) | |
960 | *last_non_space = '\0'; | |
961 | return string; | |
962 | } |