Annotation of embedaddon/quagga/babeld/message.c, revision 1.1
1.1 ! misho 1: /*
! 2: * This file is free software: you may copy, redistribute and/or modify it
! 3: * under the terms of the GNU General Public License as published by the
! 4: * Free Software Foundation, either version 2 of the License, or (at your
! 5: * option) any later version.
! 6: *
! 7: * This file is distributed in the hope that it will be useful, but
! 8: * WITHOUT ANY WARRANTY; without even the implied warranty of
! 9: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
! 10: * General Public License for more details.
! 11: *
! 12: * You should have received a copy of the GNU General Public License
! 13: * along with this program. If not, see <http://www.gnu.org/licenses/>.
! 14: *
! 15: * This file incorporates work covered by the following copyright and
! 16: * permission notice:
! 17: *
! 18:
! 19: Copyright (c) 2007, 2008 by Juliusz Chroboczek
! 20:
! 21: Permission is hereby granted, free of charge, to any person obtaining a copy
! 22: of this software and associated documentation files (the "Software"), to deal
! 23: in the Software without restriction, including without limitation the rights
! 24: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
! 25: copies of the Software, and to permit persons to whom the Software is
! 26: furnished to do so, subject to the following conditions:
! 27:
! 28: The above copyright notice and this permission notice shall be included in
! 29: all copies or substantial portions of the Software.
! 30:
! 31: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
! 32: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
! 33: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
! 34: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
! 35: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
! 36: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
! 37: THE SOFTWARE.
! 38: */
! 39:
! 40: #include <zebra.h>
! 41: #include "if.h"
! 42:
! 43: #include "babeld.h"
! 44: #include "util.h"
! 45: #include "net.h"
! 46: #include "babel_interface.h"
! 47: #include "source.h"
! 48: #include "neighbour.h"
! 49: #include "route.h"
! 50: #include "xroute.h"
! 51: #include "resend.h"
! 52: #include "message.h"
! 53: #include "kernel.h"
! 54:
! 55: unsigned char packet_header[4] = {42, 2};
! 56:
! 57: int split_horizon = 1;
! 58:
! 59: unsigned short myseqno = 0;
! 60: struct timeval seqno_time = {0, 0};
! 61:
! 62: #define UNICAST_BUFSIZE 1024
! 63: int unicast_buffered = 0;
! 64: unsigned char *unicast_buffer = NULL;
! 65: struct neighbour *unicast_neighbour = NULL;
! 66: struct timeval unicast_flush_timeout = {0, 0};
! 67:
! 68: static const unsigned char v4prefix[16] =
! 69: {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
! 70:
! 71: /* Parse a network prefix, encoded in the somewhat baroque compressed
! 72: representation used by Babel. Return the number of bytes parsed. */
! 73: static int
! 74: network_prefix(int ae, int plen, unsigned int omitted,
! 75: const unsigned char *p, const unsigned char *dp,
! 76: unsigned int len, unsigned char *p_r)
! 77: {
! 78: unsigned pb;
! 79: unsigned char prefix[16];
! 80: int ret = -1;
! 81:
! 82: if(plen >= 0)
! 83: pb = (plen + 7) / 8;
! 84: else if(ae == 1)
! 85: pb = 4;
! 86: else
! 87: pb = 16;
! 88:
! 89: if(pb > 16)
! 90: return -1;
! 91:
! 92: memset(prefix, 0, 16);
! 93:
! 94: switch(ae) {
! 95: case 0:
! 96: ret = 0;
! 97: break;
! 98: case 1:
! 99: if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted))
! 100: return -1;
! 101: memcpy(prefix, v4prefix, 12);
! 102: if(omitted) {
! 103: if (dp == NULL || !v4mapped(dp)) return -1;
! 104: memcpy(prefix, dp, 12 + omitted);
! 105: }
! 106: if(pb > omitted) memcpy(prefix + 12 + omitted, p, pb - omitted);
! 107: ret = pb - omitted;
! 108: break;
! 109: case 2:
! 110: if(omitted > 16 || (pb > omitted && len < pb - omitted)) return -1;
! 111: if(omitted) {
! 112: if (dp == NULL || v4mapped(dp)) return -1;
! 113: memcpy(prefix, dp, omitted);
! 114: }
! 115: if(pb > omitted) memcpy(prefix + omitted, p, pb - omitted);
! 116: ret = pb - omitted;
! 117: break;
! 118: case 3:
! 119: if(pb > 8 && len < pb - 8) return -1;
! 120: prefix[0] = 0xfe;
! 121: prefix[1] = 0x80;
! 122: if(pb > 8) memcpy(prefix + 8, p, pb - 8);
! 123: ret = pb - 8;
! 124: break;
! 125: default:
! 126: return -1;
! 127: }
! 128:
! 129: mask_prefix(p_r, prefix, plen < 0 ? 128 : ae == 1 ? plen + 96 : plen);
! 130: return ret;
! 131: }
! 132:
! 133: static void
! 134: parse_route_attributes(const unsigned char *a, int alen,
! 135: unsigned char *channels)
! 136: {
! 137: int type, len, i = 0;
! 138:
! 139: while(i < alen) {
! 140: type = a[i];
! 141: if(type == 0) {
! 142: i++;
! 143: continue;
! 144: }
! 145:
! 146: if(i + 1 > alen) {
! 147: fprintf(stderr, "Received truncated attributes.\n");
! 148: return;
! 149: }
! 150: len = a[i + 1];
! 151: if(i + len > alen) {
! 152: fprintf(stderr, "Received truncated attributes.\n");
! 153: return;
! 154: }
! 155:
! 156: if(type == 1) {
! 157: /* Nothing. */
! 158: } else if(type == 2) {
! 159: if(len > DIVERSITY_HOPS) {
! 160: fprintf(stderr,
! 161: "Received overlong channel information (%d > %d).\n",
! 162: len, DIVERSITY_HOPS);
! 163: len = DIVERSITY_HOPS;
! 164: }
! 165: if(memchr(a + i + 2, 0, len) != NULL) {
! 166: /* 0 is reserved. */
! 167: fprintf(stderr, "Channel information contains 0!");
! 168: return;
! 169: }
! 170: memset(channels, 0, DIVERSITY_HOPS);
! 171: memcpy(channels, a + i + 2, len);
! 172: } else {
! 173: fprintf(stderr, "Received unknown route attribute %d.\n", type);
! 174: }
! 175:
! 176: i += len + 2;
! 177: }
! 178: }
! 179:
! 180: static int
! 181: network_address(int ae, const unsigned char *a, unsigned int len,
! 182: unsigned char *a_r)
! 183: {
! 184: return network_prefix(ae, -1, 0, a, NULL, len, a_r);
! 185: }
! 186:
! 187: static int
! 188: channels_len(unsigned char *channels)
! 189: {
! 190: unsigned char *p = memchr(channels, 0, DIVERSITY_HOPS);
! 191: return p ? (p - channels) : DIVERSITY_HOPS;
! 192: }
! 193:
! 194: void
! 195: parse_packet(const unsigned char *from, struct interface *ifp,
! 196: const unsigned char *packet, int packetlen)
! 197: {
! 198: int i;
! 199: const unsigned char *message;
! 200: unsigned char type, len;
! 201: int bodylen;
! 202: struct neighbour *neigh;
! 203: int have_router_id = 0, have_v4_prefix = 0, have_v6_prefix = 0,
! 204: have_v4_nh = 0, have_v6_nh = 0;
! 205: unsigned char router_id[8], v4_prefix[16], v6_prefix[16],
! 206: v4_nh[16], v6_nh[16];
! 207:
! 208: if(!linklocal(from)) {
! 209: zlog_err("Received packet from non-local address %s.",
! 210: format_address(from));
! 211: return;
! 212: }
! 213:
! 214: if(packet[0] != 42) {
! 215: zlog_err("Received malformed packet on %s from %s.",
! 216: ifp->name, format_address(from));
! 217: return;
! 218: }
! 219:
! 220: if(packet[1] != 2) {
! 221: zlog_err("Received packet with unknown version %d on %s from %s.",
! 222: packet[1], ifp->name, format_address(from));
! 223: return;
! 224: }
! 225:
! 226: neigh = find_neighbour(from, ifp);
! 227: if(neigh == NULL) {
! 228: zlog_err("Couldn't allocate neighbour.");
! 229: return;
! 230: }
! 231:
! 232: DO_NTOHS(bodylen, packet + 2);
! 233:
! 234: if(bodylen + 4 > packetlen) {
! 235: zlog_err("Received truncated packet (%d + 4 > %d).",
! 236: bodylen, packetlen);
! 237: bodylen = packetlen - 4;
! 238: }
! 239:
! 240: i = 0;
! 241: while(i < bodylen) {
! 242: message = packet + 4 + i;
! 243: type = message[0];
! 244: if(type == MESSAGE_PAD1) {
! 245: debugf(BABEL_DEBUG_COMMON,"Received pad1 from %s on %s.",
! 246: format_address(from), ifp->name);
! 247: i++;
! 248: continue;
! 249: }
! 250: if(i + 1 > bodylen) {
! 251: zlog_err("Received truncated message.");
! 252: break;
! 253: }
! 254: len = message[1];
! 255: if(i + len > bodylen) {
! 256: zlog_err("Received truncated message.");
! 257: break;
! 258: }
! 259:
! 260: if(type == MESSAGE_PADN) {
! 261: debugf(BABEL_DEBUG_COMMON,"Received pad%d from %s on %s.",
! 262: len, format_address(from), ifp->name);
! 263: } else if(type == MESSAGE_ACK_REQ) {
! 264: unsigned short nonce, interval;
! 265: if(len < 6) goto fail;
! 266: DO_NTOHS(nonce, message + 4);
! 267: DO_NTOHS(interval, message + 6);
! 268: debugf(BABEL_DEBUG_COMMON,"Received ack-req (%04X %d) from %s on %s.",
! 269: nonce, interval, format_address(from), ifp->name);
! 270: send_ack(neigh, nonce, interval);
! 271: } else if(type == MESSAGE_ACK) {
! 272: debugf(BABEL_DEBUG_COMMON,"Received ack from %s on %s.",
! 273: format_address(from), ifp->name);
! 274: /* Nothing right now */
! 275: } else if(type == MESSAGE_HELLO) {
! 276: unsigned short seqno, interval;
! 277: int changed;
! 278: if(len < 6) goto fail;
! 279: DO_NTOHS(seqno, message + 4);
! 280: DO_NTOHS(interval, message + 6);
! 281: debugf(BABEL_DEBUG_COMMON,"Received hello %d (%d) from %s on %s.",
! 282: seqno, interval,
! 283: format_address(from), ifp->name);
! 284: changed = update_neighbour(neigh, seqno, interval);
! 285: update_neighbour_metric(neigh, changed);
! 286: if(interval > 0)
! 287: schedule_neighbours_check(interval * 10, 0);
! 288: } else if(type == MESSAGE_IHU) {
! 289: unsigned short txcost, interval;
! 290: unsigned char address[16];
! 291: int rc;
! 292: if(len < 6) goto fail;
! 293: DO_NTOHS(txcost, message + 4);
! 294: DO_NTOHS(interval, message + 6);
! 295: rc = network_address(message[2], message + 8, len - 6, address);
! 296: if(rc < 0) goto fail;
! 297: debugf(BABEL_DEBUG_COMMON,"Received ihu %d (%d) from %s on %s for %s.",
! 298: txcost, interval,
! 299: format_address(from), ifp->name,
! 300: format_address(address));
! 301: if(message[2] == 0 || is_interface_ll_address(ifp, address)) {
! 302: int changed = txcost != neigh->txcost;
! 303: neigh->txcost = txcost;
! 304: neigh->ihu_time = babel_now;
! 305: neigh->ihu_interval = interval;
! 306: update_neighbour_metric(neigh, changed);
! 307: if(interval > 0)
! 308: schedule_neighbours_check(interval * 10 * 3, 0);
! 309: }
! 310: } else if(type == MESSAGE_ROUTER_ID) {
! 311: if(len < 10) {
! 312: have_router_id = 0;
! 313: goto fail;
! 314: }
! 315: memcpy(router_id, message + 4, 8);
! 316: have_router_id = 1;
! 317: debugf(BABEL_DEBUG_COMMON,"Received router-id %s from %s on %s.",
! 318: format_eui64(router_id), format_address(from), ifp->name);
! 319: } else if(type == MESSAGE_NH) {
! 320: unsigned char nh[16];
! 321: int rc;
! 322: if(len < 2) {
! 323: have_v4_nh = 0;
! 324: have_v6_nh = 0;
! 325: goto fail;
! 326: }
! 327: rc = network_address(message[2], message + 4, len - 2,
! 328: nh);
! 329: if(rc < 0) {
! 330: have_v4_nh = 0;
! 331: have_v6_nh = 0;
! 332: goto fail;
! 333: }
! 334: debugf(BABEL_DEBUG_COMMON,"Received nh %s (%d) from %s on %s.",
! 335: format_address(nh), message[2],
! 336: format_address(from), ifp->name);
! 337: if(message[2] == 1) {
! 338: memcpy(v4_nh, nh, 16);
! 339: have_v4_nh = 1;
! 340: } else {
! 341: memcpy(v6_nh, nh, 16);
! 342: have_v6_nh = 1;
! 343: }
! 344: } else if(type == MESSAGE_UPDATE) {
! 345: unsigned char prefix[16], *nh;
! 346: unsigned char plen;
! 347: unsigned char channels[DIVERSITY_HOPS];
! 348: unsigned short interval, seqno, metric;
! 349: int rc, parsed_len;
! 350: if(len < 10) {
! 351: if(len < 2 || message[3] & 0x80)
! 352: have_v4_prefix = have_v6_prefix = 0;
! 353: goto fail;
! 354: }
! 355: DO_NTOHS(interval, message + 6);
! 356: DO_NTOHS(seqno, message + 8);
! 357: DO_NTOHS(metric, message + 10);
! 358: if(message[5] == 0 ||
! 359: (message[3] == 1 ? have_v4_prefix : have_v6_prefix))
! 360: rc = network_prefix(message[2], message[4], message[5],
! 361: message + 12,
! 362: message[2] == 1 ? v4_prefix : v6_prefix,
! 363: len - 10, prefix);
! 364: else
! 365: rc = -1;
! 366: if(rc < 0) {
! 367: if(message[3] & 0x80)
! 368: have_v4_prefix = have_v6_prefix = 0;
! 369: goto fail;
! 370: }
! 371: parsed_len = 10 + rc;
! 372:
! 373: plen = message[4] + (message[2] == 1 ? 96 : 0);
! 374:
! 375: if(message[3] & 0x80) {
! 376: if(message[2] == 1) {
! 377: memcpy(v4_prefix, prefix, 16);
! 378: have_v4_prefix = 1;
! 379: } else {
! 380: memcpy(v6_prefix, prefix, 16);
! 381: have_v6_prefix = 1;
! 382: }
! 383: }
! 384: if(message[3] & 0x40) {
! 385: if(message[2] == 1) {
! 386: memset(router_id, 0, 4);
! 387: memcpy(router_id + 4, prefix + 12, 4);
! 388: } else {
! 389: memcpy(router_id, prefix + 8, 8);
! 390: }
! 391: have_router_id = 1;
! 392: }
! 393: if(!have_router_id && message[2] != 0) {
! 394: zlog_err("Received prefix with no router id.");
! 395: goto fail;
! 396: }
! 397: debugf(BABEL_DEBUG_COMMON,"Received update%s%s for %s from %s on %s.",
! 398: (message[3] & 0x80) ? "/prefix" : "",
! 399: (message[3] & 0x40) ? "/id" : "",
! 400: format_prefix(prefix, plen),
! 401: format_address(from), ifp->name);
! 402:
! 403: if(message[2] == 0) {
! 404: if(metric < 0xFFFF) {
! 405: zlog_err("Received wildcard update with finite metric.");
! 406: goto done;
! 407: }
! 408: retract_neighbour_routes(neigh);
! 409: goto done;
! 410: } else if(message[2] == 1) {
! 411: if(!have_v4_nh)
! 412: goto fail;
! 413: nh = v4_nh;
! 414: } else if(have_v6_nh) {
! 415: nh = v6_nh;
! 416: } else {
! 417: nh = neigh->address;
! 418: }
! 419:
! 420: if(message[2] == 1) {
! 421: if(!babel_get_if_nfo(ifp)->ipv4)
! 422: goto done;
! 423: }
! 424:
! 425: if((ifp->flags & BABEL_IF_FARAWAY)) {
! 426: channels[0] = 0;
! 427: } else {
! 428: /* This will be overwritten by parse_route_attributes below. */
! 429: if(metric < 256) {
! 430: /* Assume non-interfering (wired) link. */
! 431: channels[0] = 0;
! 432: } else {
! 433: /* Assume interfering. */
! 434: channels[0] = BABEL_IF_CHANNEL_INTERFERING;
! 435: channels[1] = 0;
! 436: }
! 437:
! 438: if(parsed_len < len)
! 439: parse_route_attributes(message + 2 + parsed_len,
! 440: len - parsed_len, channels);
! 441: }
! 442:
! 443: update_route(router_id, prefix, plen, seqno, metric, interval,
! 444: neigh, nh,
! 445: channels, channels_len(channels));
! 446: } else if(type == MESSAGE_REQUEST) {
! 447: unsigned char prefix[16], plen;
! 448: int rc;
! 449: if(len < 2) goto fail;
! 450: rc = network_prefix(message[2], message[3], 0,
! 451: message + 4, NULL, len - 2, prefix);
! 452: if(rc < 0) goto fail;
! 453: plen = message[3] + (message[2] == 1 ? 96 : 0);
! 454: debugf(BABEL_DEBUG_COMMON,"Received request for %s from %s on %s.",
! 455: message[2] == 0 ? "any" : format_prefix(prefix, plen),
! 456: format_address(from), ifp->name);
! 457: if(message[2] == 0) {
! 458: struct babel_interface *babel_ifp =babel_get_if_nfo(neigh->ifp);
! 459: /* If a neighbour is requesting a full route dump from us,
! 460: we might as well send it an IHU. */
! 461: send_ihu(neigh, NULL);
! 462: /* Since nodes send wildcard requests on boot, booting
! 463: a large number of nodes at the same time may cause an
! 464: update storm. Ignore a wildcard request that happens
! 465: shortly after we sent a full update. */
! 466: if(babel_ifp->last_update_time <
! 467: (time_t)(babel_now.tv_sec -
! 468: MAX(babel_ifp->hello_interval / 100, 1)))
! 469: send_update(neigh->ifp, 0, NULL, 0);
! 470: } else {
! 471: send_update(neigh->ifp, 0, prefix, plen);
! 472: }
! 473: } else if(type == MESSAGE_MH_REQUEST) {
! 474: unsigned char prefix[16], plen;
! 475: unsigned short seqno;
! 476: int rc;
! 477: if(len < 14) goto fail;
! 478: DO_NTOHS(seqno, message + 4);
! 479: rc = network_prefix(message[2], message[3], 0,
! 480: message + 16, NULL, len - 14, prefix);
! 481: if(rc < 0) goto fail;
! 482: plen = message[3] + (message[2] == 1 ? 96 : 0);
! 483: debugf(BABEL_DEBUG_COMMON,"Received request (%d) for %s from %s on %s (%s, %d).",
! 484: message[6],
! 485: format_prefix(prefix, plen),
! 486: format_address(from), ifp->name,
! 487: format_eui64(message + 8), seqno);
! 488: handle_request(neigh, prefix, plen, message[6],
! 489: seqno, message + 8);
! 490: } else {
! 491: debugf(BABEL_DEBUG_COMMON,"Received unknown packet type %d from %s on %s.",
! 492: type, format_address(from), ifp->name);
! 493: }
! 494: done:
! 495: i += len + 2;
! 496: continue;
! 497:
! 498: fail:
! 499: zlog_err("Couldn't parse packet (%d, %d) from %s on %s.",
! 500: message[0], message[1], format_address(from), ifp->name);
! 501: goto done;
! 502: }
! 503: return;
! 504: }
! 505:
! 506: /* Under normal circumstances, there are enough moderation mechanisms
! 507: elsewhere in the protocol to make sure that this last-ditch check
! 508: should never trigger. But I'm superstitious. */
! 509:
! 510: static int
! 511: check_bucket(struct interface *ifp)
! 512: {
! 513: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 514: if(babel_ifp->bucket <= 0) {
! 515: int seconds = babel_now.tv_sec - babel_ifp->bucket_time;
! 516: if(seconds > 0) {
! 517: babel_ifp->bucket = MIN(BUCKET_TOKENS_MAX,
! 518: seconds * BUCKET_TOKENS_PER_SEC);
! 519: }
! 520: /* Reset bucket time unconditionally, in case clock is stepped. */
! 521: babel_ifp->bucket_time = babel_now.tv_sec;
! 522: }
! 523:
! 524: if(babel_ifp->bucket > 0) {
! 525: babel_ifp->bucket--;
! 526: return 1;
! 527: } else {
! 528: return 0;
! 529: }
! 530: }
! 531:
! 532: void
! 533: flushbuf(struct interface *ifp)
! 534: {
! 535: int rc;
! 536: struct sockaddr_in6 sin6;
! 537: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 538:
! 539: assert(babel_ifp->buffered <= babel_ifp->bufsize);
! 540:
! 541: flushupdates(ifp);
! 542:
! 543: if(babel_ifp->buffered > 0) {
! 544: debugf(BABEL_DEBUG_COMMON," (flushing %d buffered bytes on %s)",
! 545: babel_ifp->buffered, ifp->name);
! 546: if(check_bucket(ifp)) {
! 547: memset(&sin6, 0, sizeof(sin6));
! 548: sin6.sin6_family = AF_INET6;
! 549: memcpy(&sin6.sin6_addr, protocol_group, 16);
! 550: sin6.sin6_port = htons(protocol_port);
! 551: sin6.sin6_scope_id = ifp->ifindex;
! 552: DO_HTONS(packet_header + 2, babel_ifp->buffered);
! 553: rc = babel_send(protocol_socket,
! 554: packet_header, sizeof(packet_header),
! 555: babel_ifp->sendbuf, babel_ifp->buffered,
! 556: (struct sockaddr*)&sin6, sizeof(sin6));
! 557: if(rc < 0)
! 558: zlog_err("send: %s", safe_strerror(errno));
! 559: } else {
! 560: zlog_err("Warning: bucket full, dropping packet to %s.",
! 561: ifp->name);
! 562: }
! 563: }
! 564: VALGRIND_MAKE_MEM_UNDEFINED(babel_ifp->sendbuf, babel_ifp->bufsize);
! 565: babel_ifp->buffered = 0;
! 566: babel_ifp->have_buffered_hello = 0;
! 567: babel_ifp->have_buffered_id = 0;
! 568: babel_ifp->have_buffered_nh = 0;
! 569: babel_ifp->have_buffered_prefix = 0;
! 570: babel_ifp->flush_timeout.tv_sec = 0;
! 571: babel_ifp->flush_timeout.tv_usec = 0;
! 572: }
! 573:
! 574: static void
! 575: schedule_flush(struct interface *ifp)
! 576: {
! 577: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 578: unsigned msecs = jitter(babel_ifp, 0);
! 579: if(babel_ifp->flush_timeout.tv_sec != 0 &&
! 580: timeval_minus_msec(&babel_ifp->flush_timeout, &babel_now) < msecs)
! 581: return;
! 582: set_timeout(&babel_ifp->flush_timeout, msecs);
! 583: }
! 584:
! 585: static void
! 586: schedule_flush_now(struct interface *ifp)
! 587: {
! 588: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 589: /* Almost now */
! 590: unsigned msecs = roughly(10);
! 591: if(babel_ifp->flush_timeout.tv_sec != 0 &&
! 592: timeval_minus_msec(&babel_ifp->flush_timeout, &babel_now) < msecs)
! 593: return;
! 594: set_timeout(&babel_ifp->flush_timeout, msecs);
! 595: }
! 596:
! 597: static void
! 598: schedule_unicast_flush(unsigned msecs)
! 599: {
! 600: if(!unicast_neighbour)
! 601: return;
! 602: if(unicast_flush_timeout.tv_sec != 0 &&
! 603: timeval_minus_msec(&unicast_flush_timeout, &babel_now) < msecs)
! 604: return;
! 605: unicast_flush_timeout.tv_usec = (babel_now.tv_usec + msecs * 1000) %1000000;
! 606: unicast_flush_timeout.tv_sec =
! 607: babel_now.tv_sec + (babel_now.tv_usec / 1000 + msecs) / 1000;
! 608: }
! 609:
! 610: static void
! 611: ensure_space(struct interface *ifp, int space)
! 612: {
! 613: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 614: if(babel_ifp->bufsize - babel_ifp->buffered < space)
! 615: flushbuf(ifp);
! 616: }
! 617:
! 618: static void
! 619: start_message(struct interface *ifp, int type, int len)
! 620: {
! 621: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 622: if(babel_ifp->bufsize - babel_ifp->buffered < len + 2)
! 623: flushbuf(ifp);
! 624: babel_ifp->sendbuf[babel_ifp->buffered++] = type;
! 625: babel_ifp->sendbuf[babel_ifp->buffered++] = len;
! 626: }
! 627:
! 628: static void
! 629: end_message(struct interface *ifp, int type, int bytes)
! 630: {
! 631: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 632: assert(babel_ifp->buffered >= bytes + 2 &&
! 633: babel_ifp->sendbuf[babel_ifp->buffered - bytes - 2] == type &&
! 634: babel_ifp->sendbuf[babel_ifp->buffered - bytes - 1] == bytes);
! 635: schedule_flush(ifp);
! 636: }
! 637:
! 638: static void
! 639: accumulate_byte(struct interface *ifp, unsigned char value)
! 640: {
! 641: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 642: babel_ifp->sendbuf[babel_ifp->buffered++] = value;
! 643: }
! 644:
! 645: static void
! 646: accumulate_short(struct interface *ifp, unsigned short value)
! 647: {
! 648: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 649: DO_HTONS(babel_ifp->sendbuf + babel_ifp->buffered, value);
! 650: babel_ifp->buffered += 2;
! 651: }
! 652:
! 653: static void
! 654: accumulate_bytes(struct interface *ifp,
! 655: const unsigned char *value, unsigned len)
! 656: {
! 657: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 658: memcpy(babel_ifp->sendbuf + babel_ifp->buffered, value, len);
! 659: babel_ifp->buffered += len;
! 660: }
! 661:
! 662: static int
! 663: start_unicast_message(struct neighbour *neigh, int type, int len)
! 664: {
! 665: if(unicast_neighbour) {
! 666: if(neigh != unicast_neighbour ||
! 667: unicast_buffered + len + 2 >=
! 668: MIN(UNICAST_BUFSIZE, babel_get_if_nfo(neigh->ifp)->bufsize))
! 669: flush_unicast(0);
! 670: }
! 671: if(!unicast_buffer)
! 672: unicast_buffer = malloc(UNICAST_BUFSIZE);
! 673: if(!unicast_buffer) {
! 674: zlog_err("malloc(unicast_buffer): %s", safe_strerror(errno));
! 675: return -1;
! 676: }
! 677:
! 678: unicast_neighbour = neigh;
! 679:
! 680: unicast_buffer[unicast_buffered++] = type;
! 681: unicast_buffer[unicast_buffered++] = len;
! 682: return 1;
! 683: }
! 684:
! 685: static void
! 686: end_unicast_message(struct neighbour *neigh, int type, int bytes)
! 687: {
! 688: assert(unicast_neighbour == neigh && unicast_buffered >= bytes + 2 &&
! 689: unicast_buffer[unicast_buffered - bytes - 2] == type &&
! 690: unicast_buffer[unicast_buffered - bytes - 1] == bytes);
! 691: schedule_unicast_flush(jitter(babel_get_if_nfo(neigh->ifp), 0));
! 692: }
! 693:
! 694: static void
! 695: accumulate_unicast_byte(struct neighbour *neigh, unsigned char value)
! 696: {
! 697: unicast_buffer[unicast_buffered++] = value;
! 698: }
! 699:
! 700: static void
! 701: accumulate_unicast_short(struct neighbour *neigh, unsigned short value)
! 702: {
! 703: DO_HTONS(unicast_buffer + unicast_buffered, value);
! 704: unicast_buffered += 2;
! 705: }
! 706:
! 707: static void
! 708: accumulate_unicast_bytes(struct neighbour *neigh,
! 709: const unsigned char *value, unsigned len)
! 710: {
! 711: memcpy(unicast_buffer + unicast_buffered, value, len);
! 712: unicast_buffered += len;
! 713: }
! 714:
! 715: void
! 716: send_ack(struct neighbour *neigh, unsigned short nonce, unsigned short interval)
! 717: {
! 718: int rc;
! 719: debugf(BABEL_DEBUG_COMMON,"Sending ack (%04x) to %s on %s.",
! 720: nonce, format_address(neigh->address), neigh->ifp->name);
! 721: rc = start_unicast_message(neigh, MESSAGE_ACK, 2); if(rc < 0) return;
! 722: accumulate_unicast_short(neigh, nonce);
! 723: end_unicast_message(neigh, MESSAGE_ACK, 2);
! 724: /* Roughly yields a value no larger than 3/2, so this meets the deadline */
! 725: schedule_unicast_flush(roughly(interval * 6));
! 726: }
! 727:
! 728: void
! 729: send_hello_noupdate(struct interface *ifp, unsigned interval)
! 730: {
! 731: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 732: /* This avoids sending multiple hellos in a single packet, which breaks
! 733: link quality estimation. */
! 734: if(babel_ifp->have_buffered_hello)
! 735: flushbuf(ifp);
! 736:
! 737: babel_ifp->hello_seqno = seqno_plus(babel_ifp->hello_seqno, 1);
! 738: set_timeout(&babel_ifp->hello_timeout, babel_ifp->hello_interval);
! 739:
! 740: if(!if_up(ifp))
! 741: return;
! 742:
! 743: debugf(BABEL_DEBUG_COMMON,"Sending hello %d (%d) to %s.",
! 744: babel_ifp->hello_seqno, interval, ifp->name);
! 745:
! 746: start_message(ifp, MESSAGE_HELLO, 6);
! 747: accumulate_short(ifp, 0);
! 748: accumulate_short(ifp, babel_ifp->hello_seqno);
! 749: accumulate_short(ifp, interval > 0xFFFF ? 0xFFFF : interval);
! 750: end_message(ifp, MESSAGE_HELLO, 6);
! 751: babel_ifp->have_buffered_hello = 1;
! 752: }
! 753:
! 754: void
! 755: send_hello(struct interface *ifp)
! 756: {
! 757: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 758: send_hello_noupdate(ifp, (babel_ifp->hello_interval + 9) / 10);
! 759: /* Send full IHU every 3 hellos, and marginal IHU each time */
! 760: if(babel_ifp->hello_seqno % 3 == 0)
! 761: send_ihu(NULL, ifp);
! 762: else
! 763: send_marginal_ihu(ifp);
! 764: }
! 765:
! 766: void
! 767: flush_unicast(int dofree)
! 768: {
! 769: struct sockaddr_in6 sin6;
! 770: int rc;
! 771:
! 772: if(unicast_buffered == 0)
! 773: goto done;
! 774:
! 775: if(!if_up(unicast_neighbour->ifp))
! 776: goto done;
! 777:
! 778: /* Preserve ordering of messages */
! 779: flushbuf(unicast_neighbour->ifp);
! 780:
! 781: if(check_bucket(unicast_neighbour->ifp)) {
! 782: memset(&sin6, 0, sizeof(sin6));
! 783: sin6.sin6_family = AF_INET6;
! 784: memcpy(&sin6.sin6_addr, unicast_neighbour->address, 16);
! 785: sin6.sin6_port = htons(protocol_port);
! 786: sin6.sin6_scope_id = unicast_neighbour->ifp->ifindex;
! 787: DO_HTONS(packet_header + 2, unicast_buffered);
! 788: rc = babel_send(protocol_socket,
! 789: packet_header, sizeof(packet_header),
! 790: unicast_buffer, unicast_buffered,
! 791: (struct sockaddr*)&sin6, sizeof(sin6));
! 792: if(rc < 0)
! 793: zlog_err("send(unicast): %s", safe_strerror(errno));
! 794: } else {
! 795: zlog_err("Warning: bucket full, dropping unicast packet to %s if %s.",
! 796: format_address(unicast_neighbour->address),
! 797: unicast_neighbour->ifp->name);
! 798: }
! 799:
! 800: done:
! 801: VALGRIND_MAKE_MEM_UNDEFINED(unicast_buffer, UNICAST_BUFSIZE);
! 802: unicast_buffered = 0;
! 803: if(dofree && unicast_buffer) {
! 804: free(unicast_buffer);
! 805: unicast_buffer = NULL;
! 806: }
! 807: unicast_neighbour = NULL;
! 808: unicast_flush_timeout.tv_sec = 0;
! 809: unicast_flush_timeout.tv_usec = 0;
! 810: }
! 811:
! 812: static void
! 813: really_send_update(struct interface *ifp,
! 814: const unsigned char *id,
! 815: const unsigned char *prefix, unsigned char plen,
! 816: unsigned short seqno, unsigned short metric,
! 817: unsigned char *channels, int channels_len)
! 818: {
! 819: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 820: int add_metric, v4, real_plen, omit = 0;
! 821: const unsigned char *real_prefix;
! 822: unsigned short flags = 0;
! 823: int channels_size;
! 824:
! 825: if(diversity_kind != DIVERSITY_CHANNEL)
! 826: channels_len = -1;
! 827:
! 828: channels_size = channels_len >= 0 ? channels_len + 2 : 0;
! 829:
! 830: if(!if_up(ifp))
! 831: return;
! 832:
! 833: add_metric = output_filter(id, prefix, plen, ifp->ifindex);
! 834: if(add_metric >= INFINITY)
! 835: return;
! 836:
! 837: metric = MIN(metric + add_metric, INFINITY);
! 838: /* Worst case */
! 839: ensure_space(ifp, 20 + 12 + 28);
! 840:
! 841: v4 = plen >= 96 && v4mapped(prefix);
! 842:
! 843: if(v4) {
! 844: if(!babel_ifp->ipv4)
! 845: return;
! 846: if(!babel_ifp->have_buffered_nh ||
! 847: memcmp(babel_ifp->buffered_nh, babel_ifp->ipv4, 4) != 0) {
! 848: start_message(ifp, MESSAGE_NH, 6);
! 849: accumulate_byte(ifp, 1);
! 850: accumulate_byte(ifp, 0);
! 851: accumulate_bytes(ifp, babel_ifp->ipv4, 4);
! 852: end_message(ifp, MESSAGE_NH, 6);
! 853: memcpy(babel_ifp->buffered_nh, babel_ifp->ipv4, 4);
! 854: babel_ifp->have_buffered_nh = 1;
! 855: }
! 856:
! 857: real_prefix = prefix + 12;
! 858: real_plen = plen - 96;
! 859: } else {
! 860: if(babel_ifp->have_buffered_prefix) {
! 861: while(omit < plen / 8 &&
! 862: babel_ifp->buffered_prefix[omit] == prefix[omit])
! 863: omit++;
! 864: }
! 865: if(!babel_ifp->have_buffered_prefix || plen >= 48)
! 866: flags |= 0x80;
! 867: real_prefix = prefix;
! 868: real_plen = plen;
! 869: }
! 870:
! 871: if(!babel_ifp->have_buffered_id
! 872: || memcmp(id, babel_ifp->buffered_id, 8) != 0) {
! 873: if(real_plen == 128 && memcmp(real_prefix + 8, id, 8) == 0) {
! 874: flags |= 0x40;
! 875: } else {
! 876: start_message(ifp, MESSAGE_ROUTER_ID, 10);
! 877: accumulate_short(ifp, 0);
! 878: accumulate_bytes(ifp, id, 8);
! 879: end_message(ifp, MESSAGE_ROUTER_ID, 10);
! 880: }
! 881: memcpy(babel_ifp->buffered_id, id, 16);
! 882: babel_ifp->have_buffered_id = 1;
! 883: }
! 884:
! 885: start_message(ifp, MESSAGE_UPDATE, 10 + (real_plen + 7) / 8 - omit +
! 886: channels_size);
! 887: accumulate_byte(ifp, v4 ? 1 : 2);
! 888: accumulate_byte(ifp, flags);
! 889: accumulate_byte(ifp, real_plen);
! 890: accumulate_byte(ifp, omit);
! 891: accumulate_short(ifp, (babel_ifp->update_interval + 5) / 10);
! 892: accumulate_short(ifp, seqno);
! 893: accumulate_short(ifp, metric);
! 894: accumulate_bytes(ifp, real_prefix + omit, (real_plen + 7) / 8 - omit);
! 895: /* Note that an empty channels TLV is different from no such TLV. */
! 896: if(channels_len >= 0) {
! 897: accumulate_byte(ifp, 2);
! 898: accumulate_byte(ifp, channels_len);
! 899: accumulate_bytes(ifp, channels, channels_len);
! 900: }
! 901: end_message(ifp, MESSAGE_UPDATE, 10 + (real_plen + 7) / 8 - omit +
! 902: channels_size);
! 903:
! 904: if(flags & 0x80) {
! 905: memcpy(babel_ifp->buffered_prefix, prefix, 16);
! 906: babel_ifp->have_buffered_prefix = 1;
! 907: }
! 908: }
! 909:
! 910: static int
! 911: compare_buffered_updates(const void *av, const void *bv)
! 912: {
! 913: const struct buffered_update *a = av, *b = bv;
! 914: int rc, v4a, v4b, ma, mb;
! 915:
! 916: rc = memcmp(a->id, b->id, 8);
! 917: if(rc != 0)
! 918: return rc;
! 919:
! 920: v4a = (a->plen >= 96 && v4mapped(a->prefix));
! 921: v4b = (b->plen >= 96 && v4mapped(b->prefix));
! 922:
! 923: if(v4a > v4b)
! 924: return 1;
! 925: else if(v4a < v4b)
! 926: return -1;
! 927:
! 928: ma = (!v4a && a->plen == 128 && memcmp(a->prefix + 8, a->id, 8) == 0);
! 929: mb = (!v4b && b->plen == 128 && memcmp(b->prefix + 8, b->id, 8) == 0);
! 930:
! 931: if(ma > mb)
! 932: return -1;
! 933: else if(mb > ma)
! 934: return 1;
! 935:
! 936: if(a->plen < b->plen)
! 937: return 1;
! 938: else if(a->plen > b->plen)
! 939: return -1;
! 940:
! 941: return memcmp(a->prefix, b->prefix, 16);
! 942: }
! 943:
! 944: void
! 945: flushupdates(struct interface *ifp)
! 946: {
! 947: babel_interface_nfo *babel_ifp = NULL;
! 948: struct xroute *xroute;
! 949: struct babel_route *route;
! 950: const unsigned char *last_prefix = NULL;
! 951: unsigned char last_plen = 0xFF;
! 952: int i;
! 953:
! 954: if(ifp == NULL) {
! 955: struct interface *ifp_aux;
! 956: struct listnode *linklist_node = NULL;
! 957: FOR_ALL_INTERFACES(ifp_aux, linklist_node)
! 958: flushupdates(ifp_aux);
! 959: return;
! 960: }
! 961:
! 962: babel_ifp = babel_get_if_nfo(ifp);
! 963: if(babel_ifp->num_buffered_updates > 0) {
! 964: struct buffered_update *b = babel_ifp->buffered_updates;
! 965: int n = babel_ifp->num_buffered_updates;
! 966:
! 967: babel_ifp->buffered_updates = NULL;
! 968: babel_ifp->update_bufsize = 0;
! 969: babel_ifp->num_buffered_updates = 0;
! 970:
! 971: if(!if_up(ifp))
! 972: goto done;
! 973:
! 974: debugf(BABEL_DEBUG_COMMON," (flushing %d buffered updates on %s (%d))",
! 975: n, ifp->name, ifp->ifindex);
! 976:
! 977: /* In order to send fewer update messages, we want to send updates
! 978: with the same router-id together, with IPv6 going out before IPv4. */
! 979:
! 980: for(i = 0; i < n; i++) {
! 981: route = find_installed_route(b[i].prefix, b[i].plen);
! 982: if(route)
! 983: memcpy(b[i].id, route->src->id, 8);
! 984: else
! 985: memcpy(b[i].id, myid, 8);
! 986: }
! 987:
! 988: qsort(b, n, sizeof(struct buffered_update), compare_buffered_updates);
! 989:
! 990: for(i = 0; i < n; i++) {
! 991: /* The same update may be scheduled multiple times before it is
! 992: sent out. Since our buffer is now sorted, it is enough to
! 993: compare with the previous update. */
! 994:
! 995: if(last_prefix) {
! 996: if(b[i].plen == last_plen &&
! 997: memcmp(b[i].prefix, last_prefix, 16) == 0)
! 998: continue;
! 999: }
! 1000:
! 1001: xroute = find_xroute(b[i].prefix, b[i].plen);
! 1002: route = find_installed_route(b[i].prefix, b[i].plen);
! 1003:
! 1004: if(xroute && (!route || xroute->metric <= kernel_metric)) {
! 1005: really_send_update(ifp, myid,
! 1006: xroute->prefix, xroute->plen,
! 1007: myseqno, xroute->metric,
! 1008: NULL, 0);
! 1009: last_prefix = xroute->prefix;
! 1010: last_plen = xroute->plen;
! 1011: } else if(route) {
! 1012: unsigned char channels[DIVERSITY_HOPS];
! 1013: int chlen;
! 1014: struct interface *route_ifp = route->neigh->ifp;
! 1015: struct babel_interface *babel_route_ifp = NULL;
! 1016: unsigned short metric;
! 1017: unsigned short seqno;
! 1018:
! 1019: seqno = route->seqno;
! 1020: metric =
! 1021: route_interferes(route, ifp) ?
! 1022: route_metric(route) :
! 1023: route_metric_noninterfering(route);
! 1024:
! 1025: if(metric < INFINITY)
! 1026: satisfy_request(route->src->prefix, route->src->plen,
! 1027: seqno, route->src->id, ifp);
! 1028: if((babel_ifp->flags & BABEL_IF_SPLIT_HORIZON) &&
! 1029: route->neigh->ifp == ifp)
! 1030: continue;
! 1031:
! 1032: babel_route_ifp = babel_get_if_nfo(route_ifp);
! 1033: if(babel_route_ifp->channel ==BABEL_IF_CHANNEL_NONINTERFERING) {
! 1034: memcpy(channels, route->channels, DIVERSITY_HOPS);
! 1035: } else {
! 1036: if(babel_route_ifp->channel == BABEL_IF_CHANNEL_UNKNOWN)
! 1037: channels[0] = BABEL_IF_CHANNEL_INTERFERING;
! 1038: else {
! 1039: assert(babel_route_ifp->channel > 0 &&
! 1040: babel_route_ifp->channel <= 255);
! 1041: channels[0] = babel_route_ifp->channel;
! 1042: }
! 1043: memcpy(channels + 1, route->channels, DIVERSITY_HOPS - 1);
! 1044: }
! 1045:
! 1046: chlen = channels_len(channels);
! 1047: really_send_update(ifp, route->src->id,
! 1048: route->src->prefix,
! 1049: route->src->plen,
! 1050: seqno, metric,
! 1051: channels, chlen);
! 1052: update_source(route->src, seqno, metric);
! 1053: last_prefix = route->src->prefix;
! 1054: last_plen = route->src->plen;
! 1055: } else {
! 1056: /* There's no route for this prefix. This can happen shortly
! 1057: after an xroute has been retracted, so send a retraction. */
! 1058: really_send_update(ifp, myid, b[i].prefix, b[i].plen,
! 1059: myseqno, INFINITY, NULL, -1);
! 1060: }
! 1061: }
! 1062: schedule_flush_now(ifp);
! 1063: done:
! 1064: free(b);
! 1065: }
! 1066: babel_ifp->update_flush_timeout.tv_sec = 0;
! 1067: babel_ifp->update_flush_timeout.tv_usec = 0;
! 1068: }
! 1069:
! 1070: static void
! 1071: schedule_update_flush(struct interface *ifp, int urgent)
! 1072: {
! 1073: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 1074: unsigned msecs;
! 1075: msecs = update_jitter(babel_ifp, urgent);
! 1076: if(babel_ifp->update_flush_timeout.tv_sec != 0 &&
! 1077: timeval_minus_msec(&babel_ifp->update_flush_timeout, &babel_now) < msecs)
! 1078: return;
! 1079: set_timeout(&babel_ifp->update_flush_timeout, msecs);
! 1080: }
! 1081:
! 1082: static void
! 1083: buffer_update(struct interface *ifp,
! 1084: const unsigned char *prefix, unsigned char plen)
! 1085: {
! 1086: babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
! 1087: if(babel_ifp->num_buffered_updates > 0 &&
! 1088: babel_ifp->num_buffered_updates >= babel_ifp->update_bufsize)
! 1089: flushupdates(ifp);
! 1090:
! 1091: if(babel_ifp->update_bufsize == 0) {
! 1092: int n;
! 1093: assert(babel_ifp->buffered_updates == NULL);
! 1094: /* Allocate enough space to hold a full update. Since the
! 1095: number of installed routes will grow over time, make sure we
! 1096: have enough space to send a full-ish frame. */
! 1097: n = installed_routes_estimate() + xroutes_estimate() + 4;
! 1098: n = MAX(n, babel_ifp->bufsize / 16);
! 1099: again:
! 1100: babel_ifp->buffered_updates = malloc(n *sizeof(struct buffered_update));
! 1101: if(babel_ifp->buffered_updates == NULL) {
! 1102: zlog_err("malloc(buffered_updates): %s", safe_strerror(errno));
! 1103: if(n > 4) {
! 1104: /* Try again with a tiny buffer. */
! 1105: n = 4;
! 1106: goto again;
! 1107: }
! 1108: return;
! 1109: }
! 1110: babel_ifp->update_bufsize = n;
! 1111: babel_ifp->num_buffered_updates = 0;
! 1112: }
! 1113:
! 1114: memcpy(babel_ifp->buffered_updates[babel_ifp->num_buffered_updates].prefix,
! 1115: prefix, 16);
! 1116: babel_ifp->buffered_updates[babel_ifp->num_buffered_updates].plen = plen;
! 1117: babel_ifp->num_buffered_updates++;
! 1118: }
! 1119:
! 1120: static void
! 1121: buffer_update_callback(struct babel_route *route, void *closure)
! 1122: {
! 1123: buffer_update((struct interface*)closure,
! 1124: route->src->prefix, route->src->plen);
! 1125: }
! 1126:
! 1127: void
! 1128: send_update(struct interface *ifp, int urgent,
! 1129: const unsigned char *prefix, unsigned char plen)
! 1130: {
! 1131: babel_interface_nfo *babel_ifp = NULL;
! 1132:
! 1133: if(ifp == NULL) {
! 1134: struct interface *ifp_aux;
! 1135: struct listnode *linklist_node = NULL;
! 1136: struct babel_route *route;
! 1137: FOR_ALL_INTERFACES(ifp_aux, linklist_node)
! 1138: send_update(ifp_aux, urgent, prefix, plen);
! 1139: if(prefix) {
! 1140: /* Since flushupdates only deals with non-wildcard interfaces, we
! 1141: need to do this now. */
! 1142: route = find_installed_route(prefix, plen);
! 1143: if(route && route_metric(route) < INFINITY)
! 1144: satisfy_request(prefix, plen, route->src->seqno, route->src->id,
! 1145: NULL);
! 1146: }
! 1147: return;
! 1148: }
! 1149:
! 1150: if(!if_up(ifp))
! 1151: return;
! 1152:
! 1153: babel_ifp = babel_get_if_nfo(ifp);
! 1154: if(prefix) {
! 1155: debugf(BABEL_DEBUG_COMMON,"Sending update to %s for %s.",
! 1156: ifp->name, format_prefix(prefix, plen));
! 1157: buffer_update(ifp, prefix, plen);
! 1158: } else {
! 1159: send_self_update(ifp);
! 1160: debugf(BABEL_DEBUG_COMMON,"Sending update to %s for any.", ifp->name);
! 1161: for_all_installed_routes(buffer_update_callback, ifp);
! 1162: set_timeout(&babel_ifp->update_timeout, babel_ifp->update_interval);
! 1163: babel_ifp->last_update_time = babel_now.tv_sec;
! 1164: }
! 1165: schedule_update_flush(ifp, urgent);
! 1166: }
! 1167:
! 1168: void
! 1169: send_update_resend(struct interface *ifp,
! 1170: const unsigned char *prefix, unsigned char plen)
! 1171: {
! 1172: assert(prefix != NULL);
! 1173:
! 1174: send_update(ifp, 1, prefix, plen);
! 1175: record_resend(RESEND_UPDATE, prefix, plen, 0, 0, NULL, resend_delay);
! 1176: }
! 1177:
! 1178: void
! 1179: send_wildcard_retraction(struct interface *ifp)
! 1180: {
! 1181: babel_interface_nfo *babel_ifp = NULL;
! 1182: if(ifp == NULL) {
! 1183: struct interface *ifp_aux;
! 1184: struct listnode *linklist_node = NULL;
! 1185: FOR_ALL_INTERFACES(ifp_aux, linklist_node)
! 1186: send_wildcard_retraction(ifp_aux);
! 1187: return;
! 1188: }
! 1189:
! 1190: if(!if_up(ifp))
! 1191: return;
! 1192:
! 1193: babel_ifp = babel_get_if_nfo(ifp);
! 1194: start_message(ifp, MESSAGE_UPDATE, 10);
! 1195: accumulate_byte(ifp, 0);
! 1196: accumulate_byte(ifp, 0x40);
! 1197: accumulate_byte(ifp, 0);
! 1198: accumulate_byte(ifp, 0);
! 1199: accumulate_short(ifp, 0xFFFF);
! 1200: accumulate_short(ifp, myseqno);
! 1201: accumulate_short(ifp, 0xFFFF);
! 1202: end_message(ifp, MESSAGE_UPDATE, 10);
! 1203:
! 1204: babel_ifp->have_buffered_id = 0;
! 1205: }
! 1206:
! 1207: void
! 1208: update_myseqno()
! 1209: {
! 1210: myseqno = seqno_plus(myseqno, 1);
! 1211: seqno_time = babel_now;
! 1212: }
! 1213:
! 1214: static void
! 1215: send_xroute_update_callback(struct xroute *xroute, void *closure)
! 1216: {
! 1217: struct interface *ifp = (struct interface*)closure;
! 1218: send_update(ifp, 0, xroute->prefix, xroute->plen);
! 1219: }
! 1220:
! 1221: void
! 1222: send_self_update(struct interface *ifp)
! 1223: {
! 1224: if(ifp == NULL) {
! 1225: struct interface *ifp_aux;
! 1226: struct listnode *linklist_node = NULL;
! 1227: FOR_ALL_INTERFACES(ifp_aux, linklist_node) {
! 1228: if(!if_up(ifp_aux))
! 1229: continue;
! 1230: send_self_update(ifp_aux);
! 1231: }
! 1232: return;
! 1233: }
! 1234:
! 1235: debugf(BABEL_DEBUG_COMMON,"Sending self update to %s.", ifp->name);
! 1236: for_all_xroutes(send_xroute_update_callback, ifp);
! 1237: }
! 1238:
! 1239: void
! 1240: send_ihu(struct neighbour *neigh, struct interface *ifp)
! 1241: {
! 1242: babel_interface_nfo *babel_ifp = NULL;
! 1243: int rxcost, interval;
! 1244: int ll;
! 1245:
! 1246: if(neigh == NULL && ifp == NULL) {
! 1247: struct interface *ifp_aux;
! 1248: struct listnode *linklist_node = NULL;
! 1249: FOR_ALL_INTERFACES(ifp_aux, linklist_node) {
! 1250: if(if_up(ifp_aux))
! 1251: continue;
! 1252: send_ihu(NULL, ifp_aux);
! 1253: }
! 1254: return;
! 1255: }
! 1256:
! 1257: if(neigh == NULL) {
! 1258: struct neighbour *ngh;
! 1259: FOR_ALL_NEIGHBOURS(ngh) {
! 1260: if(ngh->ifp == ifp)
! 1261: send_ihu(ngh, ifp);
! 1262: }
! 1263: return;
! 1264: }
! 1265:
! 1266:
! 1267: if(ifp && neigh->ifp != ifp)
! 1268: return;
! 1269:
! 1270: ifp = neigh->ifp;
! 1271: babel_ifp = babel_get_if_nfo(ifp);
! 1272: if(!if_up(ifp))
! 1273: return;
! 1274:
! 1275: rxcost = neighbour_rxcost(neigh);
! 1276: interval = (babel_ifp->hello_interval * 3 + 9) / 10;
! 1277:
! 1278: /* Conceptually, an IHU is a unicast message. We usually send them as
! 1279: multicast, since this allows aggregation into a single packet and
! 1280: avoids an ARP exchange. If we already have a unicast message queued
! 1281: for this neighbour, however, we might as well piggyback the IHU. */
! 1282: debugf(BABEL_DEBUG_COMMON,"Sending %sihu %d on %s to %s.",
! 1283: unicast_neighbour == neigh ? "unicast " : "",
! 1284: rxcost,
! 1285: neigh->ifp->name,
! 1286: format_address(neigh->address));
! 1287:
! 1288: ll = linklocal(neigh->address);
! 1289:
! 1290: if(unicast_neighbour != neigh) {
! 1291: start_message(ifp, MESSAGE_IHU, ll ? 14 : 22);
! 1292: accumulate_byte(ifp, ll ? 3 : 2);
! 1293: accumulate_byte(ifp, 0);
! 1294: accumulate_short(ifp, rxcost);
! 1295: accumulate_short(ifp, interval);
! 1296: if(ll)
! 1297: accumulate_bytes(ifp, neigh->address + 8, 8);
! 1298: else
! 1299: accumulate_bytes(ifp, neigh->address, 16);
! 1300: end_message(ifp, MESSAGE_IHU, ll ? 14 : 22);
! 1301: } else {
! 1302: int rc;
! 1303: rc = start_unicast_message(neigh, MESSAGE_IHU, ll ? 14 : 22);
! 1304: if(rc < 0) return;
! 1305: accumulate_unicast_byte(neigh, ll ? 3 : 2);
! 1306: accumulate_unicast_byte(neigh, 0);
! 1307: accumulate_unicast_short(neigh, rxcost);
! 1308: accumulate_unicast_short(neigh, interval);
! 1309: if(ll)
! 1310: accumulate_unicast_bytes(neigh, neigh->address + 8, 8);
! 1311: else
! 1312: accumulate_unicast_bytes(neigh, neigh->address, 16);
! 1313: end_unicast_message(neigh, MESSAGE_IHU, ll ? 14 : 22);
! 1314: }
! 1315: }
! 1316:
! 1317: /* Send IHUs to all marginal neighbours */
! 1318: void
! 1319: send_marginal_ihu(struct interface *ifp)
! 1320: {
! 1321: struct neighbour *neigh;
! 1322: FOR_ALL_NEIGHBOURS(neigh) {
! 1323: if(ifp && neigh->ifp != ifp)
! 1324: continue;
! 1325: if(neigh->txcost >= 384 || (neigh->reach & 0xF000) != 0xF000)
! 1326: send_ihu(neigh, ifp);
! 1327: }
! 1328: }
! 1329:
! 1330: void
! 1331: send_request(struct interface *ifp,
! 1332: const unsigned char *prefix, unsigned char plen)
! 1333: {
! 1334: int v4, len;
! 1335:
! 1336: if(ifp == NULL) {
! 1337: struct interface *ifp_aux;
! 1338: struct listnode *linklist_node = NULL;
! 1339: FOR_ALL_INTERFACES(ifp_aux, linklist_node) {
! 1340: if(if_up(ifp_aux))
! 1341: continue;
! 1342: send_request(ifp_aux, prefix, plen);
! 1343: }
! 1344: return;
! 1345: }
! 1346:
! 1347: /* make sure any buffered updates go out before this request. */
! 1348: flushupdates(ifp);
! 1349:
! 1350: if(!if_up(ifp))
! 1351: return;
! 1352:
! 1353: debugf(BABEL_DEBUG_COMMON,"sending request to %s for %s.",
! 1354: ifp->name, prefix ? format_prefix(prefix, plen) : "any");
! 1355: v4 = plen >= 96 && v4mapped(prefix);
! 1356: len = !prefix ? 2 : v4 ? 6 : 18;
! 1357:
! 1358: start_message(ifp, MESSAGE_REQUEST, len);
! 1359: accumulate_byte(ifp, !prefix ? 0 : v4 ? 1 : 2);
! 1360: accumulate_byte(ifp, !prefix ? 0 : v4 ? plen - 96 : plen);
! 1361: if(prefix) {
! 1362: if(v4)
! 1363: accumulate_bytes(ifp, prefix + 12, 4);
! 1364: else
! 1365: accumulate_bytes(ifp, prefix, 16);
! 1366: }
! 1367: end_message(ifp, MESSAGE_REQUEST, len);
! 1368: }
! 1369:
! 1370: void
! 1371: send_unicast_request(struct neighbour *neigh,
! 1372: const unsigned char *prefix, unsigned char plen)
! 1373: {
! 1374: int rc, v4, len;
! 1375:
! 1376: /* make sure any buffered updates go out before this request. */
! 1377: flushupdates(neigh->ifp);
! 1378:
! 1379: debugf(BABEL_DEBUG_COMMON,"sending unicast request to %s for %s.",
! 1380: format_address(neigh->address),
! 1381: prefix ? format_prefix(prefix, plen) : "any");
! 1382: v4 = plen >= 96 && v4mapped(prefix);
! 1383: len = !prefix ? 2 : v4 ? 6 : 18;
! 1384:
! 1385: rc = start_unicast_message(neigh, MESSAGE_REQUEST, len);
! 1386: if(rc < 0) return;
! 1387: accumulate_unicast_byte(neigh, !prefix ? 0 : v4 ? 1 : 2);
! 1388: accumulate_unicast_byte(neigh, !prefix ? 0 : v4 ? plen - 96 : plen);
! 1389: if(prefix) {
! 1390: if(v4)
! 1391: accumulate_unicast_bytes(neigh, prefix + 12, 4);
! 1392: else
! 1393: accumulate_unicast_bytes(neigh, prefix, 16);
! 1394: }
! 1395: end_unicast_message(neigh, MESSAGE_REQUEST, len);
! 1396: }
! 1397:
! 1398: void
! 1399: send_multihop_request(struct interface *ifp,
! 1400: const unsigned char *prefix, unsigned char plen,
! 1401: unsigned short seqno, const unsigned char *id,
! 1402: unsigned short hop_count)
! 1403: {
! 1404: int v4, pb, len;
! 1405:
! 1406: /* Make sure any buffered updates go out before this request. */
! 1407: flushupdates(ifp);
! 1408:
! 1409: if(ifp == NULL) {
! 1410: struct interface *ifp_aux;
! 1411: struct listnode *linklist_node = NULL;
! 1412: FOR_ALL_INTERFACES(ifp_aux, linklist_node) {
! 1413: if(!if_up(ifp_aux))
! 1414: continue;
! 1415: send_multihop_request(ifp_aux, prefix, plen, seqno, id, hop_count);
! 1416: }
! 1417: return;
! 1418: }
! 1419:
! 1420: if(!if_up(ifp))
! 1421: return;
! 1422:
! 1423: debugf(BABEL_DEBUG_COMMON,"Sending request (%d) on %s for %s.",
! 1424: hop_count, ifp->name, format_prefix(prefix, plen));
! 1425: v4 = plen >= 96 && v4mapped(prefix);
! 1426: pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8;
! 1427: len = 6 + 8 + pb;
! 1428:
! 1429: start_message(ifp, MESSAGE_MH_REQUEST, len);
! 1430: accumulate_byte(ifp, v4 ? 1 : 2);
! 1431: accumulate_byte(ifp, v4 ? plen - 96 : plen);
! 1432: accumulate_short(ifp, seqno);
! 1433: accumulate_byte(ifp, hop_count);
! 1434: accumulate_byte(ifp, 0);
! 1435: accumulate_bytes(ifp, id, 8);
! 1436: if(prefix) {
! 1437: if(v4)
! 1438: accumulate_bytes(ifp, prefix + 12, pb);
! 1439: else
! 1440: accumulate_bytes(ifp, prefix, pb);
! 1441: }
! 1442: end_message(ifp, MESSAGE_MH_REQUEST, len);
! 1443: }
! 1444:
! 1445: void
! 1446: send_unicast_multihop_request(struct neighbour *neigh,
! 1447: const unsigned char *prefix, unsigned char plen,
! 1448: unsigned short seqno, const unsigned char *id,
! 1449: unsigned short hop_count)
! 1450: {
! 1451: int rc, v4, pb, len;
! 1452:
! 1453: /* Make sure any buffered updates go out before this request. */
! 1454: flushupdates(neigh->ifp);
! 1455:
! 1456: debugf(BABEL_DEBUG_COMMON,"Sending multi-hop request to %s for %s (%d hops).",
! 1457: format_address(neigh->address),
! 1458: format_prefix(prefix, plen), hop_count);
! 1459: v4 = plen >= 96 && v4mapped(prefix);
! 1460: pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8;
! 1461: len = 6 + 8 + pb;
! 1462:
! 1463: rc = start_unicast_message(neigh, MESSAGE_MH_REQUEST, len);
! 1464: if(rc < 0) return;
! 1465: accumulate_unicast_byte(neigh, v4 ? 1 : 2);
! 1466: accumulate_unicast_byte(neigh, v4 ? plen - 96 : plen);
! 1467: accumulate_unicast_short(neigh, seqno);
! 1468: accumulate_unicast_byte(neigh, hop_count);
! 1469: accumulate_unicast_byte(neigh, 0);
! 1470: accumulate_unicast_bytes(neigh, id, 8);
! 1471: if(prefix) {
! 1472: if(v4)
! 1473: accumulate_unicast_bytes(neigh, prefix + 12, pb);
! 1474: else
! 1475: accumulate_unicast_bytes(neigh, prefix, pb);
! 1476: }
! 1477: end_unicast_message(neigh, MESSAGE_MH_REQUEST, len);
! 1478: }
! 1479:
! 1480: void
! 1481: send_request_resend(struct neighbour *neigh,
! 1482: const unsigned char *prefix, unsigned char plen,
! 1483: unsigned short seqno, unsigned char *id)
! 1484: {
! 1485: if(neigh)
! 1486: send_unicast_multihop_request(neigh, prefix, plen, seqno, id, 127);
! 1487: else
! 1488: send_multihop_request(NULL, prefix, plen, seqno, id, 127);
! 1489:
! 1490: record_resend(RESEND_REQUEST, prefix, plen, seqno, id,
! 1491: neigh ? neigh->ifp : NULL, resend_delay);
! 1492: }
! 1493:
! 1494: void
! 1495: handle_request(struct neighbour *neigh, const unsigned char *prefix,
! 1496: unsigned char plen, unsigned char hop_count,
! 1497: unsigned short seqno, const unsigned char *id)
! 1498: {
! 1499: struct xroute *xroute;
! 1500: struct babel_route *route;
! 1501: struct neighbour *successor = NULL;
! 1502:
! 1503: xroute = find_xroute(prefix, plen);
! 1504: route = find_installed_route(prefix, plen);
! 1505:
! 1506: if(xroute && (!route || xroute->metric <= kernel_metric)) {
! 1507: if(hop_count > 0 && memcmp(id, myid, 8) == 0) {
! 1508: if(seqno_compare(seqno, myseqno) > 0) {
! 1509: if(seqno_minus(seqno, myseqno) > 100) {
! 1510: /* Hopelessly out-of-date request */
! 1511: return;
! 1512: }
! 1513: update_myseqno();
! 1514: }
! 1515: }
! 1516: send_update(neigh->ifp, 1, prefix, plen);
! 1517: return;
! 1518: }
! 1519:
! 1520: if(route &&
! 1521: (memcmp(id, route->src->id, 8) != 0 ||
! 1522: seqno_compare(seqno, route->seqno) <= 0)) {
! 1523: send_update(neigh->ifp, 1, prefix, plen);
! 1524: return;
! 1525: }
! 1526:
! 1527: if(hop_count <= 1)
! 1528: return;
! 1529:
! 1530: if(route && memcmp(id, route->src->id, 8) == 0 &&
! 1531: seqno_minus(seqno, route->seqno) > 100) {
! 1532: /* Hopelessly out-of-date */
! 1533: return;
! 1534: }
! 1535:
! 1536: if(request_redundant(neigh->ifp, prefix, plen, seqno, id))
! 1537: return;
! 1538:
! 1539: /* Let's try to forward this request. */
! 1540: if(route && route_metric(route) < INFINITY)
! 1541: successor = route->neigh;
! 1542:
! 1543: if(!successor || successor == neigh) {
! 1544: /* We were about to forward a request to its requestor. Try to
! 1545: find a different neighbour to forward the request to. */
! 1546: struct babel_route *other_route;
! 1547:
! 1548: other_route = find_best_route(prefix, plen, 0, neigh);
! 1549: if(other_route && route_metric(other_route) < INFINITY)
! 1550: successor = other_route->neigh;
! 1551: }
! 1552:
! 1553: if(!successor || successor == neigh)
! 1554: /* Give up */
! 1555: return;
! 1556:
! 1557: send_unicast_multihop_request(successor, prefix, plen, seqno, id,
! 1558: hop_count - 1);
! 1559: record_resend(RESEND_REQUEST, prefix, plen, seqno, id,
! 1560: neigh->ifp, 0);
! 1561: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>