1 /*
2 Copyright 2020 Northern.tech AS
3
4 This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; version 3.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18
19 To the extent this program is licensed as part of the Enterprise
20 versions of CFEngine, the applicable Commercial Open Source License
21 (COSL) may apply to this file if you as a licensee so wish it. See
22 included file COSL.txt.
23 */
24
25 #include <platform.h>
26
27 #include <stdint.h>
28 #include <ctype.h>
29 #include <ip_address.h>
30 #include <alloc.h>
31
32 struct IPV4Address {
33 uint8_t octets[4];
34 uint16_t port;
35 };
36 struct IPV6Address {
37 uint16_t sixteen[8];
38 uint16_t port;
39 };
40
41 struct IPAddress {
42 void *address;
43 int type;
44 };
45
46 #define Char2Dec(o, c) \
47 (o * 10) + c - '0'
48
49 /*
50 * Hexadecimal conversion is not as simple as decimal conversion,
51 * so we implement it here.
52 * We do not check for errors, we assume the caller has checked that
53 * the characters are hexadecimal.
54 */
Char2Hex(int beginning,char increment)55 static int Char2Hex(int beginning, char increment)
56 {
57 int number = beginning;
58 number *= 16;
59 if (('a' <= increment) && (increment <= 'f'))
60 {
61 number += (increment - 'a' + 0x0A);
62 }
63 else if (('A' <= increment) && (increment <= 'F'))
64 {
65 number += (increment - 'A' + 0x0A);
66 }
67 else
68 {
69 number += (increment - '0');
70 }
71 return number;
72 }
73
74 /*
75 * This function parses the source pointer and checks if it conforms to the
76 * 0a0b0c0d or 0a0b0c0d:0e0f formats (commonly used in procfs)
77 *
78 * If address is not NULL and the address is IPV4, then the result is copied there.
79 *
80 * Returns 0 on success.
81 */
IPV4_hex_parser(const char * source,struct IPV4Address * address)82 static int IPV4_hex_parser(const char *source, struct IPV4Address *address)
83 {
84 {
85 // shortcut for the 0a0b0c0d format
86 unsigned int a, b, c, d, pport = 0;
87 if (strlen(source) == 8 &&
88 sscanf(source, "%2x%2x%2x%2x", &a, &b, &c, &d) == 4)
89 {
90 address->octets[3] = a;
91 address->octets[2] = b;
92 address->octets[1] = c;
93 address->octets[0] = d;
94 address->port = pport;
95 return 0;
96 }
97
98 // shortcut for the 0a0b0c0d:0e0f format
99 if (strlen(source) == 8+1+4 &&
100 sscanf(source, "%2x%2x%2x%2x:%4x", &a, &b, &c, &d, &pport) == 5)
101 {
102 address->octets[3] = a;
103 address->octets[2] = b;
104 address->octets[1] = c;
105 address->octets[0] = d;
106 address->port = pport;
107 return 0;
108 }
109 }
110
111 return -1;
112 }
113
114 /*
115 * This function parses the source pointer and checks if it conforms to the
116 * RFC 791.
117 *
118 * xxx.xxx.xxx.xxx[:ppppp]
119 *
120 * If address is not NULL and the address is IPV4, then the result is copied there.
121 *
122 * Returns 0 on success.
123 */
IPV4_parser(const char * source,struct IPV4Address * address)124 static int IPV4_parser(const char *source, struct IPV4Address *address)
125 {
126 char *p = NULL;
127 int octet = 0;
128 int port = 0;
129 int period_counter = 0;
130 int port_counter = 0;
131 int char_counter = 0;
132 bool is_period = false;
133 bool is_digit = false;
134 bool is_port = false;
135 bool has_digit = false;
136
137 /*
138 * For simplicity sake we initialize address (if not NULL).
139 */
140 if (address)
141 {
142 int i = 0;
143 for (i = 0; i < 4; ++i)
144 {
145 address->octets[i] = 0;
146 }
147 address->port = 0;
148 }
149
150 /*
151 * IPV4 parsing has 6 states, of which:
152 * 2 are end states
153 * 4 are parsing states
154 *
155 * States 0 to 3 are purely address parsing. State 5
156 * might never be reached if there is no port.
157 * State 4 is the final state if everything went ok.
158 * State 6 is reached in case of error.
159 *
160 * 0 1 2 3
161 * |d |d |d |d
162 * | p | p | p | done
163 * 0 -> 1 -> 2 -> 3 -> 4
164 * | | | | |
165 * 7 <--+----+----+ |
166 * error | ':' |
167 * _5-----+
168 * d \| done
169 */
170 int state = 0;
171 bool state_change = false;
172 for (p = (char *)source; *p != '\0'; ++p)
173 {
174 /*
175 * Do some character recognition
176 */
177 is_digit = isdigit(*p);
178 is_period = (*p == '.') ? 1 : 0;
179 is_port = (*p == ':') ? 1 : 0;
180 /*
181 * Update the corresponding flags.
182 */
183 if (is_period)
184 {
185 period_counter++;
186 }
187 if (is_port)
188 {
189 port_counter++;
190 }
191 /*
192 * Do the right operation depending on the state
193 */
194 switch (state)
195 {
196 case 0:
197 case 1:
198 case 2:
199 /*
200 * The three first states are the same.
201 * XXX.XXX.XXX.xxx[:nnnnn]
202 */
203 if (is_digit)
204 {
205 octet = Char2Dec(octet, *p);
206 has_digit = true;
207 }
208 else if (is_period)
209 {
210 if (address)
211 {
212 address->octets[state] = octet;
213 }
214 state++;
215 state_change = true;
216 }
217 else
218 {
219 state = 7;
220 state_change = true;
221 }
222 break;
223 case 3:
224 /*
225 * This case is different from the previous ones. A period here means error.
226 * xxx.xxx.xxx.XXX[:nnnnn]
227 */
228 if (is_digit)
229 {
230 octet = Char2Dec(octet, *p);
231 has_digit = true;
232 }
233 else if (is_port)
234 {
235 if (address)
236 {
237 address->octets[state] = octet;
238 }
239 state = 5;
240 state_change = true;
241 }
242 else
243 {
244 state = 7;
245 state_change = true;
246 }
247 break;
248 case 4:
249 break;
250 case 5:
251 if (is_digit)
252 {
253 port = Char2Dec(port, *p);
254 }
255 else
256 {
257 state = 7;
258 state_change = true;
259 }
260 break;
261 case 6:
262 default:
263 return -1;
264 break;
265 }
266 /*
267 * It is important to the filtering before counting the characters.
268 * Otherwise the counter will need to start from -1.
269 */
270 char_counter++;
271 /*
272 * Do some sanity checks, this should hold no matter
273 * in which state of the state machine we are.
274 */
275 if (octet > 255)
276 {
277 return -1;
278 }
279 if (port > 65535)
280 {
281 return -1;
282 }
283 if (period_counter > 1)
284 {
285 return -1;
286 }
287 if (port_counter > 1)
288 {
289 return -1;
290 }
291 if (state_change)
292 {
293 /*
294 * Check that we have digits, otherwise the transition is wrong.
295 */
296 if (!has_digit)
297 {
298 return -1;
299 }
300 /*
301 * Reset all the variables.
302 */
303 char_counter = 0;
304 octet = 0;
305 port = 0;
306 period_counter = 0;
307 port_counter = 0;
308 is_period = false;
309 is_digit = false;
310 is_port = false;
311 has_digit = false;
312 state_change = false;
313 }
314 }
315 /*
316 * These states are not end state, which mean we exited the loop because of an error
317 */
318 if ((state == 0) || (state == 1) || (state == 2))
319 {
320 return -1;
321 }
322 /*
323 * If state is 3 then we exited the loop without copying the last octet.
324 * This is because we didn't get to state 4.
325 * Notice that we need to check if we had characters, it might be possible that we
326 * have the following situation 'xxx.xxx.xxx.' which will fit the state change but not
327 * produce a valid IP.
328 */
329 if (state == 3)
330 {
331 if (char_counter == 0)
332 {
333 return -1;
334 }
335 if (address)
336 {
337 address->octets[3] = octet;
338 }
339 }
340 /*
341 * If state is 5 then we exited the loop without copying the port.
342 * This is because we hit a '\0'.
343 * Notice that we need to check if we had characters, it might be possible that we
344 * have the following situation 'xxx.xxx.xxx.xxx:' which will fit the state change but not
345 * produce a valid IP.
346 */
347 if (state == 5)
348 {
349 if (char_counter == 0)
350 {
351 return -1;
352 }
353 if (address)
354 {
355 address->port = port;
356 }
357 }
358 /*
359 * If state is 6 then there was an error.
360 */
361 if (state == 6)
362 {
363 return -1;
364 }
365 return 0;
366 }
367
368 /*
369 * This function parses the address and checks if it conforms to the
370 * 0a0b0c0d0e0f0g0h or 0a0b0c0d0e0f0g0h:0i0j format (commonly used in procfs)
371 *
372 * Returns 0 on success.
373 */
IPV6_hex_parser(const char * source,struct IPV6Address * address)374 static int IPV6_hex_parser(const char *source, struct IPV6Address *address)
375 {
376 {
377 // shortcut for the 0a0b0c0d0e0f0g0h format
378 unsigned int a, b, c, d, e, f, g, h, pport = 0;
379
380 if (strlen(source) == 32 &&
381 sscanf(source, "%4x%4x%4x%4x%4x%4x%4x%4x", &a, &b, &c, &d, &e, &f, &g, &h) == 8)
382 {
383 address->sixteen[0] = a;
384 address->sixteen[1] = b;
385 address->sixteen[2] = c;
386 address->sixteen[3] = d;
387 address->sixteen[4] = e;
388 address->sixteen[5] = f;
389 address->sixteen[6] = g;
390 address->sixteen[7] = h;
391 return 0;
392 }
393
394 if (strlen(source) == 32+1+4 &&
395 sscanf(source, "%4x%4x%4x%4x%4x%4x%4x%4x:%4x", &a, &b, &c, &d, &e, &f, &g, &h, &pport) == 9)
396 {
397 address->sixteen[0] = a;
398 address->sixteen[1] = b;
399 address->sixteen[2] = c;
400 address->sixteen[3] = d;
401 address->sixteen[4] = e;
402 address->sixteen[5] = f;
403 address->sixteen[6] = g;
404 address->sixteen[7] = h;
405 address->port = pport;
406 return 0;
407 }
408 }
409
410 return -1;
411 }
412
413 /*
414 * This function parses the address and checks if it conforms to the
415 * RFCs 2373, 2460 and 5952.
416 * We do not support Microsoft UNC encoding, i.e.
417 * hhhh-hhhh-hhhh-hhhh-hhhh-hhhh-hhhh-hhhh.ipv6-literal.net
418 * Despite following RFC 5292 we do not signal errors derived from bad
419 * zero compression although this might change on time, so please do not
420 * trust that we will honor address with wrong zero compression.
421 *
422 * Returns 0 on success.
423 */
IPV6_parser(const char * source,struct IPV6Address * address)424 static int IPV6_parser(const char *source, struct IPV6Address *address)
425 {
426 /*
427 * IPV6 parsing is more complex than IPV4 parsing. There are a few ground rules:
428 * - Leading zeros can be omitted.
429 * - Fields that are just zeros can be abbreviated to one zero or completely omitted.
430 * In the later case the following notation is used: '::'.
431 * - Port number is specified in a special way:
432 * [hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh]:ppppp
433 * Notice that it is possible to have the '[' and ']' without specifying a port.
434 *
435 * Simplified state machine:
436 *
437 * _h _h _h _h _h _h _h _h _d
438 * |/ ':' |/ ':' |/ ':' |/ ':' |/ ':' |/ ':' |/ ':' |/ ']' ':' |/ done
439 * 0------>1------>2------>3------>4------>5------>6------>7------>8------>9------>11
440 * |\ | done |
441 * -'[' 9<------+
442 *
443 * This is a simplified state machine since I assume that we keep the square brackets inside
444 * the same state as hexadecimal digits, which in practice is not true.
445 */
446 char *p = NULL;
447 int sixteen = 0;
448 int unsorted_sixteen[6];
449 int unsorted_pointer = 0;
450 int bracket_expected = 0;
451 int port = 0;
452 int char_counter = 0;
453 bool is_start_bracket = 0;
454 bool is_end_bracket = 0;
455 bool is_colon = 0;
456 bool is_hexdigit = 0;
457 bool is_upper_hexdigit = 0;
458 bool is_digit = 0;
459 int zero_compression = 0;
460 int already_compressed = 0;
461 int state = 0;
462 bool state_change = false;
463
464 /*
465 * Initialize our container for unknown numbers.
466 */
467 for (unsorted_pointer = 0; unsorted_pointer < 6; ++unsorted_pointer)
468 {
469 unsorted_sixteen[unsorted_pointer] = 0;
470 }
471 unsorted_pointer = 0;
472 /*
473 * For simplicity sake we initialize address (if not NULL).
474 */
475 if (address)
476 {
477 int i = 0;
478 for (i = 0; i < 8; ++i)
479 {
480 address->sixteen[i] = 0;
481 }
482 address->port = 0;
483 }
484
485 for (p = (char *)source; *p != '\0'; ++p)
486 {
487 /*
488 * Take a closer look at the character
489 */
490 is_start_bracket = (*p == '[') ? 1 : 0;
491 is_end_bracket = (*p == ']') ? 1 : 0;
492 is_hexdigit = isxdigit(*p);
493 is_digit = isdigit(*p);
494 is_colon = (*p == ':') ? 1 : 0;
495 if (is_hexdigit)
496 {
497 if (isalpha(*p))
498 {
499 is_upper_hexdigit = isupper(*p);
500 }
501 }
502
503 switch (state)
504 {
505 case 0:
506 /*
507 * This case is slightly different because of the possible presence of '['.
508 * Notice that '[' is only valid as the first character, anything else is
509 * an error!
510 */
511 if (is_start_bracket)
512 {
513 if (char_counter == 0)
514 {
515 bracket_expected = 1;
516 }
517 else
518 {
519 state = 11;
520 state_change = true;
521 }
522 }
523 else if (is_hexdigit)
524 {
525 /*
526 * RFC 5952 forbids upper case hex digits
527 */
528 if (is_upper_hexdigit)
529 {
530 state = 11;
531 state_change = true;
532 }
533 else
534 {
535 sixteen = Char2Hex(sixteen, *p);
536 }
537 }
538 else if (is_colon)
539 {
540 if (address)
541 {
542 address->sixteen[0] = sixteen;
543 }
544 state = 1;
545 state_change = true;
546 }
547 else
548 {
549 state = 11;
550 state_change = true;
551 }
552 break;
553 case 1:
554 /*
555 * This state is special since it cannot have a ']' as in the next
556 * states.
557 */
558 if (is_hexdigit)
559 {
560 /*
561 * RFC 5952 forbids upper case hex digits
562 */
563 if (is_upper_hexdigit)
564 {
565 state = 11;
566 state_change = true;
567 }
568 else
569 {
570 sixteen = Char2Hex(sixteen, *p);
571 }
572 }
573 else if (is_colon)
574 {
575 if (char_counter == 0)
576 {
577 /*
578 * This means 'X::Y...' which means zero compression.
579 * Flag it!
580 */
581 zero_compression = 1;
582 already_compressed = 1;
583 }
584 else
585 {
586 if (address)
587 {
588 address->sixteen[state] = sixteen;
589 }
590 }
591 ++state;
592 state_change = true;
593 }
594 else
595 {
596 state = 11;
597 state_change = true;
598 }
599 break;
600 case 2:
601 case 3:
602 case 4:
603 case 5:
604 case 6:
605 if (is_hexdigit)
606 {
607 /*
608 * RFC 5952 forbids upper case hex digits
609 */
610 if (is_upper_hexdigit)
611 {
612 state = 11;
613 state_change = true;
614 }
615 else
616 {
617 sixteen = Char2Hex(sixteen, *p);
618 }
619 }
620 else if (is_colon)
621 {
622 if (char_counter == 0)
623 {
624 if (already_compressed)
625 {
626 /*
627 * The '::' symbol can only occur once in a given address.
628 */
629 state = 11;
630 state_change = true;
631 }
632 else
633 {
634 /*
635 * This means '...:X::Y...' which means zero compression.
636 * Flag it!
637 */
638 zero_compression = 1;
639 already_compressed = 1;
640 }
641 }
642 else
643 {
644 if (zero_compression)
645 {
646 /*
647 * If zero compression is enabled, then we cannot trust the position
648 * since we might compressed several fields. We store the value and
649 * look at them afterwards.
650 */
651 unsorted_sixteen[unsorted_pointer] = sixteen;
652 ++unsorted_pointer;
653 }
654 else
655 {
656 /*
657 * No zero compression, just assign the address and keep moving.
658 */
659 if (address)
660 {
661 address->sixteen[state] = sixteen;
662 }
663 }
664 ++state;
665 state_change = true;
666 }
667 }
668 else if (is_end_bracket)
669 {
670 if (bracket_expected && zero_compression)
671 {
672 bracket_expected = 0;
673 /*
674 * RFC 5952 says that we can end an address at any point after
675 * the second position (consequence of the zero compression).
676 * Therefore if we find a ']' we just jump to state 8.
677 */
678 unsorted_sixteen[unsorted_pointer] = sixteen;
679 ++unsorted_pointer;
680 state = 8;
681 state_change = true;
682 }
683 else
684 {
685 /*
686 * Funny stuff, we got a ']' that we were not expecting.
687 * Politely walk back and signal the error.
688 */
689 state = 11;
690 state_change = true;
691 }
692 }
693 else
694 {
695 state = 11;
696 state_change = true;
697 }
698 break;
699 case 7:
700 /*
701 * This case is special.
702 */
703 if (is_hexdigit)
704 {
705 /*
706 * RFC 5952 forbids uppercase hex digits
707 */
708 if (is_upper_hexdigit)
709 {
710 state = 11;
711 state_change = true;
712 }
713 else
714 {
715 sixteen = Char2Hex(sixteen, *p);
716 }
717 }
718 else if (is_end_bracket)
719 {
720 if (bracket_expected)
721 {
722 bracket_expected = 0;
723 if (address)
724 {
725 address->sixteen[state] = sixteen;
726 }
727 /*
728 * The last possible position for a sixteen is number 8.
729 */
730 ++state;
731 state_change = true;
732 }
733 else
734 {
735 /*
736 * Funny stuff, we got a ']' that we were not expecting.
737 * Politely walk back and signal the error.
738 */
739 state = 11;
740 state_change = true;
741 }
742 }
743 else
744 {
745 state = 11;
746 state_change = true;
747 }
748 break;
749 case 8:
750 if (is_colon)
751 {
752 ++state;
753 state_change = true;
754 }
755 else
756 {
757 state = 11;
758 state_change = true;
759 }
760 break;
761 case 9:
762 if (is_digit)
763 {
764 port = Char2Dec(port, *p);
765 }
766 else
767 {
768 state = 11;
769 state_change = true;
770 }
771 break;
772 case 10:
773 break;
774 case 11:
775 default:
776 return -1;
777 break;
778 }
779 char_counter++;
780 if (sixteen > 0xFFFF)
781 {
782 return -1;
783 }
784 if (port > 65535)
785 {
786 return -1;
787 }
788 if (state_change)
789 {
790 sixteen = 0;
791 port = 0;
792 char_counter = 0;
793 is_start_bracket = false;
794 is_end_bracket = false;
795 is_colon = false;
796 is_hexdigit = false;
797 is_upper_hexdigit = false;
798 is_digit = 0;
799 state_change = false;
800 }
801 }
802 /*
803 * Look at the end state and return accordingly.
804 */
805 if ((state == 0) || (state == 1))
806 {
807 /*
808 * These states are not final states, so if we exited is because something went wrong.
809 */
810 return -1;
811 }
812 /*
813 * Thanks to RFC5952 the final states can be intermediate states. This because of zero compression,
814 * which means that the following address 1:0:0:0:0:0:0:1 can be written as
815 * 1::1. Not to mention more exotic varieties such as 1:0:0:0:0:0:0:0 1:: or
816 * 0:0:0:0:0:0:0:0 ::
817 * The first intermediate state that can exit is 2, since even the smallest of all address('::')
818 * will have at least two ':'.
819 * Another exotic case is 'X:0:0:Y:0:0:0:Z' which becomes 'X::Y:0:0:0:Z' or X:0:0:Y::Z because the symbol '::'
820 * can appear only once in a given address.
821 */
822 if ((state == 2) || (state == 3) || (state == 4) || (state == 5) || (state == 6))
823 {
824 /*
825 * We check first for non-closed brackets.
826 * Then we check if there is a number that has not been added to our array.
827 * Finally we move to zero compression.
828 */
829 if (bracket_expected)
830 {
831 return -1;
832 }
833 unsorted_sixteen[unsorted_pointer] = sixteen;
834 ++unsorted_pointer;
835 if (zero_compression)
836 {
837 /*
838 * If there is no address, then we can just return :-)
839 */
840 if (address)
841 {
842 /*
843 * We need to find the rightful positions for those numbers.
844 * We use a simple trick:
845 * We know how many unsorted addresses we have from unsorted pointer,
846 * and we know that once zero_compression is activated we do not fill
847 * any more numbers to the address structure. Therefore the right way
848 * to do this is to take the array of unsorted_sixteen and start assigning
849 * numbers backwards.
850 */
851 int i = 0;
852 for (i = 0; i < unsorted_pointer; ++i)
853 {
854 address->sixteen[7 - i] = unsorted_sixteen[unsorted_pointer - i - 1];
855 }
856 }
857 }
858 else
859 {
860 /*
861 * We cannot end up here without zero compression, or an error.
862 */
863 return -1;
864 }
865 }
866 if (state == 7)
867 {
868 /*
869 * This state corresponds to the final state of a simple ipv6 address, i.e.
870 * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
871 * We exited because we ran out of characters. Let's check that we have something
872 * before assigning things.
873 */
874 if (char_counter == 0)
875 {
876 /*
877 * The last field was empty, signal the error.
878 */
879 return -1;
880 }
881 if (bracket_expected)
882 {
883 /*
884 * We were expecting a bracket but it never came, so this is an error.
885 */
886 return -1;
887 }
888 if (address)
889 {
890 address->sixteen[7] = sixteen;
891 }
892 }
893 if (state == 8)
894 {
895 /*
896 * This state corresponds to the final state if brackets were present.
897 * We still need to check if zero compression was activated and copy
898 * the values if so.
899 */
900 if (zero_compression)
901 {
902 /*
903 * If there is no address, then we can just return :-)
904 */
905 if (address)
906 {
907 /*
908 * We need to find the rightful positions for those numbers.
909 * We use a simple trick:
910 * We know how many unsorted addresses we have from unsorted pointer,
911 * and we know that once zero_compression is activated we do not fill
912 * any more numbers to the address structure. Therefore the right way
913 * to do this is to take the array of unsorted_sixteen and start assigning
914 * numbers backwards.
915 */
916 int i = 0;
917 for (i = 0; i < unsorted_pointer; ++i)
918 {
919 address->sixteen[7 - i] = unsorted_sixteen[i];
920 }
921 }
922 }
923 }
924 if (state == 9)
925 {
926 /*
927 * This state corresponds to the final state if we had brackets around us.
928 * This is usually used to append a port number to the address, so we check
929 * if we have a port and then assign it.
930 */
931 if (char_counter == 0)
932 {
933 /*
934 * The last field was empty, signal the error.
935 */
936 return -1;
937 }
938 if (address)
939 {
940 address->port = port;
941 }
942 }
943 if (state == 11)
944 {
945 /*
946 * Error state
947 */
948 return -1;
949 }
950 return 0;
951 }
952
IPAddressNew(Buffer * source)953 IPAddress *IPAddressNew(Buffer *source)
954 {
955 if (!source || !BufferData(source))
956 {
957 return NULL;
958 }
959 IPAddress *address = NULL;
960 const char *pad = BufferData(source);
961 struct IPV4Address *ipv4 = NULL;
962 struct IPV6Address *ipv6 = NULL;
963 ipv4 = (struct IPV4Address *)xmalloc(sizeof(struct IPV4Address));
964 ipv6 = (struct IPV6Address *)xmalloc(sizeof(struct IPV6Address));
965
966 if (IPV4_parser(pad, ipv4) == 0)
967 {
968 free (ipv6);
969 address = (IPAddress *)xmalloc(sizeof(IPAddress));
970 address->type = IP_ADDRESS_TYPE_IPV4;
971 address->address = (void *)ipv4;
972 }
973 else if (IPV6_parser(pad, ipv6) == 0)
974 {
975 free (ipv4);
976 address = (IPAddress *)xmalloc(sizeof(IPAddress));
977 address->type = IP_ADDRESS_TYPE_IPV6;
978 address->address = (void *)ipv6;
979 }
980 else
981 {
982 /*
983 * It was not a valid IP address.
984 */
985 free (ipv4);
986 free (ipv6);
987 return NULL;
988 }
989 return address;
990 }
991
IPAddressNewHex(Buffer * source)992 IPAddress *IPAddressNewHex(Buffer *source)
993 {
994 if (!source || !BufferData(source))
995 {
996 return NULL;
997 }
998 IPAddress *address = NULL;
999 const char *pad = BufferData(source);
1000 struct IPV4Address *ipv4 = NULL;
1001 struct IPV6Address *ipv6 = NULL;
1002 ipv4 = (struct IPV4Address *)xmalloc(sizeof(struct IPV4Address));
1003 ipv6 = (struct IPV6Address *)xmalloc(sizeof(struct IPV6Address));
1004
1005 if (IPV4_hex_parser(pad, ipv4) == 0)
1006 {
1007 free (ipv6);
1008 address = (IPAddress *)xmalloc(sizeof(IPAddress));
1009 address->type = IP_ADDRESS_TYPE_IPV4;
1010 address->address = (void *)ipv4;
1011 }
1012 else if (IPV6_hex_parser(pad, ipv6) == 0)
1013 {
1014 free (ipv4);
1015 address = (IPAddress *)xmalloc(sizeof(IPAddress));
1016 address->type = IP_ADDRESS_TYPE_IPV6;
1017 address->address = (void *)ipv6;
1018 }
1019 else
1020 {
1021 /*
1022 * It was not a valid IP address.
1023 */
1024 free (ipv4);
1025 free (ipv6);
1026 return NULL;
1027 }
1028 return address;
1029 }
1030
IPAddressDestroy(IPAddress ** address)1031 int IPAddressDestroy(IPAddress **address)
1032 {
1033 if (!address || !(*address))
1034 {
1035 return 0;
1036 }
1037 if ((*address)->address)
1038 {
1039 free ((*address)->address);
1040 }
1041 free (*address);
1042 *address = NULL;
1043 return 0;
1044 }
1045
IPAddressType(IPAddress * address)1046 int IPAddressType(IPAddress *address)
1047 {
1048 if (!address)
1049 {
1050 return -1;
1051 }
1052 return address->type;
1053 }
1054
IPAddressGetAddress(IPAddress * address)1055 Buffer *IPAddressGetAddress(IPAddress *address)
1056 {
1057 if (!address)
1058 {
1059 return NULL;
1060 }
1061 Buffer *buffer = NULL;
1062 int result = 0;
1063
1064 if (address->type == IP_ADDRESS_TYPE_IPV4)
1065 {
1066 struct IPV4Address *ipv4 = (struct IPV4Address *)address->address;
1067 buffer = BufferNew();
1068 #if BIG_ENDIAN
1069 result = BufferPrintf(buffer, "%u.%u.%u.%u", ipv4->octets[0], ipv4->octets[1], ipv4->octets[2], ipv4->octets[3]);
1070 #elif LITTLE_ENDIAN
1071 result = BufferPrintf(buffer, "%u.%u.%u.%u", ipv4->octets[3], ipv4->octets[2], ipv4->octets[1], ipv4->octets[0]);
1072 #else
1073 #warning "Unrecognized endianness, assuming big endian"
1074 result = BufferPrintf(buffer, "%u.%u.%u.%u", ipv4->octets[0], ipv4->octets[1], ipv4->octets[2], ipv4->octets[3]);
1075 #endif
1076 }
1077 else if (address->type == IP_ADDRESS_TYPE_IPV6)
1078 {
1079 struct IPV6Address *ipv6 = (struct IPV6Address *)address->address;
1080 buffer = BufferNew();
1081 #if BIG_ENDIAN
1082 result = BufferPrintf(buffer, "%x:%x:%x:%x:%x:%x:%x:%x", ipv6->sixteen[0], ipv6->sixteen[1], ipv6->sixteen[2],
1083 ipv6->sixteen[3], ipv6->sixteen[4], ipv6->sixteen[5], ipv6->sixteen[6], ipv6->sixteen[7]);
1084 #elif LITTLE_ENDIAN
1085 result = BufferPrintf(buffer, "%x:%x:%x:%x:%x:%x:%x:%x", ipv6->sixteen[7], ipv6->sixteen[6], ipv6->sixteen[5],
1086 ipv6->sixteen[4], ipv6->sixteen[3], ipv6->sixteen[2], ipv6->sixteen[1], ipv6->sixteen[0]);
1087 #else
1088 #warning "Unrecognized endianness, assuming big endian"
1089 result = BufferPrintf(buffer, "%x:%x:%x:%x:%x:%x:%x:%x", ipv6->sixteen[0], ipv6->sixteen[1], ipv6->sixteen[2],
1090 ipv6->sixteen[3], ipv6->sixteen[4], ipv6->sixteen[5], ipv6->sixteen[6], ipv6->sixteen[7]);
1091 #endif
1092 }
1093 else
1094 {
1095 buffer = NULL;
1096 }
1097 if (result < 0)
1098 {
1099 BufferDestroy(buffer);
1100 return NULL;
1101 }
1102 return buffer;
1103 }
1104
IPAddressGetPort(IPAddress * address)1105 int IPAddressGetPort(IPAddress *address)
1106 {
1107 if (!address)
1108 {
1109 return -1;
1110 }
1111 int port = -1;
1112 if (address->type == IP_ADDRESS_TYPE_IPV4)
1113 {
1114 struct IPV4Address *ipv4 = (struct IPV4Address *)address->address;
1115 port = ipv4->port;
1116 }
1117 else if (address->type == IP_ADDRESS_TYPE_IPV6)
1118 {
1119 struct IPV6Address *ipv6 = (struct IPV6Address *)address->address;
1120 port = ipv6->port;
1121 }
1122 else
1123 {
1124 return -1;
1125 }
1126 return port;
1127 }
1128
1129 /*
1130 * Comparison for IPV4 addresses
1131 */
IPV4Compare(struct IPV4Address * a,struct IPV4Address * b)1132 static int IPV4Compare(struct IPV4Address *a, struct IPV4Address *b)
1133 {
1134 int i = 0;
1135 for (i = 0; i < 4; ++i)
1136 {
1137 if (a->octets[i] != b->octets[i])
1138 {
1139 return 0;
1140 }
1141 }
1142 return 1;
1143 }
1144
1145 /*
1146 * Comparison for IPV6 addresses
1147 */
IPV6Compare(struct IPV6Address * a,struct IPV6Address * b)1148 static int IPV6Compare(struct IPV6Address *a, struct IPV6Address *b)
1149 {
1150 int i = 0;
1151 for (i = 0; i < 8; ++i)
1152 {
1153 if (a->sixteen[i] != b->sixteen[i])
1154 {
1155 return 0;
1156 }
1157 }
1158 return 1;
1159 }
1160
IPAddressIsEqual(IPAddress * a,IPAddress * b)1161 int IPAddressIsEqual(IPAddress *a, IPAddress *b)
1162 {
1163 /*
1164 * We do not support IPV4 versus IPV6 comparisons.
1165 * This is trickier than what it seems, since even the IPV6 representation of an IPV6 address is not
1166 * clear yet.
1167 */
1168 if (!a || !b)
1169 {
1170 return -1;
1171 }
1172 if (a->type != b->type)
1173 {
1174 return -1;
1175 }
1176 if (a->type == IP_ADDRESS_TYPE_IPV4)
1177 {
1178 return IPV4Compare((struct IPV4Address *)a->address, (struct IPV4Address *)b->address);
1179 }
1180 else if (a->type == IP_ADDRESS_TYPE_IPV6)
1181 {
1182 return IPV6Compare((struct IPV6Address *)a->address, (struct IPV6Address *)b->address);
1183 }
1184 return -1;
1185 }
1186
1187 /*
1188 * Sorting comparison for IPV4 addresses
1189 */
IPV4CompareLess(struct IPV4Address * a,struct IPV4Address * b)1190 static bool IPV4CompareLess(struct IPV4Address *a, struct IPV4Address *b)
1191 {
1192 int i = 0;
1193 for (i = 0; i < 4; ++i)
1194 {
1195 if (a->octets[i] > b->octets[i])
1196 {
1197 return false;
1198 }
1199 else if (a->octets[i] < b->octets[i])
1200 {
1201 return true;
1202 }
1203 }
1204
1205 return false;
1206 }
1207
1208 /*
1209 * Sorting comparison for IPV6 addresses
1210 */
IPV6CompareLess(struct IPV6Address * a,struct IPV6Address * b)1211 static bool IPV6CompareLess(struct IPV6Address *a, struct IPV6Address *b)
1212 {
1213 int i = 0;
1214 for (i = 0; i < 8; ++i)
1215 {
1216 if (a->sixteen[i] > b->sixteen[i])
1217 {
1218 return false;
1219 }
1220 else if (a->sixteen[i] < b->sixteen[i])
1221 {
1222 return true;
1223 }
1224 }
1225
1226 return false;
1227 }
1228
IPAddressCompareLess(IPAddress * a,IPAddress * b)1229 bool IPAddressCompareLess(IPAddress *a, IPAddress *b)
1230 {
1231 /*
1232 * We do not support IPV4 versus IPV6 comparisons.
1233 * This is trickier than what it seems, since even the IPV6 representation of an IPV6 address is not
1234 * clear yet.
1235 */
1236 if (a == NULL || b == NULL)
1237 {
1238 return true;
1239 }
1240
1241 assert(a->type == IP_ADDRESS_TYPE_IPV4 || a->type == IP_ADDRESS_TYPE_IPV6);
1242 assert(b->type == IP_ADDRESS_TYPE_IPV4 || b->type == IP_ADDRESS_TYPE_IPV6);
1243
1244 // If not same type - Sort IPv4 BEFORE any other types:
1245 if (a->type != b->type)
1246 {
1247 if (a->type == IP_ADDRESS_TYPE_IPV4)
1248 {
1249 return true;
1250 }
1251 else
1252 {
1253 assert(b->type == IP_ADDRESS_TYPE_IPV4);
1254 return false;
1255 }
1256 }
1257
1258 assert(a->type == b->type);
1259 IPAddressVersion type = a->type;
1260
1261 if (type == IP_ADDRESS_TYPE_IPV4)
1262 {
1263 return IPV4CompareLess((struct IPV4Address *)a->address, (struct IPV4Address *)b->address);
1264 }
1265
1266 assert(type == IP_ADDRESS_TYPE_IPV6);
1267
1268 return IPV6CompareLess((struct IPV6Address *)a->address, (struct IPV6Address *)b->address);
1269 }
1270
IPAddressIsIPAddress(Buffer * source,IPAddress ** address)1271 bool IPAddressIsIPAddress(Buffer *source, IPAddress **address)
1272 {
1273 if (!source || !BufferData(source))
1274 {
1275 return false;
1276 }
1277 bool create_object = false;
1278 if (address)
1279 {
1280 create_object = true;
1281 }
1282 const char *pad = BufferData(source);
1283 struct IPV4Address *ipv4 = NULL;
1284 struct IPV6Address *ipv6 = NULL;
1285 ipv4 = (struct IPV4Address *)xmalloc(sizeof(struct IPV4Address));
1286 ipv6 = (struct IPV6Address *)xmalloc(sizeof(struct IPV6Address));
1287 if (IPV4_parser(pad, ipv4) == 0)
1288 {
1289 free (ipv6);
1290 if (create_object)
1291 {
1292 *address = (IPAddress *)xmalloc(sizeof(IPAddress));
1293 (*address)->type = IP_ADDRESS_TYPE_IPV4;
1294 (*address)->address = (void *)ipv4;
1295 }
1296 else
1297 {
1298 /*
1299 * We know it is a valid IPV4 address and we know we don't need the
1300 * IPV4 structure.
1301 */
1302 free (ipv4);
1303 }
1304 }
1305 else if (IPV6_parser(pad, ipv6) == 0)
1306 {
1307 free (ipv4);
1308 if (create_object)
1309 {
1310 *address = (IPAddress *)xmalloc(sizeof(IPAddress));
1311 (*address)->type = IP_ADDRESS_TYPE_IPV6;
1312 (*address)->address = (void *)ipv6;
1313 }
1314 else
1315 {
1316 /*
1317 * We know it is a valid IPV6 address and we know we don't need the
1318 * IPV6 structure.
1319 */
1320 free (ipv6);
1321 }
1322 }
1323 else
1324 {
1325 /*
1326 * It was not a valid IP address.
1327 */
1328 free (ipv4);
1329 free (ipv6);
1330 return false;
1331 }
1332 return true;
1333 }
1334