1 /* $OpenBSD: config.c,v 1.56 2010/10/24 17:20:08 deraadt 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 free(xconf->csock); 69 free(xconf->rcsock); 70 71 conf->listen_addrs = xconf->listen_addrs; 72 memcpy(xconf, conf, sizeof(struct bgpd_config)); 73 74 if (conf->listen_addrs == NULL) { 75 /* there is no old conf, just copy new one over */ 76 xconf->listen_addrs = listen_addrs; 77 TAILQ_FOREACH(nla, xconf->listen_addrs, entry) 78 nla->reconf = RECONF_REINIT; 79 80 } else { 81 /* 82 * merge new listeners: 83 * -flag all existing ones as to be deleted 84 * -those that are in both new and old: flag to keep 85 * -new ones get inserted and flagged as to reinit 86 * -remove all that are still flagged for deletion 87 */ 88 89 TAILQ_FOREACH(nla, xconf->listen_addrs, entry) 90 nla->reconf = RECONF_DELETE; 91 92 /* no new listeners? preserve default ones */ 93 if (TAILQ_EMPTY(listen_addrs)) 94 TAILQ_FOREACH(ola, xconf->listen_addrs, entry) 95 if (ola->flags & DEFAULT_LISTENER) 96 ola->reconf = RECONF_KEEP; 97 98 for (nla = TAILQ_FIRST(listen_addrs); nla != NULL; nla = next) { 99 next = TAILQ_NEXT(nla, entry); 100 101 TAILQ_FOREACH(ola, xconf->listen_addrs, entry) 102 if (!memcmp(&nla->sa, &ola->sa, 103 sizeof(nla->sa))) 104 break; 105 106 if (ola == NULL) { 107 /* new listener, copy over */ 108 TAILQ_REMOVE(listen_addrs, nla, entry); 109 TAILQ_INSERT_TAIL(xconf->listen_addrs, 110 nla, entry); 111 nla->reconf = RECONF_REINIT; 112 } else /* exists, just flag */ 113 ola->reconf = RECONF_KEEP; 114 } 115 116 for (nla = TAILQ_FIRST(xconf->listen_addrs); nla != NULL; 117 nla = next) { 118 next = TAILQ_NEXT(nla, entry); 119 if (nla->reconf == RECONF_DELETE) { 120 TAILQ_REMOVE(xconf->listen_addrs, nla, entry); 121 free(nla); 122 } 123 } 124 125 while ((ola = TAILQ_FIRST(listen_addrs)) != NULL) { 126 TAILQ_REMOVE(listen_addrs, ola, entry); 127 free(ola); 128 } 129 free(listen_addrs); 130 } 131 132 return (0); 133 } 134 135 u_int32_t 136 get_bgpid(void) 137 { 138 struct ifaddrs *ifap, *ifa; 139 u_int32_t ip = 0, cur, localnet; 140 141 localnet = htonl(INADDR_LOOPBACK & IN_CLASSA_NET); 142 143 if (getifaddrs(&ifap) == -1) 144 fatal("getifaddrs"); 145 146 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 147 if (ifa->ifa_addr->sa_family != AF_INET) 148 continue; 149 cur = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; 150 if ((cur & localnet) == localnet) /* skip 127/8 */ 151 continue; 152 if (ntohl(cur) > ntohl(ip)) 153 ip = cur; 154 } 155 freeifaddrs(ifap); 156 157 return (ip); 158 } 159 160 int 161 host(const char *s, struct bgpd_addr *h, u_int8_t *len) 162 { 163 int done = 0; 164 int mask; 165 char *p, *ps; 166 const char *errstr; 167 168 if ((p = strrchr(s, '/')) != NULL) { 169 mask = strtonum(p + 1, 0, 128, &errstr); 170 if (errstr) { 171 log_warnx("prefixlen is %s: %s", errstr, p + 1); 172 return (0); 173 } 174 if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) 175 fatal("host: malloc"); 176 strlcpy(ps, s, strlen(s) - strlen(p) + 1); 177 } else { 178 if ((ps = strdup(s)) == NULL) 179 fatal("host: strdup"); 180 mask = 128; 181 } 182 183 bzero(h, sizeof(struct bgpd_addr)); 184 185 /* IPv4 address? */ 186 if (!done) 187 done = host_v4(s, h, len); 188 189 /* IPv6 address? */ 190 if (!done) { 191 done = host_v6(ps, h); 192 *len = mask; 193 } 194 195 free(ps); 196 197 return (done); 198 } 199 200 int 201 host_v4(const char *s, struct bgpd_addr *h, u_int8_t *len) 202 { 203 struct in_addr ina; 204 int bits = 32; 205 206 bzero(&ina, sizeof(struct in_addr)); 207 if (strrchr(s, '/') != NULL) { 208 if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1) 209 return (0); 210 } else { 211 if (inet_pton(AF_INET, s, &ina) != 1) 212 return (0); 213 } 214 215 h->aid = AID_INET; 216 h->v4.s_addr = ina.s_addr; 217 *len = bits; 218 219 return (1); 220 } 221 222 int 223 host_v6(const char *s, struct bgpd_addr *h) 224 { 225 struct addrinfo hints, *res; 226 227 bzero(&hints, sizeof(hints)); 228 hints.ai_family = AF_INET6; 229 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 230 hints.ai_flags = AI_NUMERICHOST; 231 if (getaddrinfo(s, "0", &hints, &res) == 0) { 232 sa2addr(res->ai_addr, h); 233 freeaddrinfo(res); 234 return (1); 235 } 236 237 return (0); 238 } 239 240 void 241 prepare_listeners(struct bgpd_config *conf) 242 { 243 struct listen_addr *la, *next; 244 int opt = 1; 245 246 if (TAILQ_EMPTY(conf->listen_addrs)) { 247 if ((la = calloc(1, sizeof(struct listen_addr))) == NULL) 248 fatal("setup_listeners calloc"); 249 la->fd = -1; 250 la->flags = DEFAULT_LISTENER; 251 la->reconf = RECONF_REINIT; 252 la->sa.ss_len = sizeof(struct sockaddr_in); 253 ((struct sockaddr_in *)&la->sa)->sin_family = AF_INET; 254 ((struct sockaddr_in *)&la->sa)->sin_addr.s_addr = 255 htonl(INADDR_ANY); 256 ((struct sockaddr_in *)&la->sa)->sin_port = htons(BGP_PORT); 257 TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry); 258 259 if ((la = calloc(1, sizeof(struct listen_addr))) == NULL) 260 fatal("setup_listeners calloc"); 261 la->fd = -1; 262 la->flags = DEFAULT_LISTENER; 263 la->reconf = RECONF_REINIT; 264 la->sa.ss_len = sizeof(struct sockaddr_in6); 265 ((struct sockaddr_in6 *)&la->sa)->sin6_family = AF_INET6; 266 ((struct sockaddr_in6 *)&la->sa)->sin6_port = htons(BGP_PORT); 267 TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry); 268 } 269 270 for (la = TAILQ_FIRST(conf->listen_addrs); la != NULL; la = next) { 271 next = TAILQ_NEXT(la, entry); 272 if (la->reconf != RECONF_REINIT) 273 continue; 274 275 if ((la->fd = socket(la->sa.ss_family, SOCK_STREAM, 276 IPPROTO_TCP)) == -1) { 277 if (la->flags & DEFAULT_LISTENER && (errno == 278 EAFNOSUPPORT || errno == EPROTONOSUPPORT)) { 279 TAILQ_REMOVE(conf->listen_addrs, la, entry); 280 free(la); 281 continue; 282 } else 283 fatal("socket"); 284 } 285 286 opt = 1; 287 if (setsockopt(la->fd, SOL_SOCKET, SO_REUSEADDR, 288 &opt, sizeof(opt)) == -1) 289 fatal("setsockopt SO_REUSEADDR"); 290 291 if (bind(la->fd, (struct sockaddr *)&la->sa, la->sa.ss_len) == 292 -1) { 293 switch (la->sa.ss_family) { 294 case AF_INET: 295 log_warn("cannot bind to %s:%u", 296 log_sockaddr((struct sockaddr *)&la->sa), 297 ntohs(((struct sockaddr_in *) 298 &la->sa)->sin_port)); 299 break; 300 case AF_INET6: 301 log_warn("cannot bind to [%s]:%u", 302 log_sockaddr((struct sockaddr *)&la->sa), 303 ntohs(((struct sockaddr_in6 *) 304 &la->sa)->sin6_port)); 305 break; 306 default: 307 log_warn("cannot bind to %s", 308 log_sockaddr((struct sockaddr *)&la->sa)); 309 break; 310 } 311 close(la->fd); 312 TAILQ_REMOVE(conf->listen_addrs, la, entry); 313 free(la); 314 continue; 315 } 316 } 317 } 318 319 int 320 get_mpe_label(struct rdomain *r) 321 { 322 struct ifreq ifr; 323 struct shim_hdr shim; 324 int s; 325 326 s = socket(AF_INET, SOCK_DGRAM, 0); 327 if (s == -1) 328 return (-1); 329 330 bzero(&shim, sizeof(shim)); 331 bzero(&ifr, sizeof(ifr)); 332 strlcpy(ifr.ifr_name, r->ifmpe, sizeof(ifr.ifr_name)); 333 ifr.ifr_data = (caddr_t)&shim; 334 335 if (ioctl(s, SIOCGETLABEL, (caddr_t)&ifr) == -1) { 336 close(s); 337 return (-1); 338 } 339 close(s); 340 r->label = shim.shim_label; 341 return (0); 342 } 343