diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2009-12-01 14:28:06 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2009-12-01 14:28:06 +0000 |
commit | d34d8813c5fa9b8031432c45c008b3a7a0d97441 (patch) | |
tree | 55c9c7d433f909d1af59bc9e1671cee07a80c7c3 /usr.sbin/bgpd/session.c | |
parent | d2eb742e2cf480aa441fc39d7cec70b5c3e71ca6 (diff) |
Use an artificial address family id in struct bgpd_addr and almost everywhere
else. Adds conversion functions to map AFI/SAFI and the Unix AF_ values
from and into AID used in bgpd. This is needed to support things like MPLS
VPN and other upcomming changes that need to play a lot with AFI/SAFI pairs.
Mostly mechanical change, henning@ has no particular issues with this.
Must go in so that I can continue working.
Diffstat (limited to 'usr.sbin/bgpd/session.c')
-rw-r--r-- | usr.sbin/bgpd/session.c | 218 |
1 files changed, 71 insertions, 147 deletions
diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c index 3ed0195cfcf..f1f2b7faef9 100644 --- a/usr.sbin/bgpd/session.c +++ b/usr.sbin/bgpd/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.299 2009/10/26 09:27:58 claudio Exp $ */ +/* $OpenBSD: session.c,v 1.300 2009/12/01 14:28:05 claudio Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> @@ -87,11 +87,10 @@ void session_up(struct peer *); void session_down(struct peer *); void session_demote(struct peer *, int); -int la_cmp(struct listen_addr *, struct listen_addr *); -struct peer *getpeerbyip(struct sockaddr *); -int session_match_mask(struct peer *, struct sockaddr *); -struct peer *getpeerbyid(u_int32_t); -static struct sockaddr *addr2sa(struct bgpd_addr *, u_int16_t); +int la_cmp(struct listen_addr *, struct listen_addr *); +struct peer *getpeerbyip(struct sockaddr *); +int session_match_mask(struct peer *, struct bgpd_addr *); +struct peer *getpeerbyid(u_int32_t); struct bgpd_config *conf, *nconf = NULL; struct bgpd_sysdep sysdep; @@ -1073,7 +1072,7 @@ session_connect(struct peer *peer) if (peer->fd != -1) return (-1); - if ((peer->fd = socket(peer->conf.remote_addr.af, SOCK_STREAM, + if ((peer->fd = socket(aid2af(peer->conf.remote_addr.aid), SOCK_STREAM, IPPROTO_TCP)) == -1) { log_peer_warn(&peer->conf, "session_connect socket"); bgp_fsm(peer, EVNT_CON_OPENFAIL); @@ -1104,8 +1103,7 @@ session_connect(struct peer *peer) peer->wbuf.fd = peer->fd; /* if update source is set we need to bind() */ - if (peer->conf.local_addr.af) { - sa = addr2sa(&peer->conf.local_addr, 0); + if ((sa = addr2sa(&peer->conf.local_addr, 0)) != NULL) { if (bind(peer->fd, sa, sa->sa_len) == -1) { log_peer_warn(&peer->conf, "session_connect bind"); bgp_fsm(peer, EVNT_CON_OPENFAIL); @@ -1143,42 +1141,50 @@ session_setup_socket(struct peer *p) int nodelay = 1; int bsize; - if (p->conf.ebgp && p->conf.remote_addr.af == AF_INET) { - /* set TTL to foreign router's distance - 1=direct n=multihop - with ttlsec, we always use 255 */ - if (p->conf.ttlsec) { - ttl = 256 - p->conf.distance; - if (setsockopt(p->fd, IPPROTO_IP, IP_MINTTL, &ttl, + switch (p->conf.remote_addr.aid) { + case AID_INET: + /* set precedence, see RFC 1771 appendix 5 */ + if (setsockopt(p->fd, IPPROTO_IP, IP_TOS, &pre, sizeof(pre)) == + -1) { + log_peer_warn(&p->conf, + "session_setup_socket setsockopt TOS"); + return (-1); + } + + if (p->conf.ebgp) { + /* set TTL to foreign router's distance + 1=direct n=multihop with ttlsec, we always use 255 */ + if (p->conf.ttlsec) { + ttl = 256 - p->conf.distance; + if (setsockopt(p->fd, IPPROTO_IP, IP_MINTTL, + &ttl, sizeof(ttl)) == -1) { + log_peer_warn(&p->conf, + "session_setup_socket: " + "setsockopt MINTTL"); + return (-1); + } + ttl = 255; + } + + if (setsockopt(p->fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) == -1) { log_peer_warn(&p->conf, - "session_setup_socket setsockopt MINTTL"); + "session_setup_socket setsockopt TTL"); return (-1); } - ttl = 255; } - - if (setsockopt(p->fd, IPPROTO_IP, IP_TTL, &ttl, - sizeof(ttl)) == -1) { - log_peer_warn(&p->conf, - "session_setup_socket setsockopt TTL"); - return (-1); - } - } - - if (p->conf.ebgp && p->conf.remote_addr.af == AF_INET6) - /* set hoplimit to foreign router's distance */ - if (setsockopt(p->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, - sizeof(ttl)) == -1) { - log_peer_warn(&p->conf, - "session_setup_socket setsockopt hoplimit"); - return (-1); + break; + case AID_INET6: + if (p->conf.ebgp) { + /* set hoplimit to foreign router's distance */ + if (setsockopt(p->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, + &ttl, sizeof(ttl)) == -1) { + log_peer_warn(&p->conf, + "session_setup_socket setsockopt hoplimit"); + return (-1); + } } - - /* if ttlsec is in use, set minttl */ - if (p->conf.ttlsec) { - ttl = 256 - p->conf.distance; - setsockopt(p->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)); - + break; } /* set TCP_NODELAY */ @@ -1189,14 +1195,6 @@ session_setup_socket(struct peer *p) return (-1); } - /* set precedence, see RFC 1771 appendix 5 */ - if (p->conf.remote_addr.af == AF_INET && - setsockopt(p->fd, IPPROTO_IP, IP_TOS, &pre, sizeof(pre)) == -1) { - log_peer_warn(&p->conf, - "session_setup_socket setsockopt TOS"); - return (-1); - } - /* only increase bufsize (and thus window) if md5 or ipsec is in use */ if (p->conf.auth.method != AUTH_NONE) { /* try to increase bufsize. no biggie if it fails */ @@ -2619,29 +2617,23 @@ getpeerbydesc(const char *descr) struct peer * getpeerbyip(struct sockaddr *ip) { + struct bgpd_addr addr; struct peer *p, *newpeer, *loose = NULL; u_int32_t id; + sa2addr(ip, &addr); + /* we might want a more effective way to find peers by IP */ for (p = peers; p != NULL; p = p->next) if (!p->conf.template && - p->conf.remote_addr.af == ip->sa_family) { - if (p->conf.remote_addr.af == AF_INET && - p->conf.remote_addr.v4.s_addr == - ((struct sockaddr_in *)ip)->sin_addr.s_addr) - return (p); - if (p->conf.remote_addr.af == AF_INET6 && - !bcmp(&p->conf.remote_addr.v6, - &((struct sockaddr_in6 *)ip)->sin6_addr, - sizeof(p->conf.remote_addr.v6))) - return (p); - } + !memcmp(&addr, &p->conf.remote_addr, sizeof(addr))) + return (p); /* try template matching */ for (p = peers; p != NULL; p = p->next) if (p->conf.template && - p->conf.remote_addr.af == ip->sa_family && - session_match_mask(p, ip)) + p->conf.remote_addr.aid == addr.aid && + session_match_mask(p, &addr)) if (loose == NULL || loose->conf.remote_masklen < p->conf.remote_masklen) loose = p; @@ -2660,16 +2652,14 @@ getpeerbyip(struct sockaddr *ip) break; } } - if (newpeer->conf.remote_addr.af == AF_INET) { - newpeer->conf.remote_addr.v4.s_addr = - ((struct sockaddr_in *)ip)->sin_addr.s_addr; + sa2addr(ip, &newpeer->conf.remote_addr); + switch (ip->sa_family) { + case AF_INET: newpeer->conf.remote_masklen = 32; - } - if (newpeer->conf.remote_addr.af == AF_INET6) { - memcpy(&newpeer->conf.remote_addr.v6, - &((struct sockaddr_in6 *)ip)->sin6_addr, - sizeof(newpeer->conf.remote_addr.v6)); + break; + case AF_INET6: newpeer->conf.remote_masklen = 128; + break; } newpeer->conf.template = 0; newpeer->conf.cloned = 1; @@ -2687,40 +2677,24 @@ getpeerbyip(struct sockaddr *ip) } int -session_match_mask(struct peer *p, struct sockaddr *ip) +session_match_mask(struct peer *p, struct bgpd_addr *a) { - int i; in_addr_t v4mask; - struct in6_addr *in; - struct in6_addr mask; + struct in6_addr masked; - if (p->conf.remote_addr.af == AF_INET) { + switch (p->conf.remote_addr.aid) { + case AID_INET: v4mask = htonl(prefixlen2mask(p->conf.remote_masklen)); - if (p->conf.remote_addr.v4.s_addr == - ((((struct sockaddr_in *)ip)->sin_addr.s_addr) & v4mask)) + if (p->conf.remote_addr.v4.s_addr == (a->v4.s_addr & v4mask)) return (1); - else - return (0); - } - - if (p->conf.remote_addr.af == AF_INET6) { - bzero(&mask, sizeof(mask)); - for (i = 0; i < p->conf.remote_masklen / 8; i++) - mask.s6_addr[i] = 0xff; - i = p->conf.remote_masklen % 8; - if (i) - mask.s6_addr[p->conf.remote_masklen / 8] = 0xff00 >> i; - - in = &((struct sockaddr_in6 *)ip)->sin6_addr; - - for (i = 0; i < 16; i++) - if ((in->s6_addr[i] & mask.s6_addr[i]) != - p->conf.remote_addr.addr8[i]) - return (0); + return (0); + case AID_INET6: + inet6applymask(&masked, &a->v6, p->conf.remote_masklen); - return (1); + if (!memcmp(&masked, &p->conf.remote_addr.v6, sizeof(masked))) + return (1); + return (0); } - return (0); } @@ -2755,30 +2729,8 @@ session_up(struct peer *p) &p->conf, sizeof(p->conf)) == -1) fatalx("imsg_compose error"); - switch (p->sa_local.ss_family) { - case AF_INET: - sup.local_addr.af = AF_INET; - memcpy(&sup.local_addr.v4, - &((struct sockaddr_in *)&p->sa_local)->sin_addr, - sizeof(sup.local_addr.v4)); - sup.remote_addr.af = AF_INET; - memcpy(&sup.remote_addr.v4, - &((struct sockaddr_in *)&p->sa_remote)->sin_addr, - sizeof(sup.remote_addr.v4)); - break; - case AF_INET6: - sup.local_addr.af = AF_INET6; - memcpy(&sup.local_addr.v6, - &((struct sockaddr_in6 *)&p->sa_local)->sin6_addr, - sizeof(sup.local_addr.v6)); - sup.remote_addr.af = AF_INET6; - memcpy(&sup.remote_addr.v6, - &((struct sockaddr_in6 *)&p->sa_remote)->sin6_addr, - sizeof(sup.remote_addr.v6)); - break; - default: - fatalx("session_up: unsupported address family"); - } + sa2addr((struct sockaddr *)&p->sa_local, &sup.local_addr); + sa2addr((struct sockaddr *)&p->sa_remote, &sup.remote_addr); sup.remote_bgpid = p->remote_bgpid; sup.short_as = p->short_as; @@ -2802,34 +2754,6 @@ imsg_compose_rde(int type, pid_t pid, void *data, u_int16_t datalen) return (imsg_compose(ibuf_rde, type, 0, pid, -1, data, datalen)); } -static struct sockaddr * -addr2sa(struct bgpd_addr *addr, u_int16_t port) -{ - static struct sockaddr_storage ss; - struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss; - struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss; - - bzero(&ss, sizeof(ss)); - switch (addr->af) { - case AF_INET: - sa_in->sin_family = AF_INET; - sa_in->sin_len = sizeof(struct sockaddr_in); - sa_in->sin_addr.s_addr = addr->v4.s_addr; - sa_in->sin_port = htons(port); - break; - case AF_INET6: - sa_in6->sin6_family = AF_INET6; - sa_in6->sin6_len = sizeof(struct sockaddr_in6); - memcpy(&sa_in6->sin6_addr, &addr->v6, - sizeof(sa_in6->sin6_addr)); - sa_in6->sin6_port = htons(port); - sa_in6->sin6_scope_id = addr->scope_id; - break; - } - - return ((struct sockaddr *)&ss); -} - void session_demote(struct peer *p, int level) { |