--- ./bgpd/session.c.dist	Wed Jan 10 08:56:49 2007
+++ ./bgpd/session.c	Tue Jan  9 20:40:12 2007
@@ -67,6 +67,7 @@
 u_int8_t	 session_capa_add(struct peer *, struct buf *, u_int8_t,
 		    u_int8_t);
 int	session_capa_add_mp(struct buf *, u_int16_t, u_int8_t);
+int     session_capa_add_as_4bytes(struct buf *, u_int32_t) ;  
 struct bgp_msg	*session_newmsg(enum msg_type, u_int16_t);
 int	session_sendmsg(struct bgp_msg *, struct peer *);
 void	session_open(struct peer *);
@@ -1193,6 +1194,7 @@
 	peer->capa.ann.mp_v4 = SAFI_NONE;
 	peer->capa.ann.refresh = 0;
 	peer->capa.ann.restart = 0;
+        peer->capa.ann.as_4bytes = 0 ;
 }
 
 u_int8_t
@@ -1230,6 +1232,16 @@
 	return (errs);
 }
 
+int
+session_capa_add_as_4bytes(struct buf *buf, u_int32_t myas)
+{
+        int                      errs = 0;
+ 
+        myas = htonl(myas) ;
+        errs += buf_add(buf, &myas, sizeof(myas));
+        return (errs);
+}
+
 struct bgp_msg *
 session_newmsg(enum msg_type msgtype, u_int16_t len)
 {
@@ -1297,6 +1309,7 @@
 	u_int16_t		 len;
 	u_int8_t		 optparamlen = 0, op_len;
 	u_int			 errs = 0;
+        u_int16_t                short_as;
 
 
 	if ((opb = buf_open(0)) == NULL) {
@@ -1324,6 +1337,15 @@
 		}
 	}
 
+	if (p->capa.ann.as_4bytes) {	/* 4 bytes AS capability */
+		if ((op_len = session_capa_add(p, opb, CAPA_4AS, 4)) == 0)
+			errs++;
+		else {
+			optparamlen += op_len;
+			errs += session_capa_add_as_4bytes(opb, conf->as);
+		}
+	}
+
 
 	/* route refresh, RFC 2918 */
 	if (p->capa.ann.refresh) {	/* no data */
@@ -1361,7 +1383,10 @@
 	}	
 
 	msg.version = 4;
-	msg.myas = htons(conf->as);
+        if (!((conf->as >> 16) & 65535)) 
+                short_as = (u_int16_t) conf->as;
+        else short_as = AS_TRANS ;
+        msg.myas = htons(short_as);
 	if (p->conf.holdtime)
 		msg.holdtime = htons(p->conf.holdtime);
 	else
@@ -1794,7 +1819,9 @@
 	u_int32_t	 bgpid;
 	u_int8_t	 optparamlen, plen;
 	u_int8_t	 op_type, op_len;
+        int              error_code;
 
+        peer->capa.peer.as_4bytes = 0;
 	p = peer->rbuf->rptr;
 	p += MSGSIZE_HEADER_MARKER;
 	memcpy(&msglen, p, sizeof(msglen));
@@ -1828,13 +1855,6 @@
 		peer->conf.ebgp = (peer->conf.remote_as != conf->as);
 	}
 
-	if (peer->conf.remote_as != ntohs(as)) {
-		log_peer_warnx(&peer->conf, "peer sent wrong AS %u", ntohs(as));
-		session_notification(peer, ERR_OPEN, ERR_OPEN_AS, NULL, 0);
-		change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN);
-		return (-1);
-	}
-
 	memcpy(&oholdtime, p, sizeof(oholdtime));
 	p += sizeof(oholdtime);
 
@@ -1913,8 +1933,9 @@
 
 		switch (op_type) {
 		case OPT_PARAM_CAPABILITIES:		/* RFC 3392 */
-			if (parse_capabilities(peer, op_val, op_len) == -1) {
-				session_notification(peer, ERR_OPEN, 0,
+		        if ((error_code = parse_capabilities(peer, op_val, op_len)) < 0) {
+   		                error_code = -1 - error_code;
+				session_notification(peer, ERR_OPEN, error_code,
 				    NULL, 0);
 				change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN);
 				return (-1);
@@ -1941,6 +1962,13 @@
 		}
 	}
 
+        if ((peer->conf.remote_as != ntohs(as)) && (!peer->capa.peer.as_4bytes)) {
+                log_peer_warnx(&peer->conf, "peer sent wrong AS %u", ntohs(as));
+                session_notification(peer, ERR_OPEN, ERR_OPEN_AS, NULL, 0);
+                change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN);
+                return (-1);
+        }
+
 	return (0);
 }
 
@@ -2107,6 +2135,7 @@
 	u_char		*capa_val;
 	u_int16_t	 mp_afi;
 	u_int8_t	 mp_safi;
+        u_int32_t        remote_as;
 
 	len = dlen;
 	while (len > 0) {
@@ -2136,6 +2165,22 @@
 			capa_val = NULL;
 
 		switch (capa_code) {
+                case CAPA_4AS:
+                        if (capa_len != 4) {
+                                log_peer_warnx(&peer->conf,
+                                    "parse_capabilities: "
+                                    "expect len 4, len is %u", capa_len);
+                                return (-1);
+                        }
+                        memcpy(&remote_as, capa_val, sizeof(remote_as));
+                        remote_as = ntohl(remote_as);
+                        peer->capa.peer.as_4bytes = 1 ;
+                        if (peer->conf.remote_as != remote_as) {
+                                log_peer_warnx(&peer->conf, "peer sent wrong AS %u.%u", 
+					       ((remote_as >> 16) & 65535),(remote_as & 65535));
+                                return (0 - (ERR_OPEN_AS + 1));
+                        }
+                        break ;
 		case CAPA_MP:			/* RFC 2858 */
 			if (capa_len != 4) {
 				log_peer_warnx(&peer->conf,
