1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374 |
- /*
- Copyright (c) 2007, 2008 by Juliusz Chroboczek
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <assert.h>
- #include <sys/time.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include "babeld.h"
- #include "util.h"
- #include "net.h"
- #include "interface.h"
- #include "source.h"
- #include "neighbour.h"
- #include "route.h"
- #include "kernel.h"
- #include "xroute.h"
- #include "resend.h"
- #include "message.h"
- #include "configuration.h"
- #include "lorauth.h"
- unsigned char packet_header[4] = {42, 2};
- int split_horizon = 1;
- unsigned short myseqno = 0;
- struct timeval seqno_time = {0, 0};
- #define UNICAST_BUFSIZE 1024
- int unicast_buffered = 0;
- unsigned char *unicast_buffer = NULL;
- struct neighbour *unicast_neighbour = NULL;
- struct timeval unicast_flush_timeout = {0, 0};
- extern const unsigned char v4prefix[16];
- // -- lorauth --
- unsigned char buffered_cipher[514];
- // ----
- #define MAX_CHANNEL_HOPS 20
- /* Parse a network prefix, encoded in the somewhat baroque compressed
- representation used by Babel. Return the number of bytes parsed. */
- static int
- network_prefix(int ae, int plen, unsigned int omitted,
- const unsigned char *p, const unsigned char *dp,
- unsigned int len, unsigned char *p_r)
- {
- unsigned pb;
- unsigned char prefix[16];
- int ret = -1;
- if(plen >= 0)
- pb = (plen + 7) / 8;
- else if(ae == 1)
- pb = 4;
- else
- pb = 16;
- if(pb > 16)
- return -1;
- memset(prefix, 0, 16);
- switch(ae) {
- case 0:
- ret = 0;
- break;
- case 1:
- if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted))
- return -1;
- memcpy(prefix, v4prefix, 12);
- if(omitted) {
- if(dp == NULL || !v4mapped(dp)) return -1;
- memcpy(prefix, dp, 12 + omitted);
- }
- if(pb > omitted) memcpy(prefix + 12 + omitted, p, pb - omitted);
- ret = pb - omitted;
- break;
- case 2:
- if(omitted > 16 || (pb > omitted && len < pb - omitted)) return -1;
- if(omitted) {
- if(dp == NULL || v4mapped(dp)) return -1;
- memcpy(prefix, dp, omitted);
- }
- if(pb > omitted) memcpy(prefix + omitted, p, pb - omitted);
- ret = pb - omitted;
- break;
- case 3:
- if(pb > 8 && len < pb - 8) return -1;
- prefix[0] = 0xfe;
- prefix[1] = 0x80;
- if(pb > 8) memcpy(prefix + 8, p, pb - 8);
- ret = pb - 8;
- break;
- default:
- return -1;
- }
- normalize_prefix(p_r, prefix, plen < 0 ? 128 : ae == 1 ? plen + 96 : plen);
- return ret;
- }
- static void
- parse_update_subtlv(struct interface *ifp, int metric,
- const unsigned char *a, int alen,
- unsigned char *channels, int *channels_len_return)
- {
- int type, len, i = 0;
- int channels_len;
- /* This will be overwritten if there's a DIVERSITY_HOPS sub-TLV. */
- if(*channels_len_return < 1 || (ifp->flags & IF_FARAWAY)) {
- channels_len = 0;
- } else {
- if(metric < 256) {
- /* Assume non-interfering (wired) link. */
- channels_len = 0;
- } else {
- /* Assume interfering. */
- channels[0] = IF_CHANNEL_INTERFERING;
- channels_len = 1;
- }
- }
- while(i < alen) {
- type = a[i];
- if(type == SUBTLV_PAD1) {
- i++;
- continue;
- }
- if(i + 1 > alen) {
- fprintf(stderr, "Received truncated attributes.\n");
- return;
- }
- len = a[i + 1];
- if(i + len > alen) {
- fprintf(stderr, "Received truncated attributes.\n");
- return;
- }
- if(type == SUBTLV_PADN) {
- /* Nothing. */
- } else if(type == SUBTLV_DIVERSITY) {
- memcpy(channels, a + i + 2, MIN(len, *channels_len_return));
- channels_len = MIN(len, *channels_len_return);
- } else {
- debugf("Received unknown update sub-TLV %d.\n", type);
- }
- i += len + 2;
- }
- *channels_len_return = channels_len;
- }
- static int
- parse_hello_subtlv(const unsigned char *a, int alen,
- unsigned int *hello_send_us)
- {
- int type, len, i = 0, ret = 0;
- while(i < alen) {
- type = a[0];
- if(type == SUBTLV_PAD1) {
- i++;
- continue;
- }
- if(i + 1 > alen) {
- fprintf(stderr, "Received truncated sub-TLV on Hello message.\n");
- return -1;
- }
- len = a[i + 1];
- if(i + len > alen) {
- fprintf(stderr, "Received truncated sub-TLV on Hello message.\n");
- return -1;
- }
- if(type == SUBTLV_PADN) {
- /* Nothing to do. */
- } else if(type == SUBTLV_TIMESTAMP) {
- if(len >= 4) {
- DO_NTOHL(*hello_send_us, a + i + 2);
- ret = 1;
- } else {
- fprintf(stderr,
- "Received incorrect RTT sub-TLV on Hello message.\n");
- }
- } else {
- debugf("Received unknown Hello sub-TLV type %d.\n", type);
- }
- i += len + 2;
- }
- return ret;
- }
- static int
- parse_ihu_subtlv(const unsigned char *a, int alen,
- unsigned int *hello_send_us,
- unsigned int *hello_rtt_receive_time)
- {
- int type, len, i = 0, ret = 0;
- while(i < alen) {
- type = a[0];
- if(type == SUBTLV_PAD1) {
- i++;
- continue;
- }
- if(i + 1 > alen) {
- fprintf(stderr, "Received truncated sub-TLV on IHU message.\n");
- return -1;
- }
- len = a[i + 1];
- if(i + len > alen) {
- fprintf(stderr, "Received truncated sub-TLV on IHU message.\n");
- return -1;
- }
- if(type == SUBTLV_PADN) {
- /* Nothing to do. */
- } else if(type == SUBTLV_TIMESTAMP) {
- if(len >= 8) {
- DO_NTOHL(*hello_send_us, a + i + 2);
- DO_NTOHL(*hello_rtt_receive_time, a + i + 6);
- ret = 1;
- }
- else {
- fprintf(stderr,
- "Received incorrect RTT sub-TLV on IHU message.\n");
- }
- } else {
- debugf("Received unknown IHU sub-TLV type %d.\n", type);
- }
- i += len + 2;
- }
- return ret;
- }
- static int
- network_address(int ae, const unsigned char *a, unsigned int len,
- unsigned char *a_r)
- {
- return network_prefix(ae, -1, 0, a, NULL, len, a_r);
- }
- void
- parse_packet(const unsigned char *from, struct interface *ifp,
- const unsigned char *packet, int packetlen)
- {
- int i;
- const unsigned char *message;
- unsigned char type, len;
- int bodylen;
- struct neighbour *neigh;
- int have_router_id = 0, have_v4_prefix = 0, have_v6_prefix = 0,
- have_v4_nh = 0, have_v6_nh = 0;
- unsigned char router_id[8], v4_prefix[16], v6_prefix[16],
- v4_nh[16], v6_nh[16];
- int have_hello_rtt = 0;
- /* Content of the RTT sub-TLV on IHU messages. */
- unsigned int hello_send_us = 0, hello_rtt_receive_time = 0;
- // -- lorauth --
- unsigned short clen = 0;
- clean_cipher(buffered_cipher);
- // ----
- if(ifp->flags & IF_TIMESTAMPS) {
- /* We want to track exactly when we received this packet. */
- gettime(&now);
- }
- if(!linklocal(from)) {
- fprintf(stderr, "Received packet from non-local address %s.\n",
- format_address(from));
- return;
- }
- if(packet[0] != 42) {
- fprintf(stderr, "Received malformed packet on %s from %s.\n",
- ifp->name, format_address(from));
- return;
- }
- if(packet[1] != 2) {
- fprintf(stderr,
- "Received packet with unknown version %d on %s from %s.\n",
- packet[1], ifp->name, format_address(from));
- return;
- }
- neigh = find_neighbour(from, ifp);
- if(neigh == NULL) {
- fprintf(stderr, "Couldn't allocate neighbour.\n");
- return;
- }
- DO_NTOHS(bodylen, packet + 2);
- if(bodylen + 4 > packetlen) {
- fprintf(stderr, "Received truncated packet (%d + 4 > %d).\n",
- bodylen, packetlen);
- bodylen = packetlen - 4;
- }
- i = 0;
- while(i < bodylen) {
- message = packet + 4 + i;
- type = message[0];
- if(type == MESSAGE_PAD1) {
- debugf("Received pad1 from %s on %s.\n",
- format_address(from), ifp->name);
- i++;
- continue;
- }
- if(i + 1 > bodylen) {
- fprintf(stderr, "Received truncated message.\n");
- break;
- }
- len = message[1];
- if(i + len > bodylen) {
- fprintf(stderr, "Received truncated message.\n");
- break;
- }
- if(type == MESSAGE_PADN) {
- debugf("Received pad%d from %s on %s.\n",
- len, format_address(from), ifp->name);
- } else if(type == MESSAGE_ACK_REQ) {
- unsigned short nonce, interval;
- if(len < 6) goto fail;
- DO_NTOHS(nonce, message + 4);
- DO_NTOHS(interval, message + 6);
- debugf("Received ack-req (%04X %d) from %s on %s.\n",
- nonce, interval, format_address(from), ifp->name);
- send_ack(neigh, nonce, interval);
- } else if(type == MESSAGE_ACK) {
- debugf("Received ack from %s on %s.\n",
- format_address(from), ifp->name);
- /* Nothing right now */
- } else if(type == MESSAGE_HELLO) {
- unsigned short seqno, interval;
- int changed;
- unsigned int timestamp;
- if(len < 6) goto fail;
- DO_NTOHS(seqno, message + 4);
- DO_NTOHS(interval, message + 6);
- debugf("Received hello %d (%d) from %s on %s.\n",
- seqno, interval,
- format_address(from), ifp->name);
- changed = update_neighbour(neigh, seqno, interval);
- update_neighbour_metric(neigh, changed);
- if(interval > 0)
- /* Multiply by 3/2 to allow hellos to expire. */
- schedule_neighbours_check(interval * 15, 0);
- /* Sub-TLV handling. */
- if(len > 8) {
- if(parse_hello_subtlv(message + 8, len - 6, ×tamp) > 0) {
- neigh->hello_send_us = timestamp;
- neigh->hello_rtt_receive_time = now;
- have_hello_rtt = 1;
- }
- }
- } else if(type == MESSAGE_IHU) {
- unsigned short txcost, interval;
- unsigned char address[16];
- int rc;
- if(len < 6) goto fail;
- DO_NTOHS(txcost, message + 4);
- DO_NTOHS(interval, message + 6);
- rc = network_address(message[2], message + 8, len - 6, address);
- if(rc < 0) goto fail;
- debugf("Received ihu %d (%d) from %s on %s for %s.\n",
- txcost, interval,
- format_address(from), ifp->name,
- format_address(address));
- if(message[2] == 0 || interface_ll_address(ifp, address)) {
- int changed = txcost != neigh->txcost;
- neigh->txcost = txcost;
- neigh->ihu_time = now;
- neigh->ihu_interval = interval;
- update_neighbour_metric(neigh, changed);
- if(interval > 0)
- /* Multiply by 3/2 to allow neighbours to expire. */
- schedule_neighbours_check(interval * 45, 0);
- /* RTT sub-TLV. */
- if(len > 10 + rc)
- parse_ihu_subtlv(message + 8 + rc, len - 6 - rc,
- &hello_send_us, &hello_rtt_receive_time);
- }
- } else if(type == MESSAGE_ROUTER_ID) {
- if(len < 10) {
- have_router_id = 0;
- goto fail;
- }
- memcpy(router_id, message + 4, 8);
- have_router_id = 1;
- debugf("Received router-id %s from %s on %s.\n",
- format_eui64(router_id), format_address(from), ifp->name);
- } else if(type == MESSAGE_NH) {
- unsigned char nh[16];
- int rc;
- if(len < 2) {
- have_v4_nh = 0;
- have_v6_nh = 0;
- goto fail;
- }
- rc = network_address(message[2], message + 4, len - 2,
- nh);
- if(rc < 0) {
- have_v4_nh = 0;
- have_v6_nh = 0;
- goto fail;
- }
- debugf("Received nh %s (%d) from %s on %s.\n",
- format_address(nh), message[2],
- format_address(from), ifp->name);
- if(message[2] == 1) {
- memcpy(v4_nh, nh, 16);
- have_v4_nh = 1;
- } else {
- memcpy(v6_nh, nh, 16);
- have_v6_nh = 1;
- }
- } else if(type == MESSAGE_UPDATE) {
- unsigned char prefix[16], *nh;
- unsigned char plen;
- unsigned char channels[MAX_CHANNEL_HOPS];
- int channels_len = MAX_CHANNEL_HOPS;
- unsigned short interval, seqno, metric;
- int rc, parsed_len;
- if(len < 10) {
- if(len < 2 || message[3] & 0x80)
- have_v4_prefix = have_v6_prefix = 0;
- goto fail;
- }
- DO_NTOHS(interval, message + 6);
- DO_NTOHS(seqno, message + 8);
- DO_NTOHS(metric, message + 10);
- if(message[5] == 0 ||
- (message[2] == 1 ? have_v4_prefix : have_v6_prefix))
- rc = network_prefix(message[2], message[4], message[5],
- message + 12,
- message[2] == 1 ? v4_prefix : v6_prefix,
- len - 10, prefix);
- else
- rc = -1;
- if(rc < 0) {
- if(message[3] & 0x80)
- have_v4_prefix = have_v6_prefix = 0;
- goto fail;
- }
- parsed_len = 10 + rc;
- plen = message[4] + (message[2] == 1 ? 96 : 0);
- if(message[3] & 0x80) {
- if(message[2] == 1) {
- memcpy(v4_prefix, prefix, 16);
- have_v4_prefix = 1;
- } else {
- memcpy(v6_prefix, prefix, 16);
- have_v6_prefix = 1;
- }
- }
- if(message[3] & 0x40) {
- if(message[2] == 1) {
- memset(router_id, 0, 4);
- memcpy(router_id + 4, prefix + 12, 4);
- } else {
- memcpy(router_id, prefix + 8, 8);
- }
- have_router_id = 1;
- }
- if(!have_router_id && message[2] != 0) {
- fprintf(stderr, "Received prefix with no router id.\n");
- goto fail;
- }
- debugf("Received update%s%s for %s from %s on %s.\n",
- (message[3] & 0x80) ? "/prefix" : "",
- (message[3] & 0x40) ? "/id" : "",
- format_prefix(prefix, plen),
- format_address(from), ifp->name);
- // -- lorauth --
- debugf("--trying update_route\n");
- if(strlen((char *)buffered_cipher)>3){
- debugf(" --Cipher on update\n");
- debugf(" buffered_cipher:%s size: %d\n" ,
- reduced_lorauth_token(buffered_cipher),
- (unsigned int)strlen((char *)buffered_cipher));
- /* Checking authentication (see: doc-lorauth/README.es.md)
- The rule here is, if the route entry exists (meaning that the
- update has alread been authenticated) there is no need to do
- the authentication process.
- If the route entry does not exists, then the authentication process
- has to be done, it means decrypting the received cipher, then get
- the prefix and last octets to check (id, seqno). The decrypted
- prefix is compared with the announced prefix, then the decrypted
- last octets are used to check for the (id, seqno) announced.
-
- If the authentication is complete the update is considered, if not
- it is ignored.
- */
- printf(" --- lorauth AUTHENTICATION ---\n");
- struct babel_route *a_route;
- a_route = find_installed_route(prefix, plen, zeroes, 0);
- if(a_route){
- debugf(" announced route already authenticated, skiping.\n");
- }
- else{
- rc = check_lorauth_token(router_id,
- prefix,
- seqno,
- clen,
- buffered_cipher);
- if(rc == -1) {
- // some logs
- printf("\n\tprefix: %s\n\tid:%s",
- format_prefix(prefix, plen),
- format_eui64(router_id));
- printf("\n\t\t*** FAILED ***\n\n");
- goto done;
- }
- else if(rc==0){
- printf("\n\tprefix: %s\n\tid:%s\n\tcipher: %s",
- format_prefix(prefix, plen),
- format_eui64(router_id),
- reduced_lorauth_token(buffered_cipher));
- printf("\n\t\t~ ~ ~ ~ ~\n\t\t PASSED \n\t\t~ ~ ~ ~ ~ ~\n");
- }
- }
- }
- else{
- printf("\n\tprefix: %s\n\tid:%s",
- format_prefix(prefix, plen),
- format_eui64(router_id));
- printf(" \n\tNo Cipher on update\n\n\t\t***** REJECTING UPDATE *****\n");
- goto done;
- }
- // ----
- if(message[2] == 0) {
- if(metric < 0xFFFF) {
- fprintf(stderr,
- "Received wildcard update with finite metric.\n");
- goto done;
- }
- retract_neighbour_routes(neigh);
- goto done;
- } else if(message[2] == 1) {
- if(!have_v4_nh)
- goto fail;
- nh = v4_nh;
- } else if(have_v6_nh) {
- nh = v6_nh;
- } else {
- nh = neigh->address;
- }
- if(message[2] == 1) {
- if(!ifp->ipv4)
- goto done;
- }
- parse_update_subtlv(ifp, metric, message + 2 + parsed_len,
- len - parsed_len, channels, &channels_len);
-
- update_route(router_id, prefix, plen, zeroes, 0,
- buffered_cipher, clen,
- seqno,
- metric, interval, neigh, nh,
- channels, channels_len);
- } else if(type == MESSAGE_REQUEST) {
- unsigned char prefix[16], plen;
- int rc;
- if(len < 2) goto fail;
- rc = network_prefix(message[2], message[3], 0,
- message + 4, NULL, len - 2, prefix);
- if(rc < 0) goto fail;
- plen = message[3] + (message[2] == 1 ? 96 : 0);
- debugf("Received request for %s from %s on %s.\n",
- message[2] == 0 ? "any" : format_prefix(prefix, plen),
- format_address(from), ifp->name);
- if(message[2] == 0) {
- /* If a neighbour is requesting a full route dump from us,
- we might as well send it an IHU. */
- send_ihu(neigh, NULL);
- /* Since nodes send wildcard requests on boot, booting
- a large number of nodes at the same time may cause an
- update storm. Ignore a wildcard request that happens
- shortly after we sent a full update. */
- if(neigh->ifp->last_update_time <
- now.tv_sec - MAX(neigh->ifp->hello_interval / 100, 1))
-
- /* lorauth note: Here check if it is correct to send a
- proably empty buffered_cipher.*/
- send_update(neigh->ifp, 0, NULL, 0, zeroes, 0,
- // -- lorauth --
- buffered_cipher, clen);
- } else {
- send_update(neigh->ifp, 0, prefix, plen, zeroes, 0,
- // -- lorauth --
- buffered_cipher, clen);
- }
- } else if(type == MESSAGE_MH_REQUEST) {
- unsigned char prefix[16], plen;
- unsigned short seqno;
- int rc;
- if(len < 14) goto fail;
- DO_NTOHS(seqno, message + 4);
- rc = network_prefix(message[2], message[3], 0,
- message + 16, NULL, len - 14, prefix);
- if(rc < 0) goto fail;
- plen = message[3] + (message[2] == 1 ? 96 : 0);
- debugf("Received request (%d) for %s from %s on %s (%s, %d).\n",
- message[6],
- format_prefix(prefix, plen),
- format_address(from), ifp->name,
- format_eui64(message + 8), seqno);
- /* lorauth note: Here handle_request checks whether it is needed to change
- lorauth token when the seqno is changed
- */
- handle_request(neigh, prefix, plen, zeroes, 0, message[6], seqno, message + 8);
- } else if(type == MESSAGE_UPDATE_SRC_SPECIFIC) {
- unsigned char prefix[16], src_prefix[16], *nh;
- unsigned char ae, plen, src_plen, omitted;
- unsigned char channels[MAX_CHANNEL_HOPS];
- int channels_len = MAX_CHANNEL_HOPS;
- unsigned short interval, seqno, metric;
- const unsigned char *src_prefix_beginning = NULL;
- int rc, parsed_len = 0;
- if(len < 10)
- goto fail;
- ae = message[2];
- src_plen = message[3];
- plen = message[4];
- omitted = message[5];
- DO_NTOHS(interval, message + 6);
- DO_NTOHS(seqno, message + 8);
- DO_NTOHS(metric, message + 10);
- if(omitted == 0 || (ae == 1 ? have_v4_prefix : have_v6_prefix))
- rc = network_prefix(ae, plen, omitted, message + 12,
- ae == 1 ? v4_prefix : v6_prefix,
- len - 10, prefix);
- else
- rc = -1;
- if(rc < 0)
- goto fail;
- parsed_len = 10 + rc;
- src_prefix_beginning = message + 2 + parsed_len;
- rc = network_prefix(ae, src_plen, 0, src_prefix_beginning, NULL,
- len - parsed_len, src_prefix);
- if(rc < 0)
- goto fail;
- parsed_len += rc;
- if(ae == 1) {
- plen += 96;
- src_plen += 96;
- }
- if(!have_router_id) {
- fprintf(stderr, "Received prefix with no router id.\n");
- goto fail;
- }
- debugf("Received ss-update for (%s from %s) from %s on %s.\n",
- format_prefix(prefix, plen),
- format_prefix(src_prefix, src_plen),
- format_address(from), ifp->name);
- if(ae == 0) {
- debugf("Received invalid Source-Specific wildcard update.\n");
- retract_neighbour_routes(neigh);
- goto done;
- } else if(ae == 1) {
- if(!have_v4_nh)
- goto fail;
- nh = v4_nh;
- } else if(have_v6_nh) {
- nh = v6_nh;
- } else {
- nh = neigh->address;
- }
- if(ae == 1) {
- if(!ifp->ipv4)
- goto done;
- }
- parse_update_subtlv(ifp, metric, message + 2 + parsed_len,
- len - parsed_len, channels, &channels_len);
- update_route(router_id, prefix, plen, src_prefix, src_plen,
- buffered_cipher, clen,
- seqno, metric, interval, neigh, nh,
- channels, channels_len);
- } else if(type == MESSAGE_REQUEST_SRC_SPECIFIC) {
- unsigned char prefix[16], plen, ae, src_prefix[16], src_plen;
- int rc, parsed = 5;
- if(len < 3) goto fail;
- ae = message[2];
- plen = message[3];
- src_plen = message[4];
- rc = network_prefix(ae, plen, 0, message + parsed,
- NULL, len + 2 - parsed, prefix);
- if(rc < 0) goto fail;
- if(ae == 1)
- plen += 96;
- parsed += rc;
- rc = network_prefix(ae, src_plen, 0, message + parsed,
- NULL, len + 2 - parsed, src_prefix);
- if(rc < 0) goto fail;
- if(ae == 1)
- src_plen += 96;
- parsed += rc;
- if(ae == 0) {
- debugf("Received request for any source-specific "
- "from %s on %s.\n",
- format_address(from), ifp->name);
- /* See comments for std requests. */
- send_ihu(neigh, NULL);
- if(neigh->ifp->last_specific_update_time <
- now.tv_sec - MAX(neigh->ifp->hello_interval / 100, 1))
- send_update(neigh->ifp, 0, zeroes, 0, NULL, 0,
- // -- lorauth --
- buffered_cipher, clen);
- } else {
- debugf("Received request for (%s from %s) from %s on %s.\n",
- format_prefix(prefix, plen),
- format_prefix(src_prefix, src_plen),
- format_address(from), ifp->name);
- /* send_update(neigh->ifp, 0, prefix, plen, src_prefix, src_plen, */
- /* NULL, 0); */
- /* check wether to update cipher and clen in this case.*/
- send_update(neigh->ifp, 0, prefix, plen, src_prefix, src_plen,
- // -- lorauth --
- buffered_cipher, clen);
- }
- } else if(type == MESSAGE_MH_REQUEST_SRC_SPECIFIC) {
- unsigned char prefix[16], plen, ae, src_prefix[16], src_plen, hopc;
- const unsigned char *router_id;
- unsigned short seqno;
- int rc, parsed = 16;
- if(len < 14) goto fail;
- ae = message[2];
- plen = message[3];
- DO_NTOHS(seqno, message + 4);
- hopc = message[6];
- src_plen = message[7];
- router_id = message + 8;
- rc = network_prefix(ae, plen, 0, message + parsed,
- NULL, len + 2 - parsed, prefix);
- if(rc < 0) goto fail;
- if(ae == 1)
- plen += 96;
- parsed += rc;
- rc = network_prefix(ae, src_plen, 0, message + parsed,
- NULL, len + 2 - parsed, src_prefix);
- if(rc < 0) goto fail;
- if(ae == 1)
- src_plen += 96;
- debugf("Received request (%d) for (%s, %s)"
- " from %s on %s (%s, %d).\n",
- message[6],
- format_prefix(prefix, plen),
- format_prefix(src_prefix, src_plen),
- format_address(from), ifp->name,
- format_eui64(router_id), seqno);
- handle_request(neigh, prefix, plen, src_prefix, src_plen,
- hopc, seqno, router_id);
- }
- // -- lorauth ---
- else if(type == MESSAGE_LORAUTH) {
- /* parsing lorauth TLV
- see doc-lorauth/babel-integration.es.md */
- unsigned char lorauth_packet_number = message[2];
-
- debugf("-- lorauth packet received Np:%d\n", lorauth_packet_number);
- if((lorauth_packet_number == 3 && len != 8) ||
- (lorauth_packet_number != 3 && len != 255) ||
- len > 255) {
- debugf("incorrect length in lorauth packet: %d\n",len);
- clen = 0;
- goto fail;
- }
- if((lorauth_packet_number == 3 && message[3] != 6) ||
- (lorauth_packet_number != 3 && message[3] != 253) ||
- message[3] > 253) {
- debugf("incorrect clen in lorauth packet: %c\n", message[3]);
- clen = 0;
- goto fail;
- }
-
- strncpy((char *)buffered_cipher + ((lorauth_packet_number-1)*253) ,
- (char *)message + 4, message[3]);
- if(strlen((char *)buffered_cipher)==LORAUTH_CIPHER_LEN) {
- clen = LORAUTH_CIPHER_LEN;
- debugf(" -- received cipher: %s\n", buffered_cipher);
- }
- /* Checking authentication (see: doc-lorauth/README.es.md)
- (it is done when receiving an UPDATE TLV)
- The rule here is, if the route entry exists (meaning that the
- update has alread been authenticated) there is no need to do
- the authentication process.
- If the route entry does not exists, then the authentication process
- has to be done, it means decrypting the received cipher, then get
- the prefix and last octets to check (id, seqno). The decrypted
- prefix is compared with the announced prefix, then the decrypted
- last octets are used to check for the (id, seqno) announced.
-
- If the authentication is complete the update is considered, if not
- it is ignored.
- */
- }
- // ----
- else {
- debugf("Received unknown packet type %d from %s on %s.\n",
- type, format_address(from), ifp->name);
- }
- done:
- i += len + 2;
- continue;
- fail:
- clean_cipher(buffered_cipher);
- fprintf(stderr, "Couldn't parse packet (%d, %d) from %s on %s.\n",
- message[0], message[1], format_address(from), ifp->name);
- goto done;
- }
- /* We can calculate the RTT to this neighbour. */
- if(have_hello_rtt && hello_send_us && hello_rtt_receive_time) {
- int remote_waiting_us, local_waiting_us;
- unsigned int rtt, smoothed_rtt;
- unsigned int old_rttcost;
- int changed = 0;
- remote_waiting_us = neigh->hello_send_us - hello_rtt_receive_time;
- local_waiting_us = time_us(neigh->hello_rtt_receive_time) -
- hello_send_us;
- /* Sanity checks (validity window of 10 minutes). */
- if(remote_waiting_us < 0 || local_waiting_us < 0 ||
- remote_waiting_us > 600000000 || local_waiting_us > 600000000)
- return;
- rtt = MAX(0, local_waiting_us - remote_waiting_us);
- debugf("RTT to %s on %s sample result: %d us.\n",
- format_address(from), ifp->name, rtt);
- old_rttcost = neighbour_rttcost(neigh);
- if(valid_rtt(neigh)) {
- /* Running exponential average. */
- smoothed_rtt = (ifp->rtt_decay * rtt +
- (256 - ifp->rtt_decay) * neigh->rtt);
- /* Rounding (up or down) to get closer to the sample. */
- neigh->rtt = (neigh->rtt >= rtt) ? smoothed_rtt / 256 :
- (smoothed_rtt + 255) / 256;
- } else {
- /* We prefer to be conservative with new neighbours
- (higher RTT) */
- assert(rtt <= 0x7FFFFFFF);
- neigh->rtt = 2*rtt;
- }
- changed = (neighbour_rttcost(neigh) == old_rttcost ? 0 : 1);
- update_neighbour_metric(neigh, changed);
- neigh->rtt_time = now;
- }
- clean_cipher(buffered_cipher);
- return;
- }
- /* Under normal circumstances, there are enough moderation mechanisms
- elsewhere in the protocol to make sure that this last-ditch check
- should never trigger. But I'm superstitious. */
- static int
- check_bucket(struct interface *ifp)
- {
- if(ifp->bucket <= 0) {
- int seconds = now.tv_sec - ifp->bucket_time;
- if(seconds > 0) {
- ifp->bucket = MIN(BUCKET_TOKENS_MAX,
- seconds * BUCKET_TOKENS_PER_SEC);
- }
- /* Reset bucket time unconditionally, in case clock is stepped. */
- ifp->bucket_time = now.tv_sec;
- }
- if(ifp->bucket > 0) {
- ifp->bucket--;
- return 1;
- } else {
- return 0;
- }
- }
- static int
- fill_rtt_message(struct interface *ifp)
- {
- if((ifp->flags & IF_TIMESTAMPS) && (ifp->buffered_hello >= 0)) {
- if(ifp->sendbuf[ifp->buffered_hello + 8] == SUBTLV_PADN &&
- ifp->sendbuf[ifp->buffered_hello + 9] == 4) {
- unsigned int time;
- /* Change the type of sub-TLV. */
- ifp->sendbuf[ifp->buffered_hello + 8] = SUBTLV_TIMESTAMP;
- gettime(&now);
- time = time_us(now);
- DO_HTONL(ifp->sendbuf + ifp->buffered_hello + 10, time);
- return 1;
- } else {
- fprintf(stderr,
- "No space left for timestamp sub-TLV "
- "(this shouldn't happen)\n");
- return -1;
- }
- }
- return 0;
- }
- void
- flushbuf(struct interface *ifp)
- {
- int rc;
- struct sockaddr_in6 sin6;
- assert(ifp->buffered <= ifp->bufsize);
- flushupdates(ifp);
- if(ifp->buffered > 0) {
- debugf(" (flushing %d buffered bytes on %s)\n",
- ifp->buffered, ifp->name);
- if(check_bucket(ifp)) {
- memset(&sin6, 0, sizeof(sin6));
- sin6.sin6_family = AF_INET6;
- memcpy(&sin6.sin6_addr, protocol_group, 16);
- sin6.sin6_port = htons(protocol_port);
- sin6.sin6_scope_id = ifp->ifindex;
- DO_HTONS(packet_header + 2, ifp->buffered);
- fill_rtt_message(ifp);
- rc = babel_send(protocol_socket,
- packet_header, sizeof(packet_header),
- ifp->sendbuf, ifp->buffered,
- (struct sockaddr*)&sin6, sizeof(sin6));
- if(rc < 0)
- perror("send");
- } else {
- fprintf(stderr, "Warning: bucket full, dropping packet to %s.\n",
- ifp->name);
- }
- }
- VALGRIND_MAKE_MEM_UNDEFINED(ifp->sendbuf, ifp->bufsize);
- ifp->buffered = 0;
- ifp->buffered_hello = -1;
- ifp->have_buffered_id = 0;
- ifp->have_buffered_nh = 0;
- // -- lorauth --
- ifp-> have_buffered_cipher = 0;
- // ----
- ifp->have_buffered_prefix = 0;
- ifp->flush_timeout.tv_sec = 0;
- ifp->flush_timeout.tv_usec = 0;
- }
- static void
- schedule_flush(struct interface *ifp)
- {
- unsigned msecs = jitter(ifp, 0);
- if(ifp->flush_timeout.tv_sec != 0 &&
- timeval_minus_msec(&ifp->flush_timeout, &now) < msecs)
- return;
- set_timeout(&ifp->flush_timeout, msecs);
- }
- static void
- schedule_flush_now(struct interface *ifp)
- {
- /* Almost now */
- unsigned msecs = roughly(10);
- if(ifp->flush_timeout.tv_sec != 0 &&
- timeval_minus_msec(&ifp->flush_timeout, &now) < msecs)
- return;
- set_timeout(&ifp->flush_timeout, msecs);
- }
- static void
- schedule_unicast_flush(unsigned msecs)
- {
- if(!unicast_neighbour)
- return;
- if(unicast_flush_timeout.tv_sec != 0 &&
- timeval_minus_msec(&unicast_flush_timeout, &now) < msecs)
- return;
- unicast_flush_timeout.tv_usec = (now.tv_usec + msecs * 1000) % 1000000;
- unicast_flush_timeout.tv_sec =
- now.tv_sec + (now.tv_usec / 1000 + msecs) / 1000;
- }
- static void
- ensure_space(struct interface *ifp, int space)
- {
- if(ifp->bufsize - ifp->buffered < space)
- flushbuf(ifp);
- }
- static void
- start_message(struct interface *ifp, int type, int len)
- {
- if(ifp->bufsize - ifp->buffered < len + 2)
- flushbuf(ifp);
- ifp->sendbuf[ifp->buffered++] = type;
- ifp->sendbuf[ifp->buffered++] = len;
- }
- static void
- end_message(struct interface *ifp, int type, int bytes)
- {
- /*
- debugf(" ifp->buffered %d >= bytes+2=%d --> %d\n ifp->sendbuf[ifp->buffered- bytes -2 ]=%d(%d) == type=%d --> %d\n ifp->sendbuf[ifp->buffered - bytes -1]=%d(%d) == bytes --> %d\n",
- ifp->buffered,
- bytes+2,
- ifp->buffered >= bytes + 2,
- ifp->buffered - bytes - 2,
- ifp->sendbuf[ifp->buffered - bytes - 2],
- type,
- ifp->sendbuf[ifp->buffered - bytes - 2] == type,
- ifp->buffered - bytes - 1 ,
- ifp->sendbuf[ifp->buffered - bytes - 1],
- ifp->sendbuf[ifp->buffered - bytes - 1] == bytes);
- */
- // -- lorauth --
- /* if(type==MESSAGE_LORAUTH) */
- /* debugf(" lorauth case ^ \n"); */
- assert(ifp->buffered >= bytes + 2 &&
- ifp->sendbuf[ifp->buffered - bytes - 2] == type &&
- ifp->sendbuf[ifp->buffered - bytes - 1] == bytes);
- // --
- schedule_flush(ifp);
- }
- static void
- accumulate_byte(struct interface *ifp, unsigned char value)
- {
- ifp->sendbuf[ifp->buffered++] = value;
- }
- static void
- accumulate_short(struct interface *ifp, unsigned short value)
- {
- DO_HTONS(ifp->sendbuf + ifp->buffered, value);
- ifp->buffered += 2;
- }
- static void
- accumulate_int(struct interface *ifp, unsigned int value)
- {
- DO_HTONL(ifp->sendbuf + ifp->buffered, value);
- ifp->buffered += 4;
- }
- static void
- accumulate_bytes(struct interface *ifp,
- const unsigned char *value, unsigned len)
- {
- memcpy(ifp->sendbuf + ifp->buffered, value, len);
- ifp->buffered += len;
- }
- static int
- start_unicast_message(struct neighbour *neigh, int type, int len)
- {
- if(unicast_neighbour) {
- if(neigh != unicast_neighbour ||
- unicast_buffered + len + 2 >=
- MIN(UNICAST_BUFSIZE, neigh->ifp->bufsize))
- flush_unicast(0);
- }
- if(!unicast_buffer)
- unicast_buffer = malloc(UNICAST_BUFSIZE);
- if(!unicast_buffer) {
- perror("malloc(unicast_buffer)");
- return -1;
- }
- unicast_neighbour = neigh;
- unicast_buffer[unicast_buffered++] = type;
- unicast_buffer[unicast_buffered++] = len;
- return 1;
- }
- static void
- end_unicast_message(struct neighbour *neigh, int type, int bytes)
- {
- assert(unicast_neighbour == neigh && unicast_buffered >= bytes + 2 &&
- unicast_buffer[unicast_buffered - bytes - 2] == type &&
- unicast_buffer[unicast_buffered - bytes - 1] == bytes);
- schedule_unicast_flush(jitter(neigh->ifp, 0));
- }
- static void
- accumulate_unicast_byte(struct neighbour *neigh, unsigned char value)
- {
- unicast_buffer[unicast_buffered++] = value;
- }
- static void
- accumulate_unicast_short(struct neighbour *neigh, unsigned short value)
- {
- DO_HTONS(unicast_buffer + unicast_buffered, value);
- unicast_buffered += 2;
- }
- static void
- accumulate_unicast_int(struct neighbour *neigh, unsigned int value)
- {
- DO_HTONL(unicast_buffer + unicast_buffered, value);
- unicast_buffered += 4;
- }
- static void
- accumulate_unicast_bytes(struct neighbour *neigh,
- const unsigned char *value, unsigned len)
- {
- memcpy(unicast_buffer + unicast_buffered, value, len);
- unicast_buffered += len;
- }
- void
- send_ack(struct neighbour *neigh, unsigned short nonce, unsigned short interval)
- {
- int rc;
- debugf("Sending ack (%04x) to %s on %s.\n",
- nonce, format_address(neigh->address), neigh->ifp->name);
- rc = start_unicast_message(neigh, MESSAGE_ACK, 2); if(rc < 0) return;
- accumulate_unicast_short(neigh, nonce);
- end_unicast_message(neigh, MESSAGE_ACK, 2);
- /* Roughly yields a value no larger than 3/2, so this meets the deadline */
- schedule_unicast_flush(roughly(interval * 6));
- }
- void
- send_hello_noupdate(struct interface *ifp, unsigned interval)
- {
- /* This avoids sending multiple hellos in a single packet, which breaks
- link quality estimation. */
- if(ifp->buffered_hello >= 0)
- flushbuf(ifp);
- ifp->hello_seqno = seqno_plus(ifp->hello_seqno, 1);
- set_timeout(&ifp->hello_timeout, ifp->hello_interval);
- if(!if_up(ifp))
- return;
- debugf("Sending hello %d (%d) to %s.\n",
- ifp->hello_seqno, interval, ifp->name);
- start_message(ifp, MESSAGE_HELLO, (ifp->flags & IF_TIMESTAMPS) ? 12 : 6);
- ifp->buffered_hello = ifp->buffered - 2;
- accumulate_short(ifp, 0);
- accumulate_short(ifp, ifp->hello_seqno);
- accumulate_short(ifp, interval > 0xFFFF ? 0xFFFF : interval);
- if(ifp->flags & IF_TIMESTAMPS) {
- /* Sub-TLV containing the local time of emission. We use a
- Pad4 sub-TLV, which we'll fill just before sending. */
- accumulate_byte(ifp, SUBTLV_PADN);
- accumulate_byte(ifp, 4);
- accumulate_int(ifp, 0);
- }
- end_message(ifp, MESSAGE_HELLO, (ifp->flags & IF_TIMESTAMPS) ? 12 : 6);
- }
- void
- send_hello(struct interface *ifp)
- {
- send_hello_noupdate(ifp, (ifp->hello_interval + 9) / 10);
- /* Send full IHU every 3 hellos, and marginal IHU each time */
- if(ifp->hello_seqno % 3 == 0)
- send_ihu(NULL, ifp);
- else
- send_marginal_ihu(ifp);
- }
- void
- flush_unicast(int dofree)
- {
- struct sockaddr_in6 sin6;
- int rc;
- if(unicast_buffered == 0)
- goto done;
- if(!if_up(unicast_neighbour->ifp))
- goto done;
- /* Preserve ordering of messages */
- flushbuf(unicast_neighbour->ifp);
- if(check_bucket(unicast_neighbour->ifp)) {
- memset(&sin6, 0, sizeof(sin6));
- sin6.sin6_family = AF_INET6;
- memcpy(&sin6.sin6_addr, unicast_neighbour->address, 16);
- sin6.sin6_port = htons(protocol_port);
- sin6.sin6_scope_id = unicast_neighbour->ifp->ifindex;
- DO_HTONS(packet_header + 2, unicast_buffered);
- fill_rtt_message(unicast_neighbour->ifp);
- rc = babel_send(protocol_socket,
- packet_header, sizeof(packet_header),
- unicast_buffer, unicast_buffered,
- (struct sockaddr*)&sin6, sizeof(sin6));
- if(rc < 0)
- perror("send(unicast)");
- } else {
- fprintf(stderr,
- "Warning: bucket full, dropping unicast packet "
- "to %s if %s.\n",
- format_address(unicast_neighbour->address),
- unicast_neighbour->ifp->name);
- }
- done:
- VALGRIND_MAKE_MEM_UNDEFINED(unicast_buffer, UNICAST_BUFSIZE);
- unicast_buffered = 0;
- if(dofree && unicast_buffer) {
- free(unicast_buffer);
- unicast_buffer = NULL;
- }
- unicast_neighbour = NULL;
- unicast_flush_timeout.tv_sec = 0;
- unicast_flush_timeout.tv_usec = 0;
- }
- static void
- really_send_update(struct interface *ifp,
- const unsigned char *id,
- const unsigned char *prefix, unsigned char plen,
- const unsigned char *src_prefix, unsigned char src_plen,
- // -- lorauth --
- const unsigned char *cipher, unsigned short clen,
- // ----
- unsigned short seqno, unsigned short metric,
- unsigned char *channels, int channels_len)
- {
- int add_metric, v4, real_plen, omit = 0;
- const unsigned char *real_prefix;
- const unsigned char *real_src_prefix = NULL;
- int real_src_plen = 0;
- unsigned short flags = 0;
- int channels_size;
- if(diversity_kind != DIVERSITY_CHANNEL)
- channels_len = -1;
- channels_size = channels_len >= 0 ? channels_len + 2 : 0;
- if(!if_up(ifp))
- return;
- add_metric = output_filter(id, prefix, plen, src_prefix,
- src_plen, ifp->ifindex);
- if(add_metric >= INFINITY)
- return;
- metric = MIN(metric + add_metric, INFINITY);
- /* Worst case */
- ensure_space(ifp, 20 + 12 + 28 + 18);
- v4 = plen >= 96 && v4mapped(prefix);
- if(v4) {
- if(!ifp->ipv4)
- return;
- if(!ifp->have_buffered_nh ||
- memcmp(ifp->buffered_nh, ifp->ipv4, 4) != 0) {
- // bufs NH as the interface's prefix
- start_message(ifp, MESSAGE_NH, 6);
- accumulate_byte(ifp, 1);
- accumulate_byte(ifp, 0);
- accumulate_bytes(ifp, ifp->ipv4, 4);
- end_message(ifp, MESSAGE_NH, 6);
- memcpy(ifp->buffered_nh, ifp->ipv4, 4);
- ifp->have_buffered_nh = 1;
- }
- real_prefix = prefix + 12;
- real_plen = plen - 96;
- if(src_plen != 0 /* it should never be 96 */) {
- real_src_prefix = src_prefix + 12;
- real_src_plen = src_plen - 96;
- }
- } else {
- if(ifp->have_buffered_prefix) {
- while(omit < plen / 8 &&
- ifp->buffered_prefix[omit] == prefix[omit])
- omit++;
- }
- if(src_plen == 0 && (!ifp->have_buffered_prefix || plen >= 48))
- flags |= 0x80;
- real_prefix = prefix;
- real_plen = plen;
- real_src_prefix = src_prefix;
- real_src_plen = src_plen;
- }
- if(!ifp->have_buffered_id || memcmp(id, ifp->buffered_id, 8) != 0) {
- // bufs router_id TLV
- if(src_plen == 0 && real_plen == 128 &&
- memcmp(real_prefix + 8, id, 8) == 0) {
- flags |= 0x40;
- } else {
- start_message(ifp, MESSAGE_ROUTER_ID, 10);
- accumulate_short(ifp, 0);
- accumulate_bytes(ifp, id, 8);
- end_message(ifp, MESSAGE_ROUTER_ID, 10);
- }
- memcpy(ifp->buffered_id, id, 8);
- ifp->have_buffered_id = 1;
- }
- // -- lorauth --
- /* Buffering LORAUTH TLV in case there is cipher text to send*/
- if (clen > 0 && strlen((char *)cipher) > 3)
- {
- /* Spliting in 3 packets (see doc-lorauth/babel-integration.es.md)*/
- // packet 1
- start_message(ifp, MESSAGE_LORAUTH, 255);
- accumulate_byte(ifp, 1);
- accumulate_byte(ifp, 253);
- accumulate_bytes(ifp, cipher, 253);
- //debugf(" sendbuf size: %d\n", ifp->buffered);
- end_message(ifp, MESSAGE_LORAUTH, 255);
- ifp->have_buffered_cipher = 1;
- //packet 2
- start_message(ifp, MESSAGE_LORAUTH, 255);
- accumulate_byte(ifp, 2);
- accumulate_byte(ifp, 253);
- accumulate_bytes(ifp, cipher+253, 253);
- //debugf(" sendbuf size: %d\n", ifp->buffered);
- end_message(ifp, MESSAGE_LORAUTH, 255);
- ifp->have_buffered_cipher = 1;
- //packet 3
- start_message(ifp, MESSAGE_LORAUTH, 8);
- accumulate_byte(ifp, 3);
- accumulate_byte(ifp, 6);
- accumulate_bytes(ifp, cipher+506, 6);
- //debugf(" sendbuf size: %d\n", ifp->buffered);
- end_message(ifp, MESSAGE_LORAUTH, 8);
- debugf(" --Done sent lorauth TLV.\n");
- ifp->have_buffered_cipher = 1;
- }
- // ----
- // buffering UPDATE TLV
- if(src_plen == 0)
- start_message(ifp, MESSAGE_UPDATE, 10 + (real_plen + 7) / 8 - omit +
- channels_size);
- else
- start_message(ifp, MESSAGE_UPDATE_SRC_SPECIFIC,
- 10 + (real_plen + 7) / 8 - omit +
- (real_src_plen + 7) / 8 + channels_size);
- accumulate_byte(ifp, v4 ? 1 : 2);
- if(src_plen != 0)
- accumulate_byte(ifp, real_src_plen);
- else
- accumulate_byte(ifp, flags);
- accumulate_byte(ifp, real_plen);
- accumulate_byte(ifp, omit);
- accumulate_short(ifp, (ifp->update_interval + 5) / 10);
- accumulate_short(ifp, seqno);
- accumulate_short(ifp, metric);
- accumulate_bytes(ifp, real_prefix + omit, (real_plen + 7) / 8 - omit);
- if(src_plen != 0)
- accumulate_bytes(ifp, real_src_prefix, (real_src_plen + 7) / 8);
- /* Note that an empty channels TLV is different from no such TLV. */
- if(channels_len >= 0) {
- accumulate_byte(ifp, 2);
- accumulate_byte(ifp, channels_len);
- accumulate_bytes(ifp, channels, channels_len);
- }
- if(src_plen == 0)
- end_message(ifp, MESSAGE_UPDATE, 10 + (real_plen + 7) / 8 - omit +
- channels_size);
- else
- end_message(ifp, MESSAGE_UPDATE_SRC_SPECIFIC,
- 10 + (real_plen + 7) / 8 - omit +
- (real_src_plen + 7) / 8 + channels_size);
- if(flags & 0x80) {
- memcpy(ifp->buffered_prefix, prefix, 16);
- ifp->have_buffered_prefix = 1;
- }
- }
- static int
- compare_buffered_updates(const void *av, const void *bv)
- {
- const struct buffered_update *a = av, *b = bv;
- int rc, v4a, v4b, ma, mb;
- rc = memcmp(a->id, b->id, 8);
- if(rc != 0)
- return rc;
- v4a = (a->plen >= 96 && v4mapped(a->prefix));
- v4b = (b->plen >= 96 && v4mapped(b->prefix));
- if(v4a > v4b)
- return 1;
- else if(v4a < v4b)
- return -1;
- ma = (!v4a && a->plen == 128 && memcmp(a->prefix + 8, a->id, 8) == 0);
- mb = (!v4b && b->plen == 128 && memcmp(b->prefix + 8, b->id, 8) == 0);
- if(ma > mb)
- return -1;
- else if(mb > ma)
- return 1;
- if(a->plen < b->plen)
- return 1;
- else if(a->plen > b->plen)
- return -1;
- rc = memcmp(a->prefix, b->prefix, 16);
- if(rc != 0)
- return rc;
- if(a->src_plen < b->src_plen)
- return -1;
- else if(a->src_plen > b->src_plen)
- return 1;
- return memcmp(a->src_prefix, b->src_prefix, 16);
- }
- void
- flushupdates(struct interface *ifp)
- {
- struct xroute *xroute;
- struct babel_route *route;
- const unsigned char *last_prefix = NULL;
- const unsigned char *last_src_prefix = NULL;
- unsigned char last_plen = 0xFF;
- unsigned char last_src_plen = 0xFF;
- int i;
- if(ifp == NULL) {
- struct interface *ifp_aux;
- FOR_ALL_INTERFACES(ifp_aux)
- flushupdates(ifp_aux);
- return;
- }
- if(ifp->num_buffered_updates > 0) {
- struct buffered_update *b = ifp->buffered_updates;
- int n = ifp->num_buffered_updates;
- ifp->buffered_updates = NULL;
- ifp->update_bufsize = 0;
- ifp->num_buffered_updates = 0;
- if(!if_up(ifp))
- goto done;
- debugf(" (flushing %d buffered updates on %s (%d))\n",
- n, ifp->name, ifp->ifindex);
- /* In order to send fewer update messages, we want to send updates
- with the same router-id together, with IPv6 going out before IPv4. */
- for(i = 0; i < n; i++) {
- route = find_installed_route(b[i].prefix, b[i].plen,
- b[i].src_prefix, b[i].src_plen);
- if(route)
- memcpy(b[i].id, route->src->id, 8);
- else
- memcpy(b[i].id, myid, 8);
- }
- qsort(b, n, sizeof(struct buffered_update), compare_buffered_updates);
- for(i = 0; i < n; i++) {
- /* The same update may be scheduled multiple times before it is
- sent out. Since our buffer is now sorted, it is enough to
- compare with the previous update. */
- if(last_prefix &&
- b[i].plen == last_plen &&
- b[i].src_plen == last_src_plen &&
- memcmp(b[i].prefix, last_prefix, 16) == 0 &&
- memcmp(b[i].src_prefix, last_src_prefix, 16) == 0)
- continue;
- //debugf("--b[%d], prefix %s, src_prefix %s\n", i, b[i].prefix, b[i].src_prefix);
- xroute = find_xroute(b[i].prefix, b[i].plen,
- b[i].src_prefix, b[i].src_plen);
- route = find_installed_route(b[i].prefix, b[i].plen,
- b[i].src_prefix, b[i].src_plen);
- //debugf("--route, prefix %s, src_prefix %s\n", route->src->prefix, route->src->src_prefix);
- if(xroute && (!route || xroute->metric <= kernel_metric)) {
- really_send_update(ifp, myid,
- xroute->prefix, xroute->plen,
- xroute->src_prefix, xroute->src_plen,
- // -- lorauth --
- xroute->cipher, xroute->clen,
- // ----
- myseqno, xroute->metric,
- NULL, 0);
- last_prefix = xroute->prefix;
- last_plen = xroute->plen;
- last_src_prefix = xroute->src_prefix;
- last_src_plen = xroute->src_plen;
- } else if(route) {
- unsigned char channels[MAX_CHANNEL_HOPS];
- int chlen;
- struct interface *route_ifp = route->neigh->ifp;
- unsigned short metric;
- unsigned short seqno;
- seqno = route->seqno;
- metric =
- route_interferes(route, ifp) ?
- route_metric(route) :
- route_metric_noninterfering(route);
- if(metric < INFINITY)
- satisfy_request(route->src->prefix, route->src->plen,
- route->src->src_prefix,
- route->src->src_plen,
- seqno, route->src->id, ifp);
- if((ifp->flags & IF_SPLIT_HORIZON) &&
- route->neigh->ifp == ifp)
- continue;
- if(route_ifp->channel == IF_CHANNEL_NONINTERFERING) {
- memcpy(channels, route->channels,
- MIN(route->channels_len, MAX_CHANNEL_HOPS));
- chlen = MIN(route->channels_len, MAX_CHANNEL_HOPS);
- } else {
- if(route_ifp->channel == IF_CHANNEL_UNKNOWN)
- channels[0] = IF_CHANNEL_INTERFERING;
- else {
- assert(route_ifp->channel > 0 &&
- route_ifp->channel <= 255);
- channels[0] = route_ifp->channel;
- }
- memcpy(channels + 1, route->channels,
- MIN(route->channels_len, MAX_CHANNEL_HOPS - 1));
- chlen = 1 + MIN(route->channels_len, MAX_CHANNEL_HOPS - 1);
- }
- //lorauth note: Check if the following is correct
- really_send_update(ifp, route->src->id,
- route->src->prefix, route->src->plen,
- route->src->src_prefix, route->src->src_plen,
- // -- lorauth --
- //xroute->cipher, xroute->clen,
- NULL, 0, //??
- // ----
- seqno, metric,
- channels, chlen);
- update_source(route->src, seqno, metric);
- last_prefix = route->src->prefix;
- last_plen = route->src->plen;
- last_src_prefix = route->src->src_prefix;
- last_src_plen = route->src->src_plen;
- } else {
- /* There's no route for this prefix. This can happen shortly
- after an xroute has been retracted, so send a retraction. */
- really_send_update(ifp, myid, b[i].prefix, b[i].plen,
- b[i].src_prefix, b[i].src_plen,
- // -- lorauth --
- NULL, 0,
- // ----
- myseqno, INFINITY, NULL, -1);
- }
- }
- schedule_flush_now(ifp);
- done:
- free(b);
- }
- ifp->update_flush_timeout.tv_sec = 0;
- ifp->update_flush_timeout.tv_usec = 0;
- }
- static void
- schedule_update_flush(struct interface *ifp, int urgent)
- {
- unsigned msecs;
- msecs = update_jitter(ifp, urgent);
- if(ifp->update_flush_timeout.tv_sec != 0 &&
- timeval_minus_msec(&ifp->update_flush_timeout, &now) < msecs)
- return;
- set_timeout(&ifp->update_flush_timeout, msecs);
- }
- static void
- buffer_update(struct interface *ifp,
- const unsigned char *prefix, unsigned char plen,
- const unsigned char *src_prefix, unsigned char src_plen,
- // -- lorauth --
- const unsigned char *cipher, unsigned short clen)
- {
- if(ifp->num_buffered_updates > 0 &&
- ifp->num_buffered_updates >= ifp->update_bufsize)
- flushupdates(ifp);
- if(ifp->update_bufsize == 0) {
- int n;
- assert(ifp->buffered_updates == NULL);
- /* Allocate enough space to hold a full update. Since the
- number of installed routes will grow over time, make sure we
- have enough space to send a full-ish frame. */
- n = installed_routes_estimate() + xroutes_estimate() + 4;
- n = MAX(n, ifp->bufsize / 16);
- again:
- ifp->buffered_updates = malloc(n * sizeof(struct buffered_update));
- if(ifp->buffered_updates == NULL) {
- perror("malloc(buffered_updates)");
- if(n > 4) {
- /* Try again with a tiny buffer. */
- n = 4;
- goto again;
- }
- return;
- }
- ifp->update_bufsize = n;
- ifp->num_buffered_updates = 0;
- }
- memcpy(ifp->buffered_updates[ifp->num_buffered_updates].prefix,
- prefix, 16);
- ifp->buffered_updates[ifp->num_buffered_updates].plen = plen;
- memcpy(ifp->buffered_updates[ifp->num_buffered_updates].src_prefix,
- src_prefix, 16);
- ifp->buffered_updates[ifp->num_buffered_updates].src_plen = src_plen;
- // -- lorauth --
- if(clen > 0) {
- ifp->buffered_updates[ifp->num_buffered_updates].clen = clen;
- memcpy(ifp->buffered_updates[ifp->num_buffered_updates].cipher,
- cipher, clen);
- ifp->have_buffered_cipher = 1;
- debugf(" done buffering clen, cipher (%d bytes)\n", clen);
- }
- else{
- debugf(" not buffering cipher token\n");
- }
- // ----
- ifp->num_buffered_updates++;
- }
- /* Full wildcard update with prefix == src_prefix == NULL,
- Standard wildcard update with prefix == NULL && src_prefix != NULL,
- Specific wildcard update with prefix != NULL && src_prefix == NULL. */
- void
- send_update(struct interface *ifp, int urgent,
- const unsigned char *prefix, unsigned char plen,
- const unsigned char *src_prefix, unsigned char src_plen,
- // -- lorauth --
- const unsigned char *cipher, unsigned short clen
- // ----
- )
- {
- if(ifp == NULL) {
- struct interface *ifp_aux;
- struct babel_route *route;
- FOR_ALL_INTERFACES(ifp_aux)
- send_update(ifp_aux, urgent, prefix, plen, src_prefix, src_plen,
- cipher, clen);
- if(prefix) {
- /* Since flushupdates only deals with non-wildcard interfaces, we
- need to do this now. */
- route = find_installed_route(prefix, plen, src_prefix, src_plen);
- if(route && route_metric(route) < INFINITY)
- satisfy_request(prefix, plen, src_prefix, src_plen,
- route->src->seqno, route->src->id, NULL);
- }
- return;
- }
- if(!if_up(ifp))
- return;
- if(prefix && src_prefix) {
- debugf("Sending update to %s for %s from %s \ncipher: %s\n",
- ifp->name, format_prefix(prefix, plen),
- format_prefix(src_prefix, src_plen),
- // -- lorauth --
- strlen((char *)cipher)<4 ? (char *)"--":
- (char *)reduced_lorauth_token(cipher));
- buffer_update(ifp, prefix, plen, src_prefix, src_plen,
- // -- lorauth --
- cipher, clen
- // ----
- );
- } else if(prefix || src_prefix) {
- struct route_stream *routes;
- send_self_update(ifp);
- debugf("Sending update to %s for any.\n", ifp->name);
- routes = route_stream(ROUTE_INSTALLED);
- if(routes) {
- while(1) {
- struct babel_route *route = route_stream_next(routes);
- if(route == NULL)
- break;
- if((src_prefix && route->src->src_plen != 0) ||
- (prefix && route->src->src_plen == 0))
- continue;
- buffer_update(ifp, route->src->prefix, route->src->plen,
- route->src->src_prefix, route->src->src_plen,
- // -- lorauth --
- route->src->cipher,
- route->src->clen
- // ----
- );
- }
- route_stream_done(routes);
- } else {
- fprintf(stderr, "Couldn't allocate route stream.\n");
- }
- set_timeout(&ifp->update_timeout, ifp->update_interval);
- if(!prefix)
- ifp->last_update_time = now.tv_sec;
- else
- ifp->last_specific_update_time = now.tv_sec;
- } else {
- send_update(ifp, urgent, NULL, 0, zeroes, 0,
- cipher, clen); // standard_wildcard
- send_update(ifp, urgent, zeroes, 0, NULL, 0,
- cipher, clen); // specific wildcard
- }
- schedule_update_flush(ifp, urgent);
- }
- void
- send_update_resend(struct interface *ifp,
- const unsigned char *prefix, unsigned char plen,
- const unsigned char *src_prefix, unsigned char src_plen,
- const unsigned char *cipher, unsigned short clen)
- {
- assert(prefix != NULL);
- send_update(ifp, 1, prefix, plen, src_prefix, src_plen,
- cipher, clen);
- record_resend(RESEND_UPDATE, prefix, plen, src_prefix, src_plen,
- // -- lorauth --
- cipher, clen,
- // ----
- 0, NULL, NULL, resend_delay);
- }
- void
- send_wildcard_retraction(struct interface *ifp)
- {
- if(ifp == NULL) {
- struct interface *ifp_aux;
- FOR_ALL_INTERFACES(ifp_aux)
- send_wildcard_retraction(ifp_aux);
- return;
- }
- if(!if_up(ifp))
- return;
- start_message(ifp, MESSAGE_UPDATE, 10);
- accumulate_byte(ifp, 0);
- accumulate_byte(ifp, 0);
- accumulate_byte(ifp, 0);
- accumulate_byte(ifp, 0);
- accumulate_short(ifp, 0xFFFF);
- accumulate_short(ifp, myseqno);
- accumulate_short(ifp, 0xFFFF);
- end_message(ifp, MESSAGE_UPDATE, 10);
- ifp->have_buffered_id = 0;
- }
- void
- update_myseqno()
- {
- myseqno = seqno_plus(myseqno, 1);
- seqno_time = now;
- }
- void
- send_self_update(struct interface *ifp)
- {
- struct xroute_stream *xroutes;
- if(ifp == NULL) {
- struct interface *ifp_aux;
- FOR_ALL_INTERFACES(ifp_aux) {
- if(!if_up(ifp_aux))
- continue;
- send_self_update(ifp_aux);
- }
- return;
- }
- debugf("Sending self update to %s.\n", ifp->name);
- xroutes = xroute_stream();
- if(xroutes) {
- while(1) {
- struct xroute *xroute = xroute_stream_next(xroutes);
- if(xroute == NULL) break;
- send_update(ifp, 0, xroute->prefix, xroute->plen,
- xroute->src_prefix, xroute->src_plen,
- // -- lorauth --
- xroute->cipher, xroute->clen);
- }
- xroute_stream_done(xroutes);
- } else {
- fprintf(stderr, "Couldn't allocate xroute stream.\n");
- }
- }
- void
- send_ihu(struct neighbour *neigh, struct interface *ifp)
- {
- int rxcost, interval;
- int ll;
- int send_rtt_data;
- int msglen;
- if(neigh == NULL && ifp == NULL) {
- struct interface *ifp_aux;
- FOR_ALL_INTERFACES(ifp_aux) {
- if(if_up(ifp_aux))
- send_ihu(NULL, ifp_aux);
- }
- return;
- }
- if(neigh == NULL) {
- struct neighbour *ngh;
- FOR_ALL_NEIGHBOURS(ngh) {
- if(ngh->ifp == ifp)
- send_ihu(ngh, ifp);
- }
- return;
- }
- if(ifp && neigh->ifp != ifp)
- return;
- ifp = neigh->ifp;
- if(!if_up(ifp))
- return;
- rxcost = neighbour_rxcost(neigh);
- interval = (ifp->hello_interval * 3 + 9) / 10;
- /* Conceptually, an IHU is a unicast message. We usually send them as
- multicast, since this allows aggregation into a single packet and
- avoids an ARP exchange. If we already have a unicast message queued
- for this neighbour, however, we might as well piggyback the IHU. */
- debugf("Sending %sihu %d on %s to %s.\n",
- unicast_neighbour == neigh ? "unicast " : "",
- rxcost,
- neigh->ifp->name,
- format_address(neigh->address));
- ll = linklocal(neigh->address);
- if((ifp->flags & IF_TIMESTAMPS) && neigh->hello_send_us &&
- /* Checks whether the RTT data is not too old to be sent. */
- timeval_minus_msec(&now, &neigh->hello_rtt_receive_time) < 1000000) {
- send_rtt_data = 1;
- } else {
- neigh->hello_send_us = 0;
- send_rtt_data = 0;
- }
- /* The length depends on the format of the address, and then an
- optional 10-bytes sub-TLV for timestamps (used to compute a RTT). */
- msglen = (ll ? 14 : 22) + (send_rtt_data ? 10 : 0);
- if(unicast_neighbour != neigh) {
- start_message(ifp, MESSAGE_IHU, msglen);
- accumulate_byte(ifp, ll ? 3 : 2); // AE
- accumulate_byte(ifp, 0); // Reserved
- accumulate_short(ifp, rxcost); // Rxcost
- accumulate_short(ifp, interval); // Interval
- if(ll)
- accumulate_bytes(ifp, neigh->address + 8, 8);
- else
- accumulate_bytes(ifp, neigh->address, 16);
- if(send_rtt_data) {
- accumulate_byte(ifp, SUBTLV_TIMESTAMP);
- accumulate_byte(ifp, 8);
- accumulate_int(ifp, neigh->hello_send_us);
- accumulate_int(ifp, time_us(neigh->hello_rtt_receive_time));
- }
- end_message(ifp, MESSAGE_IHU, msglen);
- } else {
- int rc;
- rc = start_unicast_message(neigh, MESSAGE_IHU, msglen);
- if(rc < 0) return;
- accumulate_unicast_byte(neigh, ll ? 3 : 2);
- accumulate_unicast_byte(neigh, 0);
- accumulate_unicast_short(neigh, rxcost);
- accumulate_unicast_short(neigh, interval);
- if(ll)
- accumulate_unicast_bytes(neigh, neigh->address + 8, 8);
- else
- accumulate_unicast_bytes(neigh, neigh->address, 16);
- if(send_rtt_data) {
- accumulate_unicast_byte(neigh, SUBTLV_TIMESTAMP);
- accumulate_unicast_byte(neigh, 8);
- accumulate_unicast_int(neigh, neigh->hello_send_us);
- accumulate_unicast_int(neigh,
- time_us(neigh->hello_rtt_receive_time));
- }
- end_unicast_message(neigh, MESSAGE_IHU, msglen);
- }
- }
- /* Send IHUs to all marginal neighbours */
- void
- send_marginal_ihu(struct interface *ifp)
- {
- struct neighbour *neigh;
- FOR_ALL_NEIGHBOURS(neigh) {
- if(ifp && neigh->ifp != ifp)
- continue;
- if(neigh->txcost >= 384 || (neigh->reach & 0xF000) != 0xF000)
- send_ihu(neigh, ifp);
- }
- }
- /* Standard wildcard request with prefix == NULL && src_prefix == zeroes,
- Specific wildcard request with prefix == zeroes && src_prefix == NULL. */
- void
- send_request(struct interface *ifp,
- const unsigned char *prefix, unsigned char plen,
- const unsigned char *src_prefix, unsigned char src_plen)
- {
- int v4, pb, spb, len;
- if(ifp == NULL) {
- struct interface *ifp_auxn;
- FOR_ALL_INTERFACES(ifp_auxn) {
- if(if_up(ifp_auxn))
- continue;
- send_request(ifp_auxn, prefix, plen, src_prefix, src_plen);
- }
- return;
- }
- /* make sure any buffered updates go out before this request. */
- flushupdates(ifp);
- if(!if_up(ifp))
- return;
- if(prefix && src_prefix) {
- debugf("sending request to %s for %s from %s.\n", ifp->name,
- format_prefix(prefix, plen),
- format_prefix(src_prefix, src_plen));
- } else if(prefix) {
- debugf("sending request to %s for any specific.\n", ifp->name);
- start_message(ifp, MESSAGE_REQUEST_SRC_SPECIFIC, 3);
- accumulate_byte(ifp, 0);
- accumulate_byte(ifp, 0);
- accumulate_byte(ifp, 0);
- end_message(ifp, MESSAGE_REQUEST_SRC_SPECIFIC, 3);
- return;
- } else if(src_prefix) {
- debugf("sending request to %s for any.\n", ifp->name);
- start_message(ifp, MESSAGE_REQUEST, 2);
- accumulate_byte(ifp, 0);
- accumulate_byte(ifp, 0);
- end_message(ifp, MESSAGE_REQUEST, 2);
- return;
- } else {
- send_request(ifp, NULL, 0, zeroes, 0);
- send_request(ifp, zeroes, 0, NULL, 0);
- return;
- }
- v4 = plen >= 96 && v4mapped(prefix);
- pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8;
- len = 2 + pb;
- if(src_plen != 0) {
- spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8;
- len += spb + 1;
- start_message(ifp, MESSAGE_REQUEST_SRC_SPECIFIC, len);
- } else {
- spb = 0;
- start_message(ifp, MESSAGE_REQUEST, len);
- }
- accumulate_byte(ifp, v4 ? 1 : 2);
- accumulate_byte(ifp, v4 ? plen - 96 : plen);
- if(src_plen != 0)
- accumulate_byte(ifp, v4 ? src_plen - 96 : src_plen);
- if(v4)
- accumulate_bytes(ifp, prefix + 12, pb);
- else
- accumulate_bytes(ifp, prefix, pb);
- if(src_plen != 0) {
- if(v4)
- accumulate_bytes(ifp, src_prefix + 12, spb);
- else
- accumulate_bytes(ifp, src_prefix, spb);
- end_message(ifp, MESSAGE_REQUEST_SRC_SPECIFIC, len);
- } else {
- end_message(ifp, MESSAGE_REQUEST, len);
- }
- }
- void
- send_unicast_request(struct neighbour *neigh,
- const unsigned char *prefix, unsigned char plen,
- const unsigned char *src_prefix, unsigned char src_plen)
- {
- int rc, v4, pb, spb, len;
- /* make sure any buffered updates go out before this request. */
- flushupdates(neigh->ifp);
- if(prefix && src_prefix) {
- debugf("sending unicast request to %s for %s from %s.\n",
- format_address(neigh->address),
- format_prefix(prefix, plen),
- format_prefix(src_prefix, src_plen));
- } else if(prefix) {
- debugf("sending unicast request to %s for any specific.\n",
- format_address(neigh->address));
- rc = start_unicast_message(neigh, MESSAGE_REQUEST_SRC_SPECIFIC, 3);
- if(rc < 0) return;
- accumulate_unicast_byte(neigh, 0);
- accumulate_unicast_byte(neigh, 0);
- accumulate_unicast_byte(neigh, 0);
- end_unicast_message(neigh, MESSAGE_REQUEST_SRC_SPECIFIC, 3);
- return;
- } else if(src_prefix) {
- debugf("sending unicast request to %s for any.\n",
- format_address(neigh->address));
- rc = start_unicast_message(neigh, MESSAGE_REQUEST, 2);
- if(rc < 0) return;
- accumulate_unicast_byte(neigh, 0);
- accumulate_unicast_byte(neigh, 0);
- end_unicast_message(neigh, MESSAGE_REQUEST, 2);
- return;
- } else {
- send_unicast_request(neigh, NULL, 0, zeroes, 0);
- send_unicast_request(neigh, zeroes, 0, NULL, 0);
- return;
- }
- v4 = plen >= 96 && v4mapped(prefix);
- pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8;
- len = 2 + pb;
- if(src_plen != 0) {
- spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8;
- len += spb + 1;
- rc = start_unicast_message(neigh, MESSAGE_REQUEST_SRC_SPECIFIC, len);
- } else {
- spb = 0;
- rc = start_unicast_message(neigh, MESSAGE_REQUEST, len);
- }
- if(rc < 0) return;
- accumulate_unicast_byte(neigh, v4 ? 1 : 2);
- accumulate_unicast_byte(neigh, v4 ? plen - 96 : plen);
- if(src_plen != 0)
- accumulate_unicast_byte(neigh, v4 ? src_plen - 96 : src_plen);
- if(v4)
- accumulate_unicast_bytes(neigh, prefix + 12, pb);
- else
- accumulate_unicast_bytes(neigh, prefix, pb);
- if(src_plen != 0) {
- if(v4)
- accumulate_unicast_bytes(neigh, src_prefix + 12, spb);
- else
- accumulate_unicast_bytes(neigh, src_prefix, spb);
- end_unicast_message(neigh, MESSAGE_REQUEST_SRC_SPECIFIC, len);
- } else {
- end_unicast_message(neigh, MESSAGE_REQUEST, len);
- }
- }
- void
- send_multihop_request(struct interface *ifp,
- const unsigned char *prefix, unsigned char plen,
- const unsigned char *src_prefix, unsigned char src_plen,
- unsigned short seqno, const unsigned char *id,
- unsigned short hop_count)
- {
- int v4, pb, spb, len;
- /* Make sure any buffered updates go out before this request. */
- flushupdates(ifp);
- if(ifp == NULL) {
- struct interface *ifp_aux;
- FOR_ALL_INTERFACES(ifp_aux) {
- if(!if_up(ifp_aux))
- continue;
- send_multihop_request(ifp_aux, prefix, plen, src_prefix, src_plen,
- seqno, id, hop_count);
- }
- return;
- }
- if(!if_up(ifp))
- return;
- debugf("Sending request (%d) on %s for %s from %s.\n",
- hop_count, ifp->name, format_prefix(prefix, plen),
- format_prefix(src_prefix, src_plen));
- v4 = plen >= 96 && v4mapped(prefix);
- pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8;
- len = 6 + 8 + pb;
- if(src_plen != 0) {
- spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8;
- len += spb;
- start_message(ifp, MESSAGE_MH_REQUEST_SRC_SPECIFIC, len);
- } else {
- spb = 0;
- start_message(ifp, MESSAGE_MH_REQUEST, len);
- }
- accumulate_byte(ifp, v4 ? 1 : 2);
- accumulate_byte(ifp, v4 ? plen - 96 : plen);
- accumulate_short(ifp, seqno);
- accumulate_byte(ifp, hop_count);
- accumulate_byte(ifp, v4 ? src_plen - 96 : src_plen);
- accumulate_bytes(ifp, id, 8);
- if(prefix) {
- if(v4)
- accumulate_bytes(ifp, prefix + 12, pb);
- else
- accumulate_bytes(ifp, prefix, pb);
- }
- if(src_plen != 0) {
- if(v4)
- accumulate_bytes(ifp, src_prefix + 12, spb);
- else
- accumulate_bytes(ifp, src_prefix, spb);
- end_message(ifp, MESSAGE_MH_REQUEST_SRC_SPECIFIC, len);
- } else {
- end_message(ifp, MESSAGE_MH_REQUEST, len);
- }
- }
- void
- send_unicast_multihop_request(struct neighbour *neigh,
- const unsigned char *prefix, unsigned char plen,
- const unsigned char *src_prefix,
- unsigned char src_plen,
- unsigned short seqno, const unsigned char *id,
- unsigned short hop_count)
- {
- int rc, v4, pb, spb, len;
- /* Make sure any buffered updates go out before this request. */
- flushupdates(neigh->ifp);
- debugf("Sending multi-hop request to %s for %s from %s (%d hops).\n",
- format_address(neigh->address),
- format_prefix(prefix, plen),
- format_prefix(src_prefix, src_plen), hop_count);
- v4 = plen >= 96 && v4mapped(prefix);
- pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8;
- len = 6 + 8 + pb;
- if(src_plen != 0) {
- spb = v4 ? ((src_plen - 96) + 7) / 8 : (src_plen + 7) / 8;
- len += spb;
- rc = start_unicast_message(neigh, MESSAGE_MH_REQUEST_SRC_SPECIFIC, len);
- } else {
- spb = 0;
- rc = start_unicast_message(neigh, MESSAGE_MH_REQUEST, len);
- }
- if(rc < 0) return;
- accumulate_unicast_byte(neigh, v4 ? 1 : 2);
- accumulate_unicast_byte(neigh, v4 ? plen - 96 : plen);
- accumulate_unicast_short(neigh, seqno);
- accumulate_unicast_byte(neigh, hop_count);
- accumulate_unicast_byte(neigh, v4 ? src_plen - 96 : src_plen);
- accumulate_unicast_bytes(neigh, id, 8);
- if(prefix) {
- if(v4)
- accumulate_unicast_bytes(neigh, prefix + 12, pb);
- else
- accumulate_unicast_bytes(neigh, prefix, pb);
- }
- if(src_plen != 0) {
- if(v4)
- accumulate_unicast_bytes(neigh, src_prefix + 12, spb);
- else
- accumulate_unicast_bytes(neigh, src_prefix, spb);
- end_unicast_message(neigh, MESSAGE_MH_REQUEST_SRC_SPECIFIC, len);
- } else {
- end_unicast_message(neigh, MESSAGE_MH_REQUEST, len);
- }
- }
- void
- send_request_resend(struct neighbour *neigh,
- const unsigned char *prefix, unsigned char plen,
- const unsigned char *src_prefix, unsigned char src_plen,
- unsigned short seqno, unsigned char *id)
- {
- if(neigh)
- send_unicast_multihop_request(neigh, prefix, plen, src_prefix, src_plen,
- seqno, id, 127);
- else
- send_multihop_request(NULL, prefix, plen, src_prefix, src_plen,
- seqno, id, 127);
- record_resend(RESEND_REQUEST, prefix, plen, src_prefix, src_plen,
- // -- lorauth --
- NULL, 0,
- // ---
- seqno, id,
- neigh ? neigh->ifp : NULL, resend_delay);
- }
- void
- handle_request(struct neighbour *neigh, const unsigned char *prefix,
- unsigned char plen,
- const unsigned char *src_prefix, unsigned char src_plen,
- unsigned char hop_count,
- unsigned short seqno, const unsigned char *id)
- {
- struct xroute *xroute;
- struct babel_route *route;
- struct neighbour *successor = NULL;
- xroute = find_xroute(prefix, plen, src_prefix, src_plen);
- route = find_installed_route(prefix, plen, src_prefix, src_plen);
- if(xroute && (!route || xroute->metric <= kernel_metric)) {
- if(hop_count > 0 && memcmp(id, myid, 8) == 0) {
- if(seqno_compare(seqno, myseqno) > 0) {
- if(seqno_minus(seqno, myseqno) > 100) {
- /* Hopelessly out-of-date request */
- return;
- }
- update_myseqno();
- // -- lorauth --
- if(memcmp(id, myid, 8) == 0){
- /* since the seqno may have changed the lorauth cipher
- should be updated too.
- */
- if(route){
- if(lorauth_token(route->src->cipher, myid, myseqno) == -1)
- debugf("-- Error updating lorauth token: myid: %s, seqno: %d",
- format_eui64(myid), myseqno);
- }
- }
- // ----
- }
- }
- //send_update(neigh->ifp, 1, prefix, plen, src_prefix, src_plen);
- //send_update(neigh->ifp, 1, prefix, plen, src_prefix, src_plen, NULL, 0);
- // -- lorauth --
- if(route){
- /* send the update using cipher an clen found */
- send_update(neigh->ifp, 1, prefix, plen, src_prefix, src_plen,
- route->src->cipher, route->src->clen);
- }
- /* else */
- /* send_update(neigh->ifp, 1, prefix, plen, src_prefix, src_plen, NULL, 0); */
- // ----
- return;
- }
- if(route &&
- (memcmp(id, route->src->id, 8) != 0 ||
- seqno_compare(seqno, route->seqno) <= 0))
- {
- //send_update(neigh->ifp, 1, prefix, plen, src_prefix, src_plen);
- //send_update(neigh->ifp, 1, prefix, plen, src_prefix, src_plen, NULL, 0);
- send_update(neigh->ifp, 1, prefix, plen, src_prefix, src_plen,
- route->src->cipher, route->src->clen);
- return;
- }
- if(hop_count <= 1)
- return;
- if(route && memcmp(id, route->src->id, 8) == 0 &&
- seqno_minus(seqno, route->seqno) > 100) {
- /* Hopelessly out-of-date */
- return;
- }
- if(request_redundant(neigh->ifp, prefix, plen, src_prefix, src_plen,
- seqno, id))
- return;
- /* Let's try to forward this request. */
- if(route && route_metric(route) < INFINITY)
- successor = route->neigh;
- if(!successor || successor == neigh) {
- /* We were about to forward a request to its requestor. Try to
- find a different neighbour to forward the request to. */
- struct babel_route *other_route;
- other_route = find_best_route(prefix, plen, src_prefix, src_plen,
- 0, neigh);
- if(other_route && route_metric(other_route) < INFINITY)
- successor = other_route->neigh;
- }
- if(!successor || successor == neigh)
- /* Give up */
- return;
- send_unicast_multihop_request(successor, prefix, plen, src_prefix, src_plen,
- seqno, id, hop_count - 1);
- /* lorauth note: check here for clen and cipher */
- if(route)
- record_resend(RESEND_REQUEST, prefix, plen, src_prefix, src_plen,
- // -- lorauth --
- route->src->cipher, route->src->clen,
- // ----
- seqno, id,
- neigh->ifp, 0);
-
- record_resend(RESEND_REQUEST, prefix, plen, src_prefix, src_plen,
- // -- lorauth --
- NULL, 0,
- // ----
- seqno, id,
- neigh->ifp, 0);
- }
|