Return to hello.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / proto / ospf |
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: }