patch-2.4.26 linux-2.4.26/net/sctp/bind_addr.c

Next file: linux-2.4.26/net/sctp/chunk.c
Previous file: linux-2.4.26/net/sctp/associola.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.25/net/sctp/bind_addr.c linux-2.4.26/net/sctp/bind_addr.c
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2003
  * Copyright (c) Cisco 1999,2000
  * Copyright (c) Motorola 1999,2000,2001
- * Copyright (c) International Business Machines Corp., 2001,2002
  * Copyright (c) La Monte H.P. Yarroll 2001
  *
  * This file is part of the SCTP kernel reference implementation.
@@ -52,19 +52,20 @@
 #include <net/sctp/sm.h>
 
 /* Forward declarations for internal helpers. */
-static int sctp_copy_one_addr(sctp_bind_addr_t *, union sctp_addr *,
+static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *,
 			      sctp_scope_t scope, int gfp, int flags);
-static void sctp_bind_addr_clean(sctp_bind_addr_t *);
+static void sctp_bind_addr_clean(struct sctp_bind_addr *);
 
 /* First Level Abstractions. */
 
 /* Copy 'src' to 'dest' taking 'scope' into account.  Omit addresses
  * in 'src' which have a broader scope than 'scope'.
  */
-int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src,
+int sctp_bind_addr_copy(struct sctp_bind_addr *dest, 
+			const struct sctp_bind_addr *src,
 			sctp_scope_t scope, int gfp, int flags)
 {
-	struct sockaddr_storage_list *addr;
+	struct sctp_sockaddr_entry *addr;
 	struct list_head *pos;
 	int error = 0;
 
@@ -73,7 +74,7 @@
 
 	/* Extract the addresses which are relevant for this scope.  */
 	list_for_each(pos, &src->address_list) {
-		addr = list_entry(pos, struct sockaddr_storage_list, list);
+		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		error = sctp_copy_one_addr(dest, &addr->a, scope,
 					   gfp, flags);
 		if (error < 0)
@@ -86,7 +87,7 @@
 	 */
 	if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) {
 		list_for_each(pos, &src->address_list) {
-			addr = list_entry(pos, struct sockaddr_storage_list,
+			addr = list_entry(pos, struct sctp_sockaddr_entry,
 					  list);
 			error = sctp_copy_one_addr(dest, &addr->a,
 						   SCTP_SCOPE_LINK, gfp,
@@ -104,11 +105,11 @@
 }
 
 /* Create a new SCTP_bind_addr from nothing.  */
-sctp_bind_addr_t *sctp_bind_addr_new(int gfp)
+struct sctp_bind_addr *sctp_bind_addr_new(int gfp)
 {
-	sctp_bind_addr_t *retval;
+	struct sctp_bind_addr *retval;
 
-	retval = t_new(sctp_bind_addr_t, gfp);
+	retval = t_new(struct sctp_bind_addr, gfp);
 	if (!retval)
 		goto nomem;
 
@@ -123,7 +124,7 @@
 /* Initialize the SCTP_bind_addr structure for either an endpoint or
  * an association.
  */
-void sctp_bind_addr_init(sctp_bind_addr_t *bp, __u16 port)
+void sctp_bind_addr_init(struct sctp_bind_addr *bp, __u16 port)
 {
 	bp->malloced = 0;
 
@@ -132,14 +133,14 @@
 }
 
 /* Dispose of the address list. */
-static void sctp_bind_addr_clean(sctp_bind_addr_t *bp)
+static void sctp_bind_addr_clean(struct sctp_bind_addr *bp)
 {
-	struct sockaddr_storage_list *addr;
+	struct sctp_sockaddr_entry *addr;
 	struct list_head *pos, *temp;
 
 	/* Empty the bind address list. */
 	list_for_each_safe(pos, temp, &bp->address_list) {
-		addr = list_entry(pos, struct sockaddr_storage_list, list);
+		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		list_del(pos);
 		kfree(addr);
 		SCTP_DBG_OBJCNT_DEC(addr);
@@ -147,7 +148,7 @@
 }
 
 /* Dispose of an SCTP_bind_addr structure  */
-void sctp_bind_addr_free(sctp_bind_addr_t *bp)
+void sctp_bind_addr_free(struct sctp_bind_addr *bp)
 {
 	/* Empty the bind address list. */
 	sctp_bind_addr_clean(bp);
@@ -159,17 +160,17 @@
 }
 
 /* Add an address to the bind address list in the SCTP_bind_addr structure. */
-int sctp_add_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *new,
+int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
 		       int gfp)
 {
-	struct sockaddr_storage_list *addr;
+	struct sctp_sockaddr_entry *addr;
 
 	/* Add the address to the bind address list.  */
-	addr = t_new(struct sockaddr_storage_list, gfp);
+	addr = t_new(struct sctp_sockaddr_entry, gfp);
 	if (!addr)
 		return -ENOMEM;
 
-	addr->a = *new;
+	memcpy(&addr->a, new, sizeof(*new));
 
 	/* Fix up the port if it has not yet been set.
 	 * Both v4 and v6 have the port at the same offset.
@@ -187,13 +188,13 @@
 /* Delete an address from the bind address list in the SCTP_bind_addr
  * structure.
  */
-int sctp_del_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *del_addr)
+int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
 {
 	struct list_head *pos, *temp;
-	struct sockaddr_storage_list *addr;
+	struct sctp_sockaddr_entry *addr;
 
 	list_for_each_safe(pos, temp, &bp->address_list) {
-		addr = list_entry(pos, struct sockaddr_storage_list, list);
+		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		if (sctp_cmp_addr_exact(&addr->a, del_addr)) {
 			/* Found the exact match. */
 			list_del(pos);
@@ -212,28 +213,30 @@
  *
  * The second argument is the return value for the length.
  */
-union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp,
+union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
 					 int *addrs_len, int gfp)
 {
 	union sctp_params addrparms;
 	union sctp_params retval;
 	int addrparms_len;
-	sctp_addr_param_t rawaddr;
+	union sctp_addr_param rawaddr;
 	int len;
-	struct sockaddr_storage_list *addr;
+	struct sctp_sockaddr_entry *addr;
 	struct list_head *pos;
+	struct sctp_af *af;
+
 	addrparms_len = 0;
 	len = 0;
 
 	/* Allocate enough memory at once. */
 	list_for_each(pos, &bp->address_list) {
-		len += sizeof(sctp_addr_param_t);
+		len += sizeof(union sctp_addr_param);
 	}
 
 	/* Don't even bother embedding an address if there
 	 * is only one.
 	 */
-	if (len == sizeof(sctp_addr_param_t)) {
+	if (len == sizeof(union sctp_addr_param)) {
 		retval.v = NULL;
 		goto end_raw;
 	}
@@ -245,8 +248,9 @@
 	addrparms = retval;
 
 	list_for_each(pos, &bp->address_list) {
-		addr = list_entry(pos, struct sockaddr_storage_list, list);
-		len = sockaddr2sctp_addr(&addr->a, &rawaddr);
+		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
+		af = sctp_get_af_specific(addr->a.v4.sin_family);
+		len = af->to_addr_param(&addr->a, &rawaddr);
 		memcpy(addrparms.v, &rawaddr, len);
 		addrparms.v += len;
 		addrparms_len += len;
@@ -261,42 +265,39 @@
  * Create an address list out of the raw address list format (IPv4 and IPv6
  * address parameters).
  */
-int sctp_raw_to_bind_addrs(sctp_bind_addr_t *bp, __u8 *raw_addr_list,
+int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
 			   int addrs_len, __u16 port, int gfp)
 {
-	sctp_addr_param_t *rawaddr;
-	sctp_paramhdr_t *param;
+	union sctp_addr_param *rawaddr;
+	struct sctp_paramhdr *param;
 	union sctp_addr addr;
 	int retval = 0;
 	int len;
+	struct sctp_af *af;
 
 	/* Convert the raw address to standard address format */
 	while (addrs_len) {
-		param = (sctp_paramhdr_t *)raw_addr_list;
-		rawaddr = (sctp_addr_param_t *)raw_addr_list;
+		param = (struct sctp_paramhdr *)raw_addr_list;
+		rawaddr = (union sctp_addr_param *)raw_addr_list;
 
-		switch (param->type) {
-		case SCTP_PARAM_IPV4_ADDRESS:
-		case SCTP_PARAM_IPV6_ADDRESS:
-			sctp_param2sockaddr(&addr, rawaddr, port, 0);
-			retval = sctp_add_bind_addr(bp, &addr, gfp);
-			if (retval) {
-				/* Can't finish building the list, clean up. */
-				sctp_bind_addr_clean(bp);
-				break;;
-			}
-			len = ntohs(param->length);
-			addrs_len -= len;
-			raw_addr_list += len;
-			break;
-		default:
-			/* Corrupted raw addr list! */
+		af = sctp_get_af_specific(param_type2af(param->type));
+		if (unlikely(!af)) {
 			retval = -EINVAL;
 			sctp_bind_addr_clean(bp);
 			break;
 		}
-		if (retval)
-			break;
+
+		af->from_addr_param(&addr, rawaddr, port, 0);
+		retval = sctp_add_bind_addr(bp, &addr, gfp);
+		if (retval) {
+			/* Can't finish building the list, clean up. */
+			sctp_bind_addr_clean(bp);
+			break;;
+		}
+
+		len = ntohs(param->length);
+		addrs_len -= len;
+		raw_addr_list += len;
 	}
 
 	return retval;
@@ -307,14 +308,15 @@
  ********************************************************************/
 
 /* Does this contain a specified address?  Allow wildcarding. */
-int sctp_bind_addr_match(sctp_bind_addr_t *bp, const union sctp_addr *addr,
+int sctp_bind_addr_match(struct sctp_bind_addr *bp, 
+			 const union sctp_addr *addr,
 			 struct sctp_opt *opt)
 {
-	struct sockaddr_storage_list *laddr;
+	struct sctp_sockaddr_entry *laddr;
 	struct list_head *pos;
 
 	list_for_each(pos, &bp->address_list) {
-		laddr = list_entry(pos, struct sockaddr_storage_list, list);
+		laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		if (opt->pf->cmp_addr(&laddr->a, addr, opt))
  			return 1;
 	}
@@ -322,16 +324,52 @@
 	return 0;
 }
 
+/* Find the first address in the bind address list that is not present in
+ * the addrs packed array.
+ */
+union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr	*bp,
+					const union sctp_addr	*addrs,
+					int			addrcnt,
+					struct sctp_opt		*opt)
+{
+	struct sctp_sockaddr_entry	*laddr;
+	union sctp_addr			*addr;
+	void 				*addr_buf;
+	struct sctp_af			*af;
+	struct list_head		*pos;
+	int				i;
+
+	list_for_each(pos, &bp->address_list) {
+		laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
+		
+		addr_buf = (union sctp_addr *)addrs;
+		for (i = 0; i < addrcnt; i++) {
+			addr = (union sctp_addr *)addr_buf;
+			af = sctp_get_af_specific(addr->v4.sin_family);
+			if (!af) 
+				return NULL;
+
+			if (opt->pf->cmp_addr(&laddr->a, addr, opt))
+				break;
+
+			addr_buf += af->sockaddr_len;
+		}
+		if (i == addrcnt)
+			return &laddr->a;
+	}
+
+	return NULL;
+}
+
 /* Copy out addresses from the global local address list. */
-static int sctp_copy_one_addr(sctp_bind_addr_t *dest, union sctp_addr *addr,
+static int sctp_copy_one_addr(struct sctp_bind_addr *dest, 
+			      union sctp_addr *addr,
 			      sctp_scope_t scope, int gfp, int flags)
 {
-	struct sctp_protocol *proto = sctp_get_protocol();
 	int error = 0;
 
 	if (sctp_is_any(addr)) {
-		error = sctp_copy_local_addr_list(proto, dest, scope,
-						  gfp, flags);
+		error = sctp_copy_local_addr_list(dest, scope, gfp, flags);
 	} else if (sctp_in_scope(addr, scope)) {
 		/* Now that the address is in scope, check to see if
 		 * the address type is supported by local sock as

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)