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