| 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 | } |