DTS Application Library  0.2.3
Application library containing referenced objects and interfaces to common libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
iputil.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 2012 Gregory Nietsky <gregory@distrotetch.co.za>
3  http://www.distrotech.co.za
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
17 */
18 
23 #include <stdlib.h>
24 #include <stdint.h>
25 #include <math.h>
26 #include <stdio.h>
27 #include <string.h>
28 #ifndef __WIN32
29 #include <linux/ip.h>
30 #include <linux/icmp.h>
31 #include <linux/tcp.h>
32 #include <linux/udp.h>
33 #include <netdb.h>
34 #else
35 #include <winsock2.h>
36 #include <ws2tcpip.h>
37 #endif
38 
39 #include "include/dtsapp.h"
40 
47 extern int checkipv6mask(const char *ipaddr, const char *network, uint8_t bits) {
48  uint8_t cnt, bytelen, bitlen;
49  uint32_t mask, res = 0;
50  uint32_t *nw = (uint32_t *)network;
51  uint32_t *ip = (uint32_t *)ipaddr;
52 
53  /*calculate significant bytes and bits outside boundry*/
54  if ((bitlen = bits % 32)) {
55  bytelen = (bits - bitlen) / 32;
56  bytelen++;
57  } else {
58  bytelen = bits / 32;
59  }
60 
61  /*end loop on first mismatch do not check last block*/
62  for(cnt = 0; (!res && (cnt < (bytelen - 1))); cnt++) {
63  res += nw[cnt] ^ ip[cnt];
64  }
65 
66  /*process last block if no error sofar*/
67  if (!res) {
68  mask = (bitlen) ? htonl(~((1 << (32 - bitlen)) - 1)) : -1;
69  res += (nw[cnt] & mask) ^ (ip[cnt] & mask);
70  }
71 
72  return (res);
73 }
74 
77 enum ipversion {
80 };
81 
84 struct pseudohdr {
86  uint32_t saddr;
88  uint32_t daddr;
90  uint8_t zero;
92  uint8_t proto;
94  uint16_t len;
95 };
96 
97 #ifndef __WIN32
98 
101 extern void ipv4tcpchecksum(uint8_t *pkt) {
102  struct iphdr *ip = (struct iphdr *)pkt;
103  struct tcphdr *tcp = (struct tcphdr *)(pkt + (4 * ip->ihl));
104  uint16_t plen, csum;
105  struct pseudohdr phdr;
106 
107  /* get tcp packet len*/
108  plen = ntohs(ip->tot_len) - (4 * ip->ihl);
109  tcp->check = 0;
110  phdr.saddr = ip->saddr;
111  phdr.daddr = ip->daddr;
112  phdr.zero = 0;
113  phdr.proto = ip->protocol;
114  phdr.len = htons(plen);
115  csum = checksum(&phdr, sizeof(phdr));
116  tcp->check = checksum_add(csum, tcp, plen);
117 }
118 
122 extern void ipv4udpchecksum(uint8_t *pkt) {
123  struct iphdr *ip = (struct iphdr *)pkt;
124  struct udphdr *udp = (struct udphdr *)(pkt + (4 * ip->ihl));
125  uint16_t csum, plen;
126  struct pseudohdr phdr;
127 
128  /* get tcp packet len*/
129  plen = ntohs(ip->tot_len) - (4 * ip->ihl);
130  udp->check = 0;
131  phdr.saddr = ip->saddr;
132  phdr.daddr = ip->daddr;
133  phdr.zero = 0;
134  phdr.proto = ip->protocol;
135  phdr.len = htons(plen);
136  csum = checksum(&phdr, sizeof(phdr));
137  udp->check = checksum_add(csum, udp, plen);
138 }
139 
143 extern void ipv4icmpchecksum(uint8_t *pkt) {
144  struct iphdr *ip = (struct iphdr *)pkt;
145  struct icmphdr *icmp = (struct icmphdr *)(pkt + (4 * ip->ihl));
146 
147  icmp->checksum = 0;
148  icmp->checksum = checksum(icmp, ntohs(ip->tot_len) - (ip->ihl *4));
149 }
150 
154 extern void ipv4checksum(uint8_t *pkt) {
155  struct iphdr *ip = (struct iphdr *)pkt;
156 
157  ip->check = 0;
158  ip->check = checksum(ip, (4 * ip->ihl));
159 }
160 
165 extern int packetchecksumv4(uint8_t *pkt) {
166  struct iphdr *ip = (struct iphdr *)pkt;
167 
168  ipv4checksum(pkt);
169 
170  switch(ip->protocol) {
171  case IPPROTO_ICMP:
172  ipv4icmpchecksum(pkt);
173  break;
174  case IPPROTO_TCP:
175  ipv4tcpchecksum(pkt);
176  break;
177  case IPPROTO_UDP:
178  ipv4udpchecksum(pkt);
179  break;
180  default:
181  return (-1);
182  }
183  return (0);
184 }
185 
189 extern int packetchecksumv6(uint8_t *pkt) {
190  struct iphdr *ip = (struct iphdr *)pkt;
191  switch(ip->protocol) {
192  case IPPROTO_ICMP:
193  break;
194  case IPPROTO_TCP:
195  break;
196  case IPPROTO_UDP:
197  break;
198  default:
199  return (-1);
200  }
201  return (0);
202 }
203 
208 extern int packetchecksum(uint8_t *pkt) {
209  struct iphdr *ip = (struct iphdr *)pkt;
210 
211  switch(ip->version) {
212  case IP_PROTO_V4:
213  return (packetchecksumv4(pkt));
214  break;
215  case IP_PROTO_V6:
216  break;
217  }
218  return (-1);
219 }
220 #endif
221 
228 extern const char *cidrtosn(int bitlen, char *buf, int size) {
229  uint32_t nm;
230  uint8_t *nmb = (uint8_t*)&nm;
231 
232  if (!buf) {
233  return NULL;
234  }
235 
236  if (bitlen) {
237  nm = ~((1 << (32-bitlen))-1);
238  } else {
239  nm = 0;
240  }
241 
242  snprintf(buf, size, "%i.%i.%i.%i", nmb[3], nmb[2], nmb[1], nmb[0]);
243  return buf;
244 }
245 
254 extern const char *getnetaddr(const char *ipaddr, int cidr, char *buf, int size) {
255  uint32_t ip;
256  uint8_t *ipb = (uint8_t*)&ip;
257 
258  if (!buf) {
259  return NULL;
260  }
261 
262 #ifndef __WIN32
263  inet_pton(AF_INET, ipaddr, &ip);
264 #else
265  ip = inet_addr(ipaddr);
266 #endif
267  if (cidr) {
268  ip = ntohl(ip);
269  ip = ip & ~((1 << (32-cidr))-1);
270  } else {
271  ip = 0;
272  }
273 
274  snprintf(buf, size, "%i.%i.%i.%i", ipb[3], ipb[2], ipb[1], ipb[0]);
275  return buf;
276 }
277 
286 extern const char *getfirstaddr(const char *ipaddr, int cidr, char *buf, int size) {
287  uint32_t ip;
288  uint8_t *ipb = (uint8_t*)&ip;
289 
290  if (!buf) {
291  return NULL;
292  }
293 
294 #ifndef __WIN32
295  inet_pton(AF_INET, ipaddr, &ip);
296 #else
297  ip = inet_addr(ipaddr);
298 #endif
299  if (cidr) {
300  ip = ntohl(ip);
301  ip = ip & ~((1 << (32-cidr))-1);
302  ip++;
303  } else {
304  ip = 1;
305  }
306 
307  snprintf(buf, size, "%i.%i.%i.%i", ipb[3], ipb[2], ipb[1], ipb[0]);
308  return buf;
309 }
310 
319 extern const char *getbcaddr(const char *ipaddr, int cidr, char *buf, int size) {
320  uint32_t ip, mask;
321  uint8_t *ipb = (uint8_t*)&ip;
322 
323 #ifndef __WIN32
324  inet_pton(AF_INET, ipaddr, &ip);
325 #else
326  ip = inet_addr(ipaddr);
327 #endif
328  if (cidr) {
329  mask = (1 << (32-cidr))-1;
330  ip = ntohl(ip);
331  ip = (ip & ~mask) | mask;
332  } else {
333  ip = 0;
334  }
335  snprintf(buf, size, "%i.%i.%i.%i", ipb[3], ipb[2], ipb[1], ipb[0]);
336  return buf;
337 }
338 
347 extern const char *getlastaddr(const char *ipaddr, int cidr, char *buf, int size) {
348  uint32_t ip, mask;
349  uint8_t *ipb = (uint8_t*)&ip;
350 
351 #ifndef __WIN32
352  inet_pton(AF_INET, ipaddr, &ip);
353 #else
354  ip = inet_addr(ipaddr);
355 #endif
356  if (cidr) {
357  mask = (1 << (32-cidr))-1;
358  ip = ntohl(ip);
359  ip = (ip & ~mask) | mask;
360  ip--;
361  } else {
362  ip = 0;
363  }
364  snprintf(buf, size, "%i.%i.%i.%i", ipb[3], ipb[2], ipb[1], ipb[0]);
365  return buf;
366 }
367 
372 extern uint32_t cidrcnt(int bitlen) {
373  if (bitlen) {
374  return pow(2, (32-bitlen));
375  } else {
376  return 0xFFFFFFFF;
377  }
378 }
379 
384 extern int reservedip(const char *ipaddr) {
385  uint32_t ip;
386 
387 #ifndef __WIN32
388  inet_pton(PF_INET, ipaddr, &ip);
389 #else
390  ip = inet_addr(ipaddr);
391 #endif
392 
393  ip = ntohl(ip);
394 
395  if (!((0xe0000000 ^ ip) >> 28)) { /* 224/4*/
396  return 1;
397  } else if (!((0x00000000 ^ ip) >> 24)) { /* 0/8 */
398  return 1;
399  } else if (!((0x0a000000 ^ ip) >> 24)) { /* 10/8 */
400  return 1;
401  } else if (!((0x7f000000 ^ ip) >> 24)) { /* 127/8 */
402  return 1;
403  } else if (!((0x64400000 ^ ip) >> 22)) { /* 100.64/10 */
404  return 1;
405  } else if (!((0xac100000 ^ ip) >> 20)) { /* 172.16/12 */
406  return 1;
407  } else if (!((0xc6120000 ^ ip) >> 17)) { /* 198.18/15 */
408  return 1;
409  } else if (!((0xc0a80000 ^ ip) >> 16)) { /* 192.168/16 */
410  return 1;
411  } else if (!((0xa9fe0000 ^ ip) >> 16)) { /* 169.254/16 */
412  return 1;
413  } else if (!((0xc0000200 ^ ip) >> 8)) { /* 192.0.2/24 */
414  return 1;
415  } else if (!((0xc6336400 ^ ip) >> 8)) { /* 198.51.100/24 */
416  return 1;
417  } else if (!((0xcb007100 ^ ip) >> 8)) { /* 203.0.113/24 */
418  return 1;
419  }
420  return 0;
421 }
422 
427 extern char* ipv6to4prefix(const char *ipaddr) {
428  uint32_t ip;
429  uint8_t *ipa;
430  char *pre6;
431 
432 #ifndef __WIN32
433  if (!inet_pton(AF_INET, ipaddr, &ip)) {
434  return NULL;
435  }
436 #else
437  if (!(ip = inet_addr(ipaddr))) {
438  return NULL;
439  }
440 #endif
441 
442  pre6 = malloc(10);
443  ipa=(uint8_t*)&ip;
444  snprintf(pre6, 10, "%02x%02x:%02x%02x", ipa[0], ipa[1], ipa[2], ipa[3]);
445  return pre6;
446 }
447 
448 
456 extern int check_ipv4(const char* ip, int cidr, const char *test) {
457  uint32_t ip1, ip2;
458 
459 #ifndef __WIN32
460  inet_pton(AF_INET, ip, &ip1);
461  inet_pton(AF_INET, test, &ip2);
462 #else
463  ip1 = inet_addr(ip);
464  ip2 = inet_addr(test);
465 #endif
466 
467  ip1 = ntohl(ip1) >> (32-cidr);
468  ip2 = ntohl(ip2) >> (32-cidr);
469 
470  if (!(ip1 ^ ip2)) {
471  return 1;
472  } else {
473  return 0;
474  }
475 }
476 
480 void mcast6_ip(struct in6_addr *addr) {
481  int mip, rand;
482  uint32_t *i;
483 
484 #ifndef __WIN32
485  i = (uint32_t*)&addr->s6_addr32;
486 #else
487  i = (uint32_t*)&addr->u.Word;
488 #endif
489  i[0] = htonl(0xFF350000);
490  i[1] = 0;
491  i[2] = 0;
492  i[3] = 1 << 31;
493 
494  do {
495  rand = genrand(&mip, 4);
496  } while (!rand);
497 
498  i[3] = htonl(i[3] | mip);
499 }
500 
504 void mcast4_ip(struct in_addr *addr) {
505  uint32_t mip, rand;
506 
507  do {
508  rand = genrand(&mip, 3);
509  mip >>= 8;
510  } while (!rand || !(mip >> 8));
511  mip |= 232 << 24;
512 
513  addr->s_addr = htonl(mip);
514 }
515 
523 int inet_lookup(int family, const char *host, void *addr, socklen_t len) {
524  struct addrinfo hint, *result, *ainfo;
525  int ret = 0;
526 
527  memset(&hint, 0, sizeof(hint));
528  hint.ai_family = family;
529 
530  if (getaddrinfo(host, NULL, &hint, &result) || !result) {
531  return ret;
532  }
533 
534  for(ainfo = result; ainfo; ainfo = ainfo->ai_next) {
535  switch(ainfo->ai_family) {
536  case PF_INET:
537  if (len >= sizeof(struct in_addr)) {
538  struct sockaddr_in *sa4 = (struct sockaddr_in*)ainfo->ai_addr;
539  memcpy(addr, &sa4->sin_addr, len);
540  ret = 1;
541  }
542  break;
543  case PF_INET6:
544  if (len >= sizeof(struct in6_addr)) {
545  struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)ainfo->ai_addr;
546  memcpy(addr, &sa6->sin6_addr, len);
547  ret = 1;
548  }
549  break;
550  }
551  if (ret) {
552  break;
553  }
554  }
555  freeaddrinfo(result);
556  return ret;
557 }
uint16_t len
Packet length.
Definition: iputil.c:94
uint16_t checksum(const void *data, int len)
Obtain the checksum for a buffer.
Definition: util.c:452
void ipv4tcpchecksum(uint8_t *pkt)
Update the TCP checksum of a IPv4 packet.
Definition: iputil.c:101
void mcast6_ip(struct in6_addr *addr)
Randomally assign a SSM Multicast address.param addr Ip address structure to fill out...
Definition: iputil.c:480
int inet_lookup(int family, const char *host, void *addr, socklen_t len)
Perform DNS lookup on a host/ip retun the IP address.
Definition: iputil.c:523
const char * getbcaddr(const char *ipaddr, int cidr, char *buf, int size)
Return broadcast address.
Definition: iputil.c:319
const char * cidrtosn(int bitlen, char *buf, int size)
Return the dotted quad notation subnet mask from a CIDR.
Definition: iputil.c:228
int packetchecksum(uint8_t *pkt)
Generic IPv4 and IPv6 Checksum.
Definition: iputil.c:208
uint32_t daddr
Destination address.
Definition: iputil.c:88
ipversion
IP Protocol numbers.
Definition: iputil.c:77
uint16_t checksum_add(const uint16_t checksum, const void *data, int len)
Obtain the checksum for a buffer adding a checksum.
Definition: util.c:463
void ipv4checksum(uint8_t *pkt)
Set the checksup of a IPv4 Packet.
Definition: iputil.c:154
int checkipv6mask(const char *ipaddr, const char *network, uint8_t bits)
Check if ipaddr is in a network.
Definition: iputil.c:47
void ipv4icmpchecksum(uint8_t *pkt)
Set the checksup of a IPv4 ICMP packet.
Definition: iputil.c:143
DTS Application library API Include file.
int packetchecksumv6(uint8_t *pkt)
Prototype to check checksup on packet.
Definition: iputil.c:189
uint8_t proto
protocol.
Definition: iputil.c:92
int reservedip(const char *ipaddr)
Check IP against list of reserved IP&#39;s.
Definition: iputil.c:384
int genrand(void *buf, int len)
Generate random sequence.
Definition: util.c:82
uint32_t saddr
Source address.
Definition: iputil.c:86
void ipv4udpchecksum(uint8_t *pkt)
Update the UDP checksum of a IPv4 packet.
Definition: iputil.c:122
const char * getnetaddr(const char *ipaddr, int cidr, char *buf, int size)
Return the network address.
Definition: iputil.c:254
uint32_t cidrcnt(int bitlen)
Return the number of IP addresses in a given bitmask.
Definition: iputil.c:372
void mcast4_ip(struct in_addr *addr)
Randomally assign a SSM Multicast address.
Definition: iputil.c:504
IPv4 header structur to cast a packet too.
Definition: iputil.c:84
int packetchecksumv4(uint8_t *pkt)
Update the checksum of a IPv4 packet.
Definition: iputil.c:165
int check_ipv4(const char *ip, int cidr, const char *test)
Check if a IP address is in a network.
Definition: iputil.c:456
char * ipv6to4prefix(const char *ipaddr)
Return IPv6 to IPv4 Prefix fot the address.
Definition: iputil.c:427
const char * getfirstaddr(const char *ipaddr, int cidr, char *buf, int size)
Get the first usable address.
Definition: iputil.c:286
const char * getlastaddr(const char *ipaddr, int cidr, char *buf, int size)
Get the last usable address.
Definition: iputil.c:347
uint8_t zero
Zero byte.
Definition: iputil.c:90