123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- /* vim: set expandtab ts=4 sw=4: */
- /*
- * You may redistribute this program and/or modify it under the terms of
- * the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include "memory/Allocator.h"
- #include "net/ConverterV15.h"
- #include "util/Identity.h"
- #include "wire/SwitchHeader.h"
- #include "wire/DataHeader.h"
- #include "net/SessionManager.h"
- #include "wire/ContentType.h"
- #include "wire/Headers.h"
- #include "util/Checksum.h"
- #include "wire/RouteHeader.h"
- //#include "util/Hex.h"
- struct ConverterV15_pvt
- {
- struct ConverterV15 pub;
- struct SessionManager* sm;
- uint8_t myIp6[16];
- struct Log* log;
- Identity
- };
- /**
- * Incoming packet with a SessionManager header followed by a ContentHeader and then whatever
- * content.
- */
- static Iface_DEFUN incomingFromUpperDistributorIf(struct Message* msg,
- struct Iface* upperDistributorIf)
- {
- struct ConverterV15_pvt* conv =
- Identity_containerOf(upperDistributorIf, struct ConverterV15_pvt, pub.upperDistributorIf);
- Assert_true(msg->length >= DataHeader_SIZE + RouteHeader_SIZE);
- struct RouteHeader* hdr = (struct RouteHeader*) msg->bytes;
- struct SessionManager_Session* sess = SessionManager_sessionForIp6(hdr->ip6, conv->sm);
- if (hdr->version_be && Endian_bigEndianToHost32(hdr->version_be) < 16) {
- // definitely old
- } else if (!hdr->version_be && sess && sess->version && sess->version < 16) {
- // session thinks it's old
- } else {
- // nothing is known about a node, fuckit, assume it's new !
- return Iface_next(&conv->pub.sessionManagerIf, msg);
- }
- struct DataHeader* dh = (struct DataHeader*) &hdr[1];
- enum ContentType type = DataHeader_getContentType(dh);
- if (type > 257) {
- Log_debug(conv->log, "DROP unconvertible type [%d]", type);
- return NULL;
- }
- // My fears, come alive,
- // in this place where I once died
- // demons dreamin',
- // Knowing I,
- // I just needed to
- // _RE_ALIGN_
- Message_shift(msg, -(DataHeader_SIZE + RouteHeader_SIZE), NULL);
- if (type == ContentType_CJDHT) {
- // push a udp header and then an ip header and then checksum the udp
- Message_shift(msg, Headers_UDPHeader_SIZE, NULL);
- }
- if (type != ContentType_IPTUN) {
- Message_shift(msg, Headers_IP6Header_SIZE, NULL);
- }
- Message_shift(msg, RouteHeader_SIZE, NULL);
- Bits_memmove(msg->bytes, hdr, RouteHeader_SIZE);
- hdr = (struct RouteHeader*) msg->bytes;
- if (type == ContentType_IPTUN) {
- return Iface_next(&conv->pub.sessionManagerIf, msg);
- }
- struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) &hdr[1];
- Bits_memset(ip6, 0, Headers_IP6Header_SIZE);
- Headers_setIpVersion(ip6);
- ip6->hopLimit = 42;
- ip6->nextHeader = type;
- ip6->payloadLength_be = Endian_hostToBigEndian16(
- msg->length - RouteHeader_SIZE - Headers_IP6Header_SIZE);
- Bits_memcpyConst(ip6->destinationAddr, hdr->ip6, 16);
- Bits_memcpyConst(ip6->sourceAddr, conv->myIp6, 16);
- if (type == ContentType_CJDHT) {
- struct Headers_UDPHeader* udp = (struct Headers_UDPHeader*) &ip6[1];
- ip6->nextHeader = 17;
- ip6->hopLimit = 0;
- udp->srcPort_be = 0;
- udp->destPort_be = 0;
- udp->length_be = Endian_hostToBigEndian16(msg->length -
- RouteHeader_SIZE -
- Headers_IP6Header_SIZE -
- Headers_UDPHeader_SIZE);
- udp->checksum_be = 0;
- udp->checksum_be =
- Checksum_udpIp6(ip6->sourceAddr,
- (uint8_t*) udp,
- msg->length - RouteHeader_SIZE - Headers_IP6Header_SIZE);
- //Log_debug(conv->log, "Converted CJDHT->v15");
- }
- //Log_debug(conv->log, "send [%s]", Hex_print(ip6, 32, msg->alloc));
- return Iface_next(&conv->pub.sessionManagerIf, msg);
- }
- //// --------------- Incoming, convert v15 to v16 --------------- ////
- #define tryConvertDHT_OVERHEAD \
- (RouteHeader_SIZE + Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE)
- static inline bool tryConvertDHT(struct Message* msg)
- {
- if (msg->length < tryConvertDHT_OVERHEAD) { return false; }
- struct RouteHeader* bih = (struct RouteHeader*) msg->bytes;
- struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) &bih[1];
- struct Headers_UDPHeader* udp = (struct Headers_UDPHeader*) &ip6[1];
- if (udp->srcPort_be || udp->destPort_be) { return false; }
- Message_shift(msg, -tryConvertDHT_OVERHEAD, NULL);
- struct DataHeader dh = {
- .contentType_be = Endian_hostToBigEndian16(ContentType_CJDHT),
- .versionAndFlags = DataHeader_CURRENT_VERSION << 4
- };
- Message_push(msg, &dh, DataHeader_SIZE, NULL);
- Message_shift(msg, RouteHeader_SIZE, NULL);
- Bits_memmoveConst(msg->bytes, bih, RouteHeader_SIZE);
- return true;
- }
- /**
- * Incoming packet with a SessionManager header and under that either an ipv6 or ipv4 header
- * depending on whether it's destine for TUN/DHT or IpTunnel.
- */
- static Iface_DEFUN incomingFromSessionManagerIf(struct Message* msg, struct Iface* sessionManagerIf)
- {
- struct ConverterV15_pvt* conv =
- Identity_containerOf(sessionManagerIf, struct ConverterV15_pvt, pub.sessionManagerIf);
- if (msg->length < RouteHeader_SIZE + DataHeader_SIZE) {
- Log_debug(conv->log, "DROP runt");
- return NULL;
- }
- struct RouteHeader* bih = (struct RouteHeader*) msg->bytes;
- uint8_t* ipPtr = (uint8_t*) &bih[1];
- //Log_debug(conv->log, "recv [%s]", Hex_print(ipPtr, 32, msg->alloc));
- int ipVer = Headers_getIpVersion(ipPtr);
- if (ipVer == DataHeader_CURRENT_VERSION) {
- return Iface_next(&conv->pub.upperDistributorIf, msg);
- }
- if (ipVer == 0) {
- if (msg->length < RouteHeader_SIZE + Headers_IP6Header_SIZE) {
- Log_debug(conv->log, "DROP runt");
- return NULL;
- }
- struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) ipPtr;
- if (ip6->sourceAddr[0] == 0xfc && ip6->destinationAddr[0] == 0xfc) {
- if (tryConvertDHT(msg)) {
- return Iface_next(&conv->pub.upperDistributorIf, msg);
- }
- }
- } else if (ipVer == 6) {
- if (msg->length < RouteHeader_SIZE + Headers_IP6Header_SIZE) {
- Log_debug(conv->log, "DROP runt");
- return NULL;
- }
- struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) ipPtr;
- if (ip6->sourceAddr[0] == 0xfc && ip6->destinationAddr[0] == 0xfc) {
- Message_pop(msg, NULL, RouteHeader_SIZE + Headers_IP6Header_SIZE, NULL);
- struct DataHeader dh = {
- .contentType_be = Endian_hostToBigEndian16(ip6->nextHeader),
- .versionAndFlags = DataHeader_CURRENT_VERSION << 4
- };
- Message_push(msg, &dh, DataHeader_SIZE, NULL);
- Message_shift(msg, RouteHeader_SIZE, NULL);
- Bits_memmoveConst(msg->bytes, bih, RouteHeader_SIZE);
- return Iface_next(&conv->pub.upperDistributorIf, msg);
- }
- } else if (ipVer != 4) {
- Log_debug(conv->log, "DROP unknown packet ip version");
- return NULL;
- }
- Message_shift(msg, DataHeader_SIZE, NULL);
- Bits_memmoveConst(msg->bytes, bih, RouteHeader_SIZE);
- bih = (struct RouteHeader*) msg->bytes;
- struct DataHeader* dh = (struct DataHeader*) &bih[1];
- Bits_memset(dh, 0, DataHeader_SIZE);
- dh->contentType_be = Endian_hostToBigEndian16(ContentType_IPTUN);
- dh->versionAndFlags = DataHeader_CURRENT_VERSION << 4;
- return Iface_next(&conv->pub.upperDistributorIf, msg);
- }
- struct ConverterV15* ConverterV15_new(struct Allocator* alloc,
- struct Log* log,
- struct SessionManager* sm,
- uint8_t myIp6[16])
- {
- struct ConverterV15_pvt* out = Allocator_calloc(alloc, sizeof(struct ConverterV15_pvt), 1);
- out->pub.upperDistributorIf.send = incomingFromUpperDistributorIf;
- out->pub.sessionManagerIf.send = incomingFromSessionManagerIf;
- out->log = log;
- out->sm = sm;
- Bits_memcpyConst(out->myIp6, myIp6, 16);
- Identity_set(out);
- return &out->pub;
- }
|