File: | src/usr.sbin/ospf6d/hello.c |
Warning: | line 70, column 2 The left operand of '&' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: hello.c,v 1.23 2020/07/15 14:47:41 denis Exp $ */ | |||
2 | ||||
3 | /* | |||
4 | * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> | |||
5 | * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> | |||
6 | * | |||
7 | * Permission to use, copy, modify, and distribute this software for any | |||
8 | * purpose with or without fee is hereby granted, provided that the above | |||
9 | * copyright notice and this permission notice appear in all copies. | |||
10 | * | |||
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
18 | */ | |||
19 | ||||
20 | #include <sys/types.h> | |||
21 | #include <sys/socket.h> | |||
22 | #include <netinet/in.h> | |||
23 | #include <arpa/inet.h> | |||
24 | #include <sys/time.h> | |||
25 | #include <stdlib.h> | |||
26 | #include <string.h> | |||
27 | #include <event.h> | |||
28 | ||||
29 | #include "ospf6d.h" | |||
30 | #include "ospf6.h" | |||
31 | #include "log.h" | |||
32 | #include "ospfe.h" | |||
33 | ||||
34 | /* hello packet handling */ | |||
35 | int | |||
36 | send_hello(struct iface *iface) | |||
37 | { | |||
38 | struct in6_addr dst; | |||
39 | struct hello_hdr hello; | |||
40 | struct nbr *nbr; | |||
41 | struct ibuf *buf; | |||
42 | ||||
43 | switch (iface->type) { | |||
| ||||
44 | case IF_TYPE_POINTOPOINT: | |||
45 | case IF_TYPE_BROADCAST: | |||
46 | inet_pton(AF_INET624, AllSPFRouters"ff02::5", &dst); | |||
47 | break; | |||
48 | case IF_TYPE_NBMA: | |||
49 | case IF_TYPE_POINTOMULTIPOINT: | |||
50 | log_debug("send_hello: type %s not supported, interface %s", | |||
51 | if_type_name(iface->type), iface->name); | |||
52 | return (-1); | |||
53 | case IF_TYPE_VIRTUALLINK: | |||
54 | dst = iface->dst; | |||
55 | break; | |||
56 | default: | |||
57 | fatalx("send_hello: unknown interface type"); | |||
58 | } | |||
59 | ||||
60 | /* XXX IBUF_READ_SIZE */ | |||
61 | if ((buf = ibuf_dynamic(PKG_DEF_SIZE512, IBUF_READ_SIZE65535)) == NULL((void *)0)) | |||
62 | fatal("send_hello"); | |||
63 | ||||
64 | /* OSPF header */ | |||
65 | if (gen_ospf_hdr(buf, iface, PACKET_TYPE_HELLO1)) | |||
66 | goto fail; | |||
67 | ||||
68 | /* hello header */ | |||
69 | hello.iface_id = htonl(iface->ifindex)(__uint32_t)(__builtin_constant_p(iface->ifindex) ? (__uint32_t )(((__uint32_t)(iface->ifindex) & 0xff) << 24 | ( (__uint32_t)(iface->ifindex) & 0xff00) << 8 | (( __uint32_t)(iface->ifindex) & 0xff0000) >> 8 | ( (__uint32_t)(iface->ifindex) & 0xff000000) >> 24 ) : __swap32md(iface->ifindex)); | |||
70 | LSA_24_SETHI(hello.opts, iface->priority)((hello.opts) = ((hello.opts) & 0xffffff) | (((iface-> priority) & 0xff) << 24)); | |||
| ||||
71 | LSA_24_SETLO(hello.opts, area_ospf_options(iface->area))((hello.opts) = ((area_ospf_options(iface->area)) & 0xffffff ) | ((hello.opts) & ~0xffffff)); | |||
72 | hello.opts = htonl(hello.opts)(__uint32_t)(__builtin_constant_p(hello.opts) ? (__uint32_t)( ((__uint32_t)(hello.opts) & 0xff) << 24 | ((__uint32_t )(hello.opts) & 0xff00) << 8 | ((__uint32_t)(hello. opts) & 0xff0000) >> 8 | ((__uint32_t)(hello.opts) & 0xff000000) >> 24) : __swap32md(hello.opts)); | |||
73 | hello.hello_interval = htons(iface->hello_interval)(__uint16_t)(__builtin_constant_p(iface->hello_interval) ? (__uint16_t)(((__uint16_t)(iface->hello_interval) & 0xffU ) << 8 | ((__uint16_t)(iface->hello_interval) & 0xff00U ) >> 8) : __swap16md(iface->hello_interval)); | |||
74 | hello.rtr_dead_interval = htons(iface->dead_interval)(__uint16_t)(__builtin_constant_p(iface->dead_interval) ? ( __uint16_t)(((__uint16_t)(iface->dead_interval) & 0xffU ) << 8 | ((__uint16_t)(iface->dead_interval) & 0xff00U ) >> 8) : __swap16md(iface->dead_interval)); | |||
75 | ||||
76 | if (iface->dr) { | |||
77 | hello.d_rtr = iface->dr->id.s_addr; | |||
78 | iface->self->dr.s_addr = iface->dr->id.s_addr; | |||
79 | } else | |||
80 | hello.d_rtr = 0; | |||
81 | if (iface->bdr) { | |||
82 | hello.bd_rtr = iface->bdr->id.s_addr; | |||
83 | iface->self->bdr.s_addr = iface->bdr->id.s_addr; | |||
84 | } else | |||
85 | hello.bd_rtr = 0; | |||
86 | ||||
87 | if (ibuf_add(buf, &hello, sizeof(hello))) | |||
88 | goto fail; | |||
89 | ||||
90 | /* active neighbor(s) */ | |||
91 | LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!= ((void *)0); (nbr) = ((nbr)->entry.le_next)) { | |||
92 | if ((nbr->state >= NBR_STA_INIT0x0004) && (nbr != iface->self)) | |||
93 | if (ibuf_add(buf, &nbr->id, sizeof(nbr->id))) | |||
94 | goto fail; | |||
95 | } | |||
96 | ||||
97 | /* calculate checksum */ | |||
98 | if (upd_ospf_hdr(buf, iface)) | |||
99 | goto fail; | |||
100 | ||||
101 | if (send_packet(iface, buf, &dst) == -1) | |||
102 | goto fail; | |||
103 | ||||
104 | ibuf_free(buf); | |||
105 | return (0); | |||
106 | fail: | |||
107 | log_warn("send_hello"); | |||
108 | ibuf_free(buf); | |||
109 | return (-1); | |||
110 | } | |||
111 | ||||
112 | void | |||
113 | recv_hello(struct iface *iface, struct in6_addr *src, u_int32_t rtr_id, | |||
114 | char *buf, u_int16_t len) | |||
115 | { | |||
116 | struct hello_hdr hello; | |||
117 | struct nbr *nbr = NULL((void *)0), *dr; | |||
118 | u_int32_t nbr_id, opts; | |||
119 | int nbr_change = 0; | |||
120 | ||||
121 | if (len < sizeof(hello) || (len & 0x03)) { | |||
122 | log_warnx("recv_hello: bad packet size, interface %s", | |||
123 | iface->name); | |||
124 | return; | |||
125 | } | |||
126 | ||||
127 | memcpy(&hello, buf, sizeof(hello)); | |||
128 | buf += sizeof(hello); | |||
129 | len -= sizeof(hello); | |||
130 | ||||
131 | if (ntohs(hello.hello_interval)(__uint16_t)(__builtin_constant_p(hello.hello_interval) ? (__uint16_t )(((__uint16_t)(hello.hello_interval) & 0xffU) << 8 | ((__uint16_t)(hello.hello_interval) & 0xff00U) >> 8) : __swap16md(hello.hello_interval)) != iface->hello_interval) { | |||
132 | log_warnx("recv_hello: invalid hello-interval %d, " | |||
133 | "interface %s", ntohs(hello.hello_interval)(__uint16_t)(__builtin_constant_p(hello.hello_interval) ? (__uint16_t )(((__uint16_t)(hello.hello_interval) & 0xffU) << 8 | ((__uint16_t)(hello.hello_interval) & 0xff00U) >> 8) : __swap16md(hello.hello_interval)), | |||
134 | iface->name); | |||
135 | return; | |||
136 | } | |||
137 | ||||
138 | if (ntohs(hello.rtr_dead_interval)(__uint16_t)(__builtin_constant_p(hello.rtr_dead_interval) ? ( __uint16_t)(((__uint16_t)(hello.rtr_dead_interval) & 0xffU ) << 8 | ((__uint16_t)(hello.rtr_dead_interval) & 0xff00U ) >> 8) : __swap16md(hello.rtr_dead_interval)) != iface->dead_interval) { | |||
139 | log_warnx("recv_hello: invalid router-dead-interval %d, " | |||
140 | "interface %s", ntohl(hello.rtr_dead_interval)(__uint32_t)(__builtin_constant_p(hello.rtr_dead_interval) ? ( __uint32_t)(((__uint32_t)(hello.rtr_dead_interval) & 0xff ) << 24 | ((__uint32_t)(hello.rtr_dead_interval) & 0xff00 ) << 8 | ((__uint32_t)(hello.rtr_dead_interval) & 0xff0000 ) >> 8 | ((__uint32_t)(hello.rtr_dead_interval) & 0xff000000 ) >> 24) : __swap32md(hello.rtr_dead_interval)), | |||
141 | iface->name); | |||
142 | return; | |||
143 | } | |||
144 | ||||
145 | opts = LSA_24_GETLO(ntohl(hello.opts))(((__uint32_t)(__builtin_constant_p(hello.opts) ? (__uint32_t )(((__uint32_t)(hello.opts) & 0xff) << 24 | ((__uint32_t )(hello.opts) & 0xff00) << 8 | ((__uint32_t)(hello. opts) & 0xff0000) >> 8 | ((__uint32_t)(hello.opts) & 0xff000000) >> 24) : __swap32md(hello.opts))) & 0xffffff ); | |||
146 | if ((opts & OSPF_OPTION_E0x02 && iface->area->stub) || | |||
147 | ((opts & OSPF_OPTION_E0x02) == 0 && !iface->area->stub)) { | |||
148 | log_warnx("recv_hello: ExternalRoutingCapability mismatch, " | |||
149 | "interface %s", iface->name); | |||
150 | return; | |||
151 | } | |||
152 | ||||
153 | /* match router-id */ | |||
154 | LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!= ((void *)0); (nbr) = ((nbr)->entry.le_next)) { | |||
155 | if (nbr == iface->self) { | |||
156 | if (nbr->id.s_addr == rtr_id) { | |||
157 | log_warnx("recv_hello: Router-ID collision on " | |||
158 | "interface %s neighbor IP %s", iface->name, | |||
159 | log_in6addr(src)); | |||
160 | return; | |||
161 | } | |||
162 | continue; | |||
163 | } | |||
164 | if (nbr->id.s_addr == rtr_id) | |||
165 | break; | |||
166 | } | |||
167 | ||||
168 | if (!nbr) { | |||
169 | nbr = nbr_new(rtr_id, iface, ntohl(hello.iface_id)(__uint32_t)(__builtin_constant_p(hello.iface_id) ? (__uint32_t )(((__uint32_t)(hello.iface_id) & 0xff) << 24 | ((__uint32_t )(hello.iface_id) & 0xff00) << 8 | ((__uint32_t)(hello .iface_id) & 0xff0000) >> 8 | ((__uint32_t)(hello.iface_id ) & 0xff000000) >> 24) : __swap32md(hello.iface_id) ), 0, src); | |||
170 | /* set neighbor parameters */ | |||
171 | nbr->dr.s_addr = hello.d_rtr; | |||
172 | nbr->bdr.s_addr = hello.bd_rtr; | |||
173 | nbr->priority = LSA_24_GETHI(ntohl(hello.opts))(((__uint32_t)(__builtin_constant_p(hello.opts) ? (__uint32_t )(((__uint32_t)(hello.opts) & 0xff) << 24 | ((__uint32_t )(hello.opts) & 0xff00) << 8 | ((__uint32_t)(hello. opts) & 0xff0000) >> 8 | ((__uint32_t)(hello.opts) & 0xff000000) >> 24) : __swap32md(hello.opts))) >> 24); | |||
174 | /* XXX neighbor address shouldn't be stored on virtual links */ | |||
175 | nbr->addr = *src; | |||
176 | } | |||
177 | ||||
178 | if (!IN6_ARE_ADDR_EQUAL(&nbr->addr, src)(memcmp(&(&nbr->addr)->__u6_addr.__u6_addr8[0], &(src)->__u6_addr.__u6_addr8[0], sizeof(struct in6_addr )) == 0)) { | |||
179 | log_warnx("%s: neighbor ID %s changed its address to %s", | |||
180 | __func__, inet_ntoa(nbr->id), log_in6addr(src)); | |||
181 | nbr->addr = *src; | |||
182 | } | |||
183 | ||||
184 | nbr->options = opts; | |||
185 | ||||
186 | nbr_fsm(nbr, NBR_EVT_HELLO_RCVD); | |||
187 | ||||
188 | while (len >= sizeof(nbr_id)) { | |||
189 | memcpy(&nbr_id, buf, sizeof(nbr_id)); | |||
190 | if (nbr_id == ospfe_router_id()) { | |||
191 | /* seen myself */ | |||
192 | if (nbr->state & NBR_STA_PRELIM(0x0001 | 0x0002 | 0x0004)) { | |||
193 | nbr_fsm(nbr, NBR_EVT_2_WAY_RCVD); | |||
194 | nbr_change = 1; | |||
195 | } | |||
196 | break; | |||
197 | } | |||
198 | buf += sizeof(nbr_id); | |||
199 | len -= sizeof(nbr_id); | |||
200 | } | |||
201 | ||||
202 | if (len == 0) { | |||
203 | nbr_fsm(nbr, NBR_EVT_1_WAY_RCVD); | |||
204 | /* set neighbor parameters */ | |||
205 | nbr->dr.s_addr = hello.d_rtr; | |||
206 | nbr->bdr.s_addr = hello.bd_rtr; | |||
207 | nbr->priority = LSA_24_GETHI(ntohl(hello.opts))(((__uint32_t)(__builtin_constant_p(hello.opts) ? (__uint32_t )(((__uint32_t)(hello.opts) & 0xff) << 24 | ((__uint32_t )(hello.opts) & 0xff00) << 8 | ((__uint32_t)(hello. opts) & 0xff0000) >> 8 | ((__uint32_t)(hello.opts) & 0xff000000) >> 24) : __swap32md(hello.opts))) >> 24); | |||
208 | return; | |||
209 | } | |||
210 | ||||
211 | if (nbr->priority != LSA_24_GETHI(ntohl(hello.opts))(((__uint32_t)(__builtin_constant_p(hello.opts) ? (__uint32_t )(((__uint32_t)(hello.opts) & 0xff) << 24 | ((__uint32_t )(hello.opts) & 0xff00) << 8 | ((__uint32_t)(hello. opts) & 0xff0000) >> 8 | ((__uint32_t)(hello.opts) & 0xff000000) >> 24) : __swap32md(hello.opts))) >> 24)) { | |||
212 | nbr->priority = LSA_24_GETHI(ntohl(hello.opts))(((__uint32_t)(__builtin_constant_p(hello.opts) ? (__uint32_t )(((__uint32_t)(hello.opts) & 0xff) << 24 | ((__uint32_t )(hello.opts) & 0xff00) << 8 | ((__uint32_t)(hello. opts) & 0xff0000) >> 8 | ((__uint32_t)(hello.opts) & 0xff000000) >> 24) : __swap32md(hello.opts))) >> 24); | |||
213 | nbr_change = 1; | |||
214 | } | |||
215 | ||||
216 | if (iface->state & IF_STA_WAITING0x04 && | |||
217 | hello.d_rtr == nbr->id.s_addr && hello.bd_rtr == 0) | |||
218 | if_fsm(iface, IF_EVT_BACKUP_SEEN); | |||
219 | ||||
220 | if (iface->state & IF_STA_WAITING0x04 && hello.bd_rtr == nbr->id.s_addr) { | |||
221 | /* | |||
222 | * In case we see the BDR make sure that the DR is around | |||
223 | * with a bidirectional (2_WAY or better) connection | |||
224 | */ | |||
225 | LIST_FOREACH(dr, &iface->nbr_list, entry)for((dr) = ((&iface->nbr_list)->lh_first); (dr)!= ( (void *)0); (dr) = ((dr)->entry.le_next)) | |||
226 | if (hello.d_rtr == dr->id.s_addr && | |||
227 | dr->state & NBR_STA_BIDIR(0x0008 | (0x0010 | 0x0020 | (0x0040 | 0x0080 | 0x0100)))) | |||
228 | if_fsm(iface, IF_EVT_BACKUP_SEEN); | |||
229 | } | |||
230 | ||||
231 | if ((nbr->id.s_addr == nbr->dr.s_addr && | |||
232 | nbr->id.s_addr != hello.d_rtr) || | |||
233 | (nbr->id.s_addr != nbr->dr.s_addr && | |||
234 | nbr->id.s_addr == hello.d_rtr)) | |||
235 | /* neighbor changed from or to DR */ | |||
236 | nbr_change = 1; | |||
237 | if ((nbr->id.s_addr == nbr->bdr.s_addr && | |||
238 | nbr->id.s_addr != hello.bd_rtr) || | |||
239 | (nbr->id.s_addr != nbr->bdr.s_addr && | |||
240 | nbr->id.s_addr == hello.bd_rtr)) | |||
241 | /* neighbor changed from or to BDR */ | |||
242 | nbr_change = 1; | |||
243 | ||||
244 | nbr->dr.s_addr = hello.d_rtr; | |||
245 | nbr->bdr.s_addr = hello.bd_rtr; | |||
246 | ||||
247 | if (nbr_change) | |||
248 | if_fsm(iface, IF_EVT_NBR_CHNG); | |||
249 | ||||
250 | /* TODO NBMA needs some special handling */ | |||
251 | } |