]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/hello.c
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.
8 * Can be freely distributed and used under the terms of the GNU GPL.
14 struct ospf_hello2_packet
16 struct ospf_packet hdr
;
17 union ospf_auth2 auth
;
30 struct ospf_hello3_packet
32 struct ospf_packet hdr
;
46 ospf_hello3_options(struct ospf_packet
*pkt
)
48 struct ospf_hello3_packet
*ps
= (void *) pkt
;
49 return ntohl(ps
->options
) & 0x00FFFFFF;
53 ospf_send_hello(struct ospf_iface
*ifa
, int kind
, struct ospf_neighbor
*dirn
)
55 struct ospf_proto
*p
= ifa
->oa
->po
;
56 struct ospf_packet
*pkt
;
57 struct ospf_neighbor
*neigh
, *n1
;
63 if (ifa
->state
<= OSPF_IS_LOOP
)
70 pkt
= ospf_tx_buffer(ifa
);
71 ospf_pkt_fill_hdr(ifa
, pkt
, HELLO_P
);
75 struct ospf_hello2_packet
*ps
= (void *) pkt
;
77 if ((ifa
->type
== OSPF_IT_VLINK
) ||
78 ((ifa
->type
== OSPF_IT_PTP
) && !ifa
->ptp_netmask
))
81 ps
->netmask
= htonl(u32_mkmask(ifa
->addr
->prefix
.pxlen
));
83 ps
->helloint
= ntohs(ifa
->helloint
);
84 ps
->options
= ifa
->oa
->options
;
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
));
90 length
= sizeof(struct ospf_hello2_packet
);
91 neighbors
= ps
->neighbors
;
95 struct ospf_hello3_packet
*ps
= (void *) pkt
;
96 u32 options
= ifa
->oa
->options
| (ifa
->autype
== OSPF_AUTH_CRYPT
? OPT_AT
: 0);
98 ps
->iface_id
= htonl(ifa
->iface_id
);
99 ps
->options
= ntohl(options
| (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
);
105 length
= sizeof(struct ospf_hello3_packet
);
106 neighbors
= ps
->neighbors
;
110 max
= (ospf_pkt_maxsize(ifa
) - length
) / sizeof(u32
);
112 /* Fill all neighbors */
113 if (kind
!= OHS_SHUTDOWN
)
115 WALK_LIST(neigh
, ifa
->neigh_list
)
119 log(L_WARN
"%s: Too many neighbors on %s", p
->p
.name
, ifa
->ifname
);
122 neighbors
[i
] = htonl(neigh
->rid
);
127 length
+= i
* sizeof(u32
);
128 pkt
->length
= htons(length
);
130 OSPF_TRACE(D_PACKETS
, "HELLO packet sent via %s", ifa
->ifname
);
136 ospf_send_to_all(ifa
);
140 if (dirn
) /* Response to received hello */
142 ospf_send_to(ifa
, dirn
->ip
);
146 int to_all
= ifa
->state
> OSPF_IS_DROTHER
;
147 int me_elig
= ifa
->priority
> 0;
149 if (kind
== OHS_POLL
) /* Poll timer */
151 WALK_LIST(nb
, ifa
->nbma_list
)
152 if (!nb
->found
&& (to_all
|| (me_elig
&& nb
->eligible
)))
153 ospf_send_to(ifa
, nb
->ip
);
155 else /* Hello timer */
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
);
165 WALK_LIST(n1
, ifa
->neigh_list
)
166 ospf_send_to(ifa
, n1
->ip
);
168 WALK_LIST(nb
, ifa
->nbma_list
)
170 ospf_send_to(ifa
, nb
->ip
);
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
);
179 ospf_send_to(ifa
, ifa
->vip
);
183 bug("Bug in ospf_send_hello()");
189 ospf_receive_hello(struct ospf_packet
*pkt
, struct ospf_iface
*ifa
,
190 struct ospf_neighbor
*n
, ip_addr faddr
)
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
;
199 uint plen
, i
, err_val
= 0;
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.
207 u32 rcv_rid
= ntohl(pkt
->routerid
);
208 OSPF_TRACE(D_PACKETS
, "HELLO packet received from nbr %R on %s", rcv_rid
, ifa
->ifname
);
210 plen
= ntohs(pkt
->length
);
214 struct ospf_hello2_packet
*ps
= (void *) pkt
;
216 if (plen
< sizeof(struct ospf_hello2_packet
))
217 DROP("too short", plen
);
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
;
227 int pxlen
= u32_masklen(ntohl(ps
->netmask
));
229 DROP("prefix garbled", ntohl(ps
->netmask
));
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
);
236 neighbors
= ps
->neighbors
;
237 neigh_count
= (plen
- sizeof(struct ospf_hello2_packet
)) / sizeof(u32
);
241 struct ospf_hello3_packet
*ps
= (void *) pkt
;
243 if (plen
< sizeof(struct ospf_hello3_packet
))
244 DROP("too short", plen
);
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;
254 neighbors
= ps
->neighbors
;
255 neigh_count
= (plen
- sizeof(struct ospf_hello3_packet
)) / sizeof(u32
);
258 if (rcv_helloint
!= ifa
->helloint
)
259 DROP("hello interval mismatch", rcv_helloint
);
261 if (rcv_deadint
!= ifa
->deadint
)
262 DROP("dead interval mismatch", rcv_deadint
);
264 /* Check whether bits E, N match */
265 if ((rcv_options
^ loc_options
) & (OPT_E
| OPT_N
))
266 DROP("area type mismatch", rcv_options
);
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
);
272 /* Check consistency of existing neighbor entry */
276 if (ospf_is_v2(p
) && ((t
== OSPF_IT_BCAST
) || (t
== OSPF_IT_NBMA
) || (t
== OSPF_IT_PTMP
)))
278 /* Neighbor identified by IP address; Router ID may change */
279 if (n
->rid
!= rcv_rid
)
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
);
287 else /* OSPFv3 or OSPFv2/PtP */
289 /* Neighbor identified by Router ID; IP address may change */
290 if (!ipa_equal(faddr
, n
->ip
))
292 OSPF_TRACE(D_EVENTS
, "Neighbor %R on %s changed IP address to %I",
293 n
->rid
, ifa
->ifname
, faddr
);
301 if ((ifa
->type
== OSPF_IT_NBMA
) || (ifa
->type
== OSPF_IT_PTMP
))
303 struct nbma_node
*nn
= find_nbma_node(ifa
, faddr
);
305 if (!nn
&& ifa
->strictnbma
)
306 DROP1("new neighbor denied");
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
);
317 OSPF_TRACE(D_EVENTS
, "New neighbor %R on %s, IP address %I",
318 rcv_rid
, ifa
->ifname
, faddr
);
320 n
= ospf_neighbor_new(ifa
);
326 n
->priority
= rcv_priority
;
327 n
->iface_id
= rcv_iface_id
;
330 ospf_neigh_update_bfd(n
, n
->ifa
->bfd
);
333 u32 n_id
= ospf_is_v2(p
) ? ipa_to_u32(n
->ip
) : n
->rid
;
336 u32 old_bdr
= n
->bdr
;
337 u32 old_priority
= n
->priority
;
338 u32 old_iface_id
= n
->iface_id
;
342 n
->priority
= rcv_priority
;
343 n
->iface_id
= rcv_iface_id
;
345 /* Update inactivity timer */
346 ospf_neigh_sm(n
, INM_HELLOREC
);
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
);
354 /* Examine list of neighbors */
355 for (i
= 0; i
< neigh_count
; i
++)
356 if (neighbors
[i
] == htonl(p
->router_id
))
359 ospf_neigh_sm(n
, INM_1WAYREC
);
363 ospf_neigh_sm(n
, INM_2WAYREC
);
366 if (n
->iface_id
!= old_iface_id
)
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
;
372 /* RFC 5340 4.4.3 Event 4 - change of neighbor's interface ID */
373 ospf_notify_rt_lsa(ifa
->oa
);
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
);
379 if (ifa
->state
== OSPF_IS_WAITING
)
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
);
385 else if (ifa
->state
>= OSPF_IS_DROTHER
)
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
);
399 LOG_PKT("Bad HELLO packet from nbr %R on %s - %s (%u)",
400 rcv_rid
, ifa
->ifname
, err_dsc
, err_val
);