]> jfr.im git - irc/rqf/shadowircd.git/blob - src/irc_string.c
[svn] - the new plan:
[irc/rqf/shadowircd.git] / src / irc_string.c
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 }