Annotation of embedaddon/bird/proto/ospf/hello.c, revision 1.1
1.1 ! misho 1: /*
! 2: * BIRD -- OSPF
! 3: *
! 4: * (c) 1999--2004 Ondrej Filip <feela@network.cz>
! 5: * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
! 6: * (c) 2009--2014 CZ.NIC z.s.p.o.
! 7: *
! 8: * Can be freely distributed and used under the terms of the GNU GPL.
! 9: */
! 10:
! 11: #include "ospf.h"
! 12:
! 13:
! 14: struct ospf_hello2_packet
! 15: {
! 16: struct ospf_packet hdr;
! 17: union ospf_auth auth;
! 18:
! 19: u32 netmask;
! 20: u16 helloint;
! 21: u8 options;
! 22: u8 priority;
! 23: u32 deadint;
! 24: u32 dr;
! 25: u32 bdr;
! 26:
! 27: u32 neighbors[];
! 28: };
! 29:
! 30: struct ospf_hello3_packet
! 31: {
! 32: struct ospf_packet hdr;
! 33:
! 34: u32 iface_id;
! 35: u8 priority;
! 36: u8 options3;
! 37: u8 options2;
! 38: u8 options;
! 39: u16 helloint;
! 40: u16 deadint;
! 41: u32 dr;
! 42: u32 bdr;
! 43:
! 44: u32 neighbors[];
! 45: };
! 46:
! 47:
! 48: void
! 49: ospf_send_hello(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
! 50: {
! 51: struct ospf_proto *p = ifa->oa->po;
! 52: struct ospf_packet *pkt;
! 53: struct ospf_neighbor *neigh, *n1;
! 54: struct nbma_node *nb;
! 55: u32 *neighbors;
! 56: uint length;
! 57: int i, max;
! 58:
! 59: if (ifa->state <= OSPF_IS_LOOP)
! 60: return;
! 61:
! 62: if (ifa->stub)
! 63: return;
! 64:
! 65:
! 66: pkt = ospf_tx_buffer(ifa);
! 67: ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
! 68:
! 69: if (ospf_is_v2(p))
! 70: {
! 71: struct ospf_hello2_packet *ps = (void *) pkt;
! 72:
! 73: if ((ifa->type == OSPF_IT_VLINK) ||
! 74: ((ifa->type == OSPF_IT_PTP) && !ifa->ptp_netmask))
! 75: ps->netmask = 0;
! 76: else
! 77: ps->netmask = htonl(u32_mkmask(ifa->addr->pxlen));
! 78:
! 79: ps->helloint = ntohs(ifa->helloint);
! 80: ps->options = ifa->oa->options;
! 81: ps->priority = ifa->priority;
! 82: ps->deadint = htonl(ifa->deadint);
! 83: ps->dr = htonl(ipa_to_u32(ifa->drip));
! 84: ps->bdr = htonl(ipa_to_u32(ifa->bdrip));
! 85:
! 86: length = sizeof(struct ospf_hello2_packet);
! 87: neighbors = ps->neighbors;
! 88: }
! 89: else
! 90: {
! 91: struct ospf_hello3_packet *ps = (void *) pkt;
! 92:
! 93: ps->iface_id = htonl(ifa->iface_id);
! 94: ps->priority = ifa->priority;
! 95: ps->options3 = ifa->oa->options >> 16;
! 96: ps->options2 = ifa->oa->options >> 8;
! 97: ps->options = ifa->oa->options;
! 98: ps->helloint = ntohs(ifa->helloint);
! 99: ps->deadint = htons(ifa->deadint);
! 100: ps->dr = htonl(ifa->drid);
! 101: ps->bdr = htonl(ifa->bdrid);
! 102:
! 103: length = sizeof(struct ospf_hello3_packet);
! 104: neighbors = ps->neighbors;
! 105: }
! 106:
! 107: i = 0;
! 108: max = (ospf_pkt_maxsize(ifa) - length) / sizeof(u32);
! 109:
! 110: /* Fill all neighbors */
! 111: if (kind != OHS_SHUTDOWN)
! 112: {
! 113: WALK_LIST(neigh, ifa->neigh_list)
! 114: {
! 115: if (i == max)
! 116: {
! 117: log(L_WARN "%s: Too many neighbors on %s", p->p.name, ifa->ifname);
! 118: break;
! 119: }
! 120: neighbors[i] = htonl(neigh->rid);
! 121: i++;
! 122: }
! 123: }
! 124:
! 125: length += i * sizeof(u32);
! 126: pkt->length = htons(length);
! 127:
! 128: OSPF_TRACE(D_PACKETS, "HELLO packet sent via %s", ifa->ifname);
! 129:
! 130: switch(ifa->type)
! 131: {
! 132: case OSPF_IT_BCAST:
! 133: case OSPF_IT_PTP:
! 134: ospf_send_to_all(ifa);
! 135: break;
! 136:
! 137: case OSPF_IT_NBMA:
! 138: if (dirn) /* Response to received hello */
! 139: {
! 140: ospf_send_to(ifa, dirn->ip);
! 141: break;
! 142: }
! 143:
! 144: int to_all = ifa->state > OSPF_IS_DROTHER;
! 145: int me_elig = ifa->priority > 0;
! 146:
! 147: if (kind == OHS_POLL) /* Poll timer */
! 148: {
! 149: WALK_LIST(nb, ifa->nbma_list)
! 150: if (!nb->found && (to_all || (me_elig && nb->eligible)))
! 151: ospf_send_to(ifa, nb->ip);
! 152: }
! 153: else /* Hello timer */
! 154: {
! 155: WALK_LIST(n1, ifa->neigh_list)
! 156: if (to_all || (me_elig && (n1->priority > 0)) ||
! 157: (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid))
! 158: ospf_send_to(ifa, n1->ip);
! 159: }
! 160: break;
! 161:
! 162: case OSPF_IT_PTMP:
! 163: WALK_LIST(n1, ifa->neigh_list)
! 164: ospf_send_to(ifa, n1->ip);
! 165:
! 166: WALK_LIST(nb, ifa->nbma_list)
! 167: if (!nb->found)
! 168: ospf_send_to(ifa, nb->ip);
! 169:
! 170: /* If there is no other target, we also send HELLO packet to the other end */
! 171: if (ipa_nonzero(ifa->addr->opposite) && !ifa->strictnbma &&
! 172: EMPTY_LIST(ifa->neigh_list) && EMPTY_LIST(ifa->nbma_list))
! 173: ospf_send_to(ifa, ifa->addr->opposite);
! 174: break;
! 175:
! 176: case OSPF_IT_VLINK:
! 177: ospf_send_to(ifa, ifa->vip);
! 178: break;
! 179:
! 180: default:
! 181: bug("Bug in ospf_send_hello()");
! 182: }
! 183: }
! 184:
! 185:
! 186: void
! 187: ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
! 188: struct ospf_neighbor *n, ip_addr faddr)
! 189: {
! 190: struct ospf_proto *p = ifa->oa->po;
! 191: const char *err_dsc = NULL;
! 192: u32 rcv_iface_id, rcv_helloint, rcv_deadint, rcv_dr, rcv_bdr;
! 193: u8 rcv_options, rcv_priority;
! 194: u32 *neighbors;
! 195: u32 neigh_count;
! 196: uint plen, i, err_val = 0;
! 197:
! 198: /* RFC 2328 10.5 */
! 199:
! 200: /*
! 201: * We may not yet havethe associate neighbor, so we use Router ID from the
! 202: * packet instead of one from the neighbor structure for log messages.
! 203: */
! 204: u32 rcv_rid = ntohl(pkt->routerid);
! 205: OSPF_TRACE(D_PACKETS, "HELLO packet received from nbr %R on %s", rcv_rid, ifa->ifname);
! 206:
! 207: plen = ntohs(pkt->length);
! 208:
! 209: if (ospf_is_v2(p))
! 210: {
! 211: struct ospf_hello2_packet *ps = (void *) pkt;
! 212:
! 213: if (plen < sizeof(struct ospf_hello2_packet))
! 214: DROP("too short", plen);
! 215:
! 216: rcv_iface_id = 0;
! 217: rcv_helloint = ntohs(ps->helloint);
! 218: rcv_deadint = ntohl(ps->deadint);
! 219: rcv_dr = ntohl(ps->dr);
! 220: rcv_bdr = ntohl(ps->bdr);
! 221: rcv_options = ps->options;
! 222: rcv_priority = ps->priority;
! 223:
! 224: int pxlen = u32_masklen(ntohl(ps->netmask));
! 225: if (pxlen < 0)
! 226: DROP("prefix garbled", ntohl(ps->netmask));
! 227:
! 228: if ((ifa->type != OSPF_IT_VLINK) &&
! 229: (ifa->type != OSPF_IT_PTP) &&
! 230: ((uint) pxlen != ifa->addr->pxlen))
! 231: DROP("prefix length mismatch", pxlen);
! 232:
! 233: neighbors = ps->neighbors;
! 234: neigh_count = (plen - sizeof(struct ospf_hello2_packet)) / sizeof(u32);
! 235: }
! 236: else /* OSPFv3 */
! 237: {
! 238: struct ospf_hello3_packet *ps = (void *) pkt;
! 239:
! 240: if (plen < sizeof(struct ospf_hello3_packet))
! 241: DROP("too short", plen);
! 242:
! 243: rcv_iface_id = ntohl(ps->iface_id);
! 244: rcv_helloint = ntohs(ps->helloint);
! 245: rcv_deadint = ntohs(ps->deadint);
! 246: rcv_dr = ntohl(ps->dr);
! 247: rcv_bdr = ntohl(ps->bdr);
! 248: rcv_options = ps->options;
! 249: rcv_priority = ps->priority;
! 250:
! 251: neighbors = ps->neighbors;
! 252: neigh_count = (plen - sizeof(struct ospf_hello3_packet)) / sizeof(u32);
! 253: }
! 254:
! 255: if (rcv_helloint != ifa->helloint)
! 256: DROP("hello interval mismatch", rcv_helloint);
! 257:
! 258: if (rcv_deadint != ifa->deadint)
! 259: DROP("dead interval mismatch", rcv_deadint);
! 260:
! 261: /* Check whether bits E, N match */
! 262: if ((rcv_options ^ ifa->oa->options) & (OPT_E | OPT_N))
! 263: DROP("area type mismatch", rcv_options);
! 264:
! 265: /* Check consistency of existing neighbor entry */
! 266: if (n)
! 267: {
! 268: uint t = ifa->type;
! 269: if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
! 270: {
! 271: /* Neighbor identified by IP address; Router ID may change */
! 272: if (n->rid != rcv_rid)
! 273: {
! 274: OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed Router ID to %R",
! 275: n->rid, ifa->ifname, rcv_rid);
! 276: ospf_neigh_sm(n, INM_KILLNBR);
! 277: n = NULL;
! 278: }
! 279: }
! 280: else /* OSPFv3 or OSPFv2/PtP */
! 281: {
! 282: /* Neighbor identified by Router ID; IP address may change */
! 283: if (!ipa_equal(faddr, n->ip))
! 284: {
! 285: OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed IP address to %I",
! 286: n->rid, ifa->ifname, n->ip, faddr);
! 287: n->ip = faddr;
! 288: }
! 289: }
! 290: }
! 291:
! 292: if (!n)
! 293: {
! 294: if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
! 295: {
! 296: struct nbma_node *nn = find_nbma_node(ifa, faddr);
! 297:
! 298: if (!nn && ifa->strictnbma)
! 299: DROP1("new neighbor denied");
! 300:
! 301: if (nn && (ifa->type == OSPF_IT_NBMA) &&
! 302: (((rcv_priority == 0) && nn->eligible) ||
! 303: ((rcv_priority > 0) && !nn->eligible)))
! 304: DROP("eligibility mismatch", rcv_priority);
! 305:
! 306: if (nn)
! 307: nn->found = 1;
! 308: }
! 309:
! 310: OSPF_TRACE(D_EVENTS, "New neighbor %R on %s, IP address %I",
! 311: rcv_rid, ifa->ifname, faddr);
! 312:
! 313: n = ospf_neighbor_new(ifa);
! 314:
! 315: n->rid = rcv_rid;
! 316: n->ip = faddr;
! 317: n->dr = rcv_dr;
! 318: n->bdr = rcv_bdr;
! 319: n->priority = rcv_priority;
! 320: n->iface_id = rcv_iface_id;
! 321:
! 322: if (n->ifa->cf->bfd)
! 323: ospf_neigh_update_bfd(n, n->ifa->bfd);
! 324: }
! 325:
! 326: u32 n_id = ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid;
! 327:
! 328: u32 old_dr = n->dr;
! 329: u32 old_bdr = n->bdr;
! 330: u32 old_priority = n->priority;
! 331: u32 old_iface_id = n->iface_id;
! 332:
! 333: n->dr = rcv_dr;
! 334: n->bdr = rcv_bdr;
! 335: n->priority = rcv_priority;
! 336: n->iface_id = rcv_iface_id;
! 337:
! 338:
! 339: /* Update inactivity timer */
! 340: ospf_neigh_sm(n, INM_HELLOREC);
! 341:
! 342: /* RFC 2328 9.5.1 - non-eligible routers reply to hello on NBMA nets */
! 343: if (ifa->type == OSPF_IT_NBMA)
! 344: if ((ifa->priority == 0) && (n->priority > 0))
! 345: ospf_send_hello(n->ifa, OHS_HELLO, n);
! 346:
! 347:
! 348: /* Examine list of neighbors */
! 349: for (i = 0; i < neigh_count; i++)
! 350: if (neighbors[i] == htonl(p->router_id))
! 351: goto found_self;
! 352:
! 353: ospf_neigh_sm(n, INM_1WAYREC);
! 354: return;
! 355:
! 356: found_self:
! 357: ospf_neigh_sm(n, INM_2WAYREC);
! 358:
! 359:
! 360: if (n->iface_id != old_iface_id)
! 361: {
! 362: /* If neighbor is DR, also update cached DR interface ID */
! 363: if (ifa->drid == n->rid)
! 364: ifa->dr_iface_id = n->iface_id;
! 365:
! 366: /* RFC 5340 4.4.3 Event 4 - change of neighbor's interface ID */
! 367: ospf_notify_rt_lsa(ifa->oa);
! 368:
! 369: /* Missed in RFC 5340 4.4.3 Event 4 - (Px-)Net-LSA uses iface_id to ref Link-LSAs */
! 370: ospf_notify_net_lsa(ifa);
! 371: }
! 372:
! 373: if (ifa->state == OSPF_IS_WAITING)
! 374: {
! 375: /* Neighbor is declaring itself DR (and there is no BDR) or as BDR */
! 376: if (((n->dr == n_id) && (n->bdr == 0)) || (n->bdr == n_id))
! 377: ospf_iface_sm(ifa, ISM_BACKS);
! 378: }
! 379: else if (ifa->state >= OSPF_IS_DROTHER)
! 380: {
! 381: /* Neighbor changed priority or started/stopped declaring itself as DR/BDR */
! 382: if ((n->priority != old_priority) ||
! 383: ((n->dr == n_id) && (old_dr != n_id)) ||
! 384: ((n->dr != n_id) && (old_dr == n_id)) ||
! 385: ((n->bdr == n_id) && (old_bdr != n_id)) ||
! 386: ((n->bdr != n_id) && (old_bdr == n_id)))
! 387: ospf_iface_sm(ifa, ISM_NEICH);
! 388: }
! 389:
! 390: return;
! 391:
! 392: drop:
! 393: LOG_PKT("Bad HELLO packet from nbr %R on %s - %s (%u)",
! 394: rcv_rid, ifa->ifname, err_dsc, err_val);
! 395: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>