1 /* $OpenBSD: config.c,v 1.57 2013/11/13 09:14:48 florian Exp $ */ 2 3 /* 4 * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/socket.h> 21 #include <sys/stat.h> 22 #include <sys/mman.h> 23 #include <sys/ioctl.h> 24 25 #include <netmpls/mpls.h> 26 27 #include <errno.h> 28 #include <ifaddrs.h> 29 #include <netdb.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 34 #include "bgpd.h" 35 #include "session.h" 36 37 u_int32_t get_bgpid(void); 38 int host_v4(const char *, struct bgpd_addr *, u_int8_t *); 39 int host_v6(const char *, struct bgpd_addr *); 40 41 int 42 merge_config(struct bgpd_config *xconf, struct bgpd_config *conf, 43 struct peer *peer_l, struct listen_addrs *listen_addrs) 44 { 45 struct listen_addr *nla, *ola, *next; 46 47 /* 48 * merge the freshly parsed conf into the running xconf 49 */ 50 51 /* preserve cmd line opts */ 52 conf->opts = xconf->opts; 53 54 if (!conf->as) { 55 log_warnx("configuration error: AS not given"); 56 return (1); 57 } 58 59 if (!conf->min_holdtime) 60 conf->min_holdtime = MIN_HOLDTIME; 61 62 if (!conf->bgpid) 63 conf->bgpid = get_bgpid(); 64 65 if ((conf->flags & BGPD_FLAG_REFLECTOR) && conf->clusterid == 0) 66 conf->clusterid = conf->bgpid; 67 68 if (!conf->fib_priority) 69 conf->fib_priority = RTP_BGP; 70 71 free(xconf->csock); 72 free(xconf->rcsock); 73 74 conf->listen_addrs = xconf->listen_addrs; 75 memcpy(xconf, conf, sizeof(struct bgpd_config)); 76 77 if (conf->listen_addrs == NULL) { 78 /* there is no old conf, just copy new one over */ 79 xconf->listen_addrs = listen_addrs; 80 TAILQ_FOREACH(nla, xconf->listen_addrs, entry) 81 nla->reconf = RECONF_REINIT; 82 83 } else { 84 /* 85 * merge new listeners: 86 * -flag all existing ones as to be deleted 87 * -those that are in both new and old: flag to keep 88 * -new ones get inserted and flagged as to reinit 89 * -remove all that are still flagged for deletion 90 */ 91 92 TAILQ_FOREACH(nla, xconf->listen_addrs, entry) 93 nla->reconf = RECONF_DELETE; 94 95 /* no new listeners? preserve default ones */ 96 if (TAILQ_EMPTY(listen_addrs)) 97 TAILQ_FOREACH(ola, xconf->listen_addrs, entry) 98 if (ola->flags & DEFAULT_LISTENER) 99 ola->reconf = RECONF_KEEP; 100 101 for (nla = TAILQ_FIRST(listen_addrs); nla != NULL; nla = next) { 102 next = TAILQ_NEXT(nla, entry); 103 104 TAILQ_FOREACH(ola, xconf->listen_addrs, entry) 105 if (!memcmp(&nla->sa, &ola->sa, 106 sizeof(nla->sa))) 107 break; 108 109 if (ola == NULL) { 110 /* new listener, copy over */ 111 TAILQ_REMOVE(listen_addrs, nla, entry); 112 TAILQ_INSERT_TAIL(xconf->listen_addrs, 113 nla, entry); 114 nla->reconf = RECONF_REINIT; 115 } else /* exists, just flag */ 116 ola->reconf = RECONF_KEEP; 117 } 118 119 for (nla = TAILQ_FIRST(xconf->listen_addrs); nla != NULL; 120 nla = next) { 121 next = TAILQ_NEXT(nla, entry); 122 if (nla->reconf == RECONF_DELETE) { 123 TAILQ_REMOVE(xconf->listen_addrs, nla, entry); 124 free(nla); 125 } 126 } 127 128 while ((ola = TAILQ_FIRST(listen_addrs)) != NULL) { 129 TAILQ_REMOVE(listen_addrs, ola, entry); 130 free(ola); 131 } 132 free(listen_addrs); 133 } 134 135 return (0); 136 } 137 138 u_int32_t 139 get_bgpid(void) 140 { 141 struct ifaddrs *ifap, *ifa; 142 u_int32_t ip = 0, cur, localnet; 143 144 localnet = htonl(INADDR_LOOPBACK & IN_CLASSA_NET); 145 146 if (getifaddrs(&ifap) == -1) 147 fatal("getifaddrs"); 148 149 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 150 if (ifa->ifa_addr->sa_family != AF_INET) 151 continue; 152 cur = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; 153 if ((cur & localnet) == localnet) /* skip 127/8 */ 154 continue; 155 if (ntohl(cur) > ntohl(ip)) 156 ip = cur; 157 } 158 freeifaddrs(ifap); 159 160 return (ip); 161 } 162 163 int 164 host(const char *s, struct bgpd_addr *h, u_int8_t *len) 165 { 166 int done = 0; 167 int mask; 168 char *p, *ps; 169 const char *errstr; 170 171 if ((p = strrchr(s, '/')) != NULL) { 172 mask = strtonum(p + 1, 0, 128, &errstr); 173 if (errstr) { 174 log_warnx("prefixlen is %s: %s", errstr, p + 1); 175 return (0); 176 } 177 if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) 178 fatal("host: malloc"); 179 strlcpy(ps, s, strlen(s) - strlen(p) + 1); 180 } else { 181 if ((ps = strdup(s)) == NULL) 182 fatal("host: strdup"); 183 mask = 128; 184 } 185 186 bzero(h, sizeof(struct bgpd_addr)); 187 188 /* IPv4 address? */ 189 if (!done) 190 done = host_v4(s, h, len); 191 192 /* IPv6 address? */ 193 if (!done) { 194 done = host_v6(ps, h); 195 *len = mask; 196 } 197 198 free(ps); 199 200 return (done); 201 } 202 203 int 204 host_v4(const char *s, struct bgpd_addr *h, u_int8_t *len) 205 { 206 struct in_addr ina; 207 int bits = 32; 208 209 bzero(&ina, sizeof(struct in_addr)); 210 if (strrchr(s, '/') != NULL) { 211 if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1) 212 return (0); 213 } else { 214 if (inet_pton(AF_INET, s, &ina) != 1) 215 return (0); 216 } 217 218 h->aid = AID_INET; 219 h->v4.s_addr = ina.s_addr; 220 *len = bits; 221 222 return (1); 223 } 224 225 int 226 host_v6(const char *s, struct bgpd_addr *h) 227 { 228 struct addrinfo hints, *res; 229 230 bzero(&hints, sizeof(hints)); 231 hints.ai_family = AF_INET6; 232 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 233 hints.ai_flags = AI_NUMERICHOST; 234 if (getaddrinfo(s, "0", &hints, &res) == 0) { 235 sa2addr(res->ai_addr, h); 236 freeaddrinfo(res); 237 return (1); 238 } 239 240 return (0); 241 } 242 243 void 244 prepare_listeners(struct bgpd_config *conf) 245 { 246 struct listen_addr *la, *next; 247 int opt = 1; 248 249 if (TAILQ_EMPTY(conf->listen_addrs)) { 250 if ((la = calloc(1, sizeof(struct listen_addr))) == NULL) 251 fatal("setup_listeners calloc"); 252 la->fd = -1; 253 la->flags = DEFAULT_LISTENER; 254 la->reconf = RECONF_REINIT; 255 la->sa.ss_len = sizeof(struct sockaddr_in); 256 ((struct sockaddr_in *)&la->sa)->sin_family = AF_INET; 257 ((struct sockaddr_in *)&la->sa)->sin_addr.s_addr = 258 htonl(INADDR_ANY); 259 ((struct sockaddr_in *)&la->sa)->sin_port = htons(BGP_PORT); 260 TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry); 261 262 if ((la = calloc(1, sizeof(struct listen_addr))) == NULL) 263 fatal("setup_listeners calloc"); 264 la->fd = -1; 265 la->flags = DEFAULT_LISTENER; 266 la->reconf = RECONF_REINIT; 267 la->sa.ss_len = sizeof(struct sockaddr_in6); 268 ((struct sockaddr_in6 *)&la->sa)->sin6_family = AF_INET6; 269 ((struct sockaddr_in6 *)&la->sa)->sin6_port = htons(BGP_PORT); 270 TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry); 271 } 272 273 for (la = TAILQ_FIRST(conf->listen_addrs); la != NULL; la = next) { 274 next = TAILQ_NEXT(la, entry); 275 if (la->reconf != RECONF_REINIT) 276 continue; 277 278 if ((la->fd = socket(la->sa.ss_family, SOCK_STREAM, 279 IPPROTO_TCP)) == -1) { 280 if (la->flags & DEFAULT_LISTENER && (errno == 281 EAFNOSUPPORT || errno == EPROTONOSUPPORT)) { 282 TAILQ_REMOVE(conf->listen_addrs, la, entry); 283 free(la); 284 continue; 285 } else 286 fatal("socket"); 287 } 288 289 opt = 1; 290 if (setsockopt(la->fd, SOL_SOCKET, SO_REUSEADDR, 291 &opt, sizeof(opt)) == -1) 292 fatal("setsockopt SO_REUSEADDR"); 293 294 if (bind(la->fd, (struct sockaddr *)&la->sa, la->sa.ss_len) == 295 -1) { 296 switch (la->sa.ss_family) { 297 case AF_INET: 298 log_warn("cannot bind to %s:%u", 299 log_sockaddr((struct sockaddr *)&la->sa), 300 ntohs(((struct sockaddr_in *) 301 &la->sa)->sin_port)); 302 break; 303 case AF_INET6: 304 log_warn("cannot bind to [%s]:%u", 305 log_sockaddr((struct sockaddr *)&la->sa), 306 ntohs(((struct sockaddr_in6 *) 307 &la->sa)->sin6_port)); 308 break; 309 default: 310 log_warn("cannot bind to %s", 311 log_sockaddr((struct sockaddr *)&la->sa)); 312 break; 313 } 314 close(la->fd); 315 TAILQ_REMOVE(conf->listen_addrs, la, entry); 316 free(la); 317 continue; 318 } 319 } 320 } 321 322 int 323 get_mpe_label(struct rdomain *r) 324 { 325 struct ifreq ifr; 326 struct shim_hdr shim; 327 int s; 328 329 s = socket(AF_INET, SOCK_DGRAM, 0); 330 if (s == -1) 331 return (-1); 332 333 bzero(&shim, sizeof(shim)); 334 bzero(&ifr, sizeof(ifr)); 335 strlcpy(ifr.ifr_name, r->ifmpe, sizeof(ifr.ifr_name)); 336 ifr.ifr_data = (caddr_t)&shim; 337 338 if (ioctl(s, SIOCGETLABEL, (caddr_t)&ifr) == -1) { 339 close(s); 340 return (-1); 341 } 342 close(s); 343 r->label = shim.shim_label; 344 return (0); 345 } 346