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
rfc6296.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 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <netinet/in.h>
29 
30 #include "include/dtsapp.h"
31 
33 struct natmap {
35  uint16_t mask;
37  uint16_t adjo;
39  uint16_t adji;
41  uint8_t ipre[16];
43  uint8_t epre[16];
44 };
45 
46 static struct bucket_list *nptv6tbl = NULL;
47 
48 static int32_t nptv6_hash(const void *data, int key) {
49  const struct natmap *map = data;
50  const void *hashkey = (key) ? data : map->ipre;
51  int ret;
52 
53  ret = jenhash(hashkey, sizeof(map->ipre), 0);
54 
55  return (ret);
56 }
57 
62 extern void rfc6296_map(struct natmap *map, struct in6_addr *ipaddr, int out) {
63  uint16_t *addr_16 = (uint16_t *)&ipaddr->s6_addr;
64  uint32_t calc;
65  uint8_t cnt, *prefix, bitlen, bytelen;
66  uint16_t adj;
67 
68  prefix = (out) ? map->epre : map->ipre;
69  adj = (out) ? map->adjo : map->adji;
70 
71  if ((bitlen = map->mask % 8)) {
72  bytelen = (map->mask - bitlen) / 8;
73  bytelen++;
74  } else {
75  bytelen = map->mask / 8;
76  }
77 
78  /*as per RFC we handle /48 and longer /48 changes are reflected in SN*/
79  if ((bytelen == 6) && (~addr_16[3]) && (!bitlen)) {
80  memcpy(&ipaddr->s6_addr, prefix, bytelen);
81  calc = ntohs(addr_16[3]) + adj;
82  addr_16[3] = htons((calc & 0xFFFF) + (calc >> 16));
83  if (! ~addr_16[3]) {
84  addr_16[3] = 0;
85  }
86  } else if ((bytelen > 6) && (bytelen < 15)) {
87  /* find first non 0xFFFF word in lower 64 bits*/
88  for(cnt = ((bytelen-1) >> 1) + 1; cnt < 8; cnt++) {
89  if (! ~addr_16[cnt]) {
90  continue;
91  }
92  if (bitlen) {
93  ipaddr->s6_addr[bytelen-1] = prefix[bytelen-1] | (ipaddr->s6_addr[bytelen-1] & ((1 << (8 - bitlen)) -1));
94  } else {
95  ipaddr->s6_addr[bytelen-1] = prefix[bytelen-1];
96  }
97  memcpy(&ipaddr->s6_addr, prefix, bytelen - 1);
98  calc = ntohs(addr_16[cnt]) + adj;
99  addr_16[cnt] = htons((calc & 0xFFFF) + (calc >> 16));
100  if (! ~addr_16[cnt]) {
101  addr_16[cnt] = 0;
102  }
103  break;
104  }
105  }
106 }
107 
111 extern int rfc6296_map_add(char *intaddr, char *extaddr) {
112  struct natmap *map;
113  uint16_t emask, imask, isum, esum, bytelen, bitlen;
114  char inip[43], exip[43], *tmp2;
115  struct in6_addr i6addr;
116  uint32_t adj;
117 
118  strncpy(inip, intaddr, 43);
119  if ((tmp2 = rindex(inip, '/'))) {
120  tmp2[0] = '\0';
121  tmp2++;
122  imask = atoi(tmp2);
123  } else {
124  return (-1);
125  }
126 
127  strncpy(exip, extaddr, 43);
128  if ((tmp2 = rindex(exip, '/'))) {
129  tmp2[0] = '\0';
130  tmp2++;
131  emask = atoi(tmp2);
132  } else {
133  return (-1);
134  }
135 
136  map = objalloc(sizeof(*map), NULL);
137  map->mask = (emask > imask) ? emask : imask;
138 
139  /*rfc says we must zero extend this is what we do here looking at each supplied len*/
140  /*external range*/
141  inet_pton(AF_INET6, exip, &i6addr);
142  if ((bitlen = emask % 8)) {
143  bytelen = (emask - bitlen) / 8;
144  i6addr.s6_addr[bytelen] &= ~((1 << (8 - bitlen)) - 1);
145  bytelen++;
146  } else {
147  bytelen = emask / 8;
148  }
149  memcpy(map->epre, &i6addr.s6_addr, bytelen);
150 
151  /*internal range*/
152  inet_pton(AF_INET6, inip, &i6addr);
153  if ((bitlen = imask % 8)) {
154  bytelen = (imask - bitlen) / 8;
155  i6addr.s6_addr[bytelen] &= ~((1 << (8 - bitlen)) - 1);
156  bytelen++;
157  } else {
158  bytelen = imask / 8;
159  }
160  memcpy(map->ipre, &i6addr.s6_addr, bytelen);
161 
162  /*calculate the adjustments from checksums of prefixes*/
163  if ((bitlen = map->mask % 8)) {
164  bytelen = (map->mask - bitlen) / 8;
165  bytelen++;
166  } else {
167  bytelen = map->mask / 8;
168  }
169  esum = ntohs(checksum(map->epre, bytelen));
170  isum = ntohs(checksum(map->ipre, bytelen));
171 
172  /*outgoing transform*/
173  adj = esum - isum;
174  adj = (adj & 0xFFFF) + (adj >> 16);
175  map->adjo = (uint16_t)adj;
176 
177  /*incoming transform*/
178  adj = isum - esum;
179  adj = (adj & 0xFFFF) + (adj >> 16);
180  map->adji = (uint16_t)adj;
181 
182  if (!nptv6tbl && (!(nptv6tbl = create_bucketlist(5, nptv6_hash)))) {
183  objunref(map);
184  return (-1);
185  }
186  addtobucket(nptv6tbl, map);
187  objunref(map);
188 
189  return (0);
190 }
191 
197 extern void rfc6296_test(blist_cb callback, struct in6_addr *internal) {
198  /*find and run map*/
199  bucketlist_callback(nptv6tbl, callback, internal);
200 
201  objunref(nptv6tbl);
202 }
203 
uint16_t checksum(const void *data, int len)
Obtain the checksum for a buffer.
Definition: util.c:452
void * create_bucketlist(int bitmask, blisthash hash_function)
Definition: refobj.c:356
uint8_t epre[16]
External prefix.
Definition: rfc6296.c:43
uint16_t mask
The greater of internal or external subnet mask.
Definition: rfc6296.c:35
void * objalloc(int size, objdestroy)
Allocate a referenced lockable object.
Definition: refobj.c:129
uint16_t adjo
Outbound adjustment.
Definition: rfc6296.c:37
uint16_t adji
Inbound adjustment.
Definition: rfc6296.c:39
void rfc6296_test(blist_cb callback, struct in6_addr *internal)
Quick test function.
Definition: rfc6296.c:197
DTS Application library API Include file.
void rfc6296_map(struct natmap *map, struct in6_addr *ipaddr, int out)
Lookup and process a NAT transform as per RFC 6296.
Definition: rfc6296.c:62
int rfc6296_map_add(char *intaddr, char *extaddr)
Calculate and add a NAT map.
Definition: rfc6296.c:111
uint8_t ipre[16]
Internal prefix.
Definition: rfc6296.c:41
void(* blist_cb)(void *, void *)
This callback is run on each entry in a list.
Definition: dtsapp.h:278
void bucketlist_callback(struct bucket_list *blist, blist_cb callback, void *data2)
Run a callback function on all items in the list.
Definition: refobj.c:613
#define jenhash(key, length, initval)
Define jenhash as hashlittle on big endian it should be hashbig.
Definition: dtsapp.h:914
RFC6296 Nat map.
Definition: rfc6296.c:33
int addtobucket(struct bucket_list *blist, void *data)
Add a reference to the bucketlist.
Definition: refobj.c:428
int objunref(void *data)
Drop reference held.
Definition: refobj.c:184
Bucket list, hold hashed objects in buckets.
Definition: refobj.c:75