]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/hello.c
e00487dc6d40ce39e5f28646d45d6610a7c52b98
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
;
30 struct ospf_hello3_packet
32 struct ospf_packet hdr
;
49 ospf_send_hello(struct ospf_iface
*ifa
, int kind
, struct ospf_neighbor
*dirn
)
51 struct ospf_proto
*p
= ifa
->oa
->po
;
52 struct ospf_packet
*pkt
;
53 struct ospf_neighbor
*neigh
, *n1
;
59 if (ifa
->state
<= OSPF_IS_LOOP
)
66 pkt
= ospf_tx_buffer(ifa
);
67 ospf_pkt_fill_hdr(ifa
, pkt
, HELLO_P
);
71 struct ospf_hello2_packet
*ps
= (void *) pkt
;
73 if ((ifa
->type
== OSPF_IT_VLINK
) ||
74 ((ifa
->type
== OSPF_IT_PTP
) && !ifa
->ptp_netmask
))
77 ps
->netmask
= htonl(u32_mkmask(ifa
->addr
->pxlen
));
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
));
86 length
= sizeof(struct ospf_hello2_packet
);
87 neighbors
= ps
->neighbors
;
91 struct ospf_hello3_packet
*ps
= (void *) pkt
;
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
);
103 length
= sizeof(struct ospf_hello3_packet
);
104 neighbors
= ps
->neighbors
;
108 max
= (ospf_pkt_maxsize(ifa
) - length
) / sizeof(u32
);
110 /* Fill all neighbors */
111 if (kind
!= OHS_SHUTDOWN
)
113 WALK_LIST(neigh
, ifa
->neigh_list
)
117 log(L_WARN
"%s: Too many neighbors on %s", p
->p
.name
, ifa
->ifname
);
120 neighbors
[i
] = htonl(neigh
->rid
);
125 length
+= i
* sizeof(u32
);
126 pkt
->length
= htons(length
);
128 OSPF_TRACE(D_PACKETS
, "HELLO packet sent via %s", ifa
->ifname
);
134 ospf_send_to_all(ifa
);
138 if (dirn
) /* Response to received hello */
140 ospf_send_to(ifa
, dirn
->ip
);
144 int to_all
= ifa
->state
> OSPF_IS_DROTHER
;
145 int me_elig
= ifa
->priority
> 0;
147 if (kind
== OHS_POLL
) /* Poll timer */
149 WALK_LIST(nb
, ifa
->nbma_list
)
150 if (!nb
->found
&& (to_all
|| (me_elig
&& nb
->eligible
)))
151 ospf_send_to(ifa
, nb
->ip
);
153 else /* Hello timer */
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
);
163 WALK_LIST(n1
, ifa
->neigh_list
)
164 ospf_send_to(ifa
, n1
->ip
);
166 WALK_LIST(nb
, ifa
->nbma_list
)
168 ospf_send_to(ifa
, nb
->ip
);
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
);
177 ospf_send_to(ifa
, ifa
->vip
);
181 bug("Bug in ospf_send_hello()");
187 ospf_receive_hello(struct ospf_packet
*pkt
, struct ospf_iface
*ifa
,
188 struct ospf_neighbor
*n
, ip_addr faddr
)
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
;
196 uint plen
, i
, err_val
= 0;
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.
204 u32 rcv_rid
= ntohl(pkt
->routerid
);
205 OSPF_TRACE(D_PACKETS
, "HELLO packet received from nbr %R on %s", rcv_rid
, ifa
->ifname
);
207 plen
= ntohs(pkt
->length
);
211 struct ospf_hello2_packet
*ps
= (void *) pkt
;
213 if (plen
< sizeof(struct ospf_hello2_packet
))
214 DROP("too short", plen
);
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
;
224 int pxlen
= u32_masklen(ntohl(ps
->netmask
));
226 DROP("prefix garbled", ntohl(ps
->netmask
));
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
);
233 neighbors
= ps
->neighbors
;
234 neigh_count
= (plen
- sizeof(struct ospf_hello2_packet
)) / sizeof(u32
);
238 struct ospf_hello3_packet
*ps
= (void *) pkt
;
240 if (plen
< sizeof(struct ospf_hello3_packet
))
241 DROP("too short", plen
);
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
;
251 neighbors
= ps
->neighbors
;
252 neigh_count
= (plen
- sizeof(struct ospf_hello3_packet
)) / sizeof(u32
);
255 if (rcv_helloint
!= ifa
->helloint
)
256 DROP("hello interval mismatch", rcv_helloint
);
258 if (rcv_deadint
!= ifa
->deadint
)
259 DROP("dead interval mismatch", rcv_deadint
);
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
);
265 /* Check consistency of existing neighbor entry */
269 if (ospf_is_v2(p
) && ((t
== OSPF_IT_BCAST
) || (t
== OSPF_IT_NBMA
) || (t
== OSPF_IT_PTMP
)))
271 /* Neighbor identified by IP address; Router ID may change */
272 if (n
->rid
!= rcv_rid
)
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
);
280 else /* OSPFv3 or OSPFv2/PtP */
282 /* Neighbor identified by Router ID; IP address may change */
283 if (!ipa_equal(faddr
, n
->ip
))
285 OSPF_TRACE(D_EVENTS
, "Neighbor %R on %s changed IP address to %I",
286 n
->rid
, ifa
->ifname
, n
->ip
, faddr
);
294 if ((ifa
->type
== OSPF_IT_NBMA
) || (ifa
->type
== OSPF_IT_PTMP
))
296 struct nbma_node
*nn
= find_nbma_node(ifa
, faddr
);
298 if (!nn
&& ifa
->strictnbma
)
299 DROP1("new neighbor denied");
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
);
310 OSPF_TRACE(D_EVENTS
, "New neighbor %R on %s, IP address %I",
311 rcv_rid
, ifa
->ifname
, faddr
);
313 n
= ospf_neighbor_new(ifa
);
319 n
->priority
= rcv_priority
;
320 n
->iface_id
= rcv_iface_id
;
323 ospf_neigh_update_bfd(n
, n
->ifa
->bfd
);
326 u32 n_id
= ospf_is_v2(p
) ? ipa_to_u32(n
->ip
) : n
->rid
;
329 u32 old_bdr
= n
->bdr
;
330 u32 old_priority
= n
->priority
;
331 u32 old_iface_id
= n
->iface_id
;
335 n
->priority
= rcv_priority
;
336 n
->iface_id
= rcv_iface_id
;
339 /* Update inactivity timer */
340 ospf_neigh_sm(n
, INM_HELLOREC
);
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
);
348 /* Examine list of neighbors */
349 for (i
= 0; i
< neigh_count
; i
++)
350 if (neighbors
[i
] == htonl(p
->router_id
))
353 ospf_neigh_sm(n
, INM_1WAYREC
);
357 ospf_neigh_sm(n
, INM_2WAYREC
);
360 if (n
->iface_id
!= old_iface_id
)
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
;
366 /* RFC 5340 4.4.3 Event 4 - change of neighbor's interface ID */
367 ospf_notify_rt_lsa(ifa
->oa
);
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
);
373 if (ifa
->state
== OSPF_IS_WAITING
)
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
);
379 else if (ifa
->state
>= OSPF_IS_DROTHER
)
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
);
393 LOG_PKT("Bad HELLO packet from nbr %R on %s - %s (%u)",
394 rcv_rid
, ifa
->ifname
, err_dsc
, err_val
);