Commit c09d36c8 authored by David S. Miller's avatar David S. Miller

Merge http://linux-lksctp.bkbits.net/lksctp-2.5

into nuts.ninka.net:/home/davem/src/BK/sctp-2.5
parents 1d02c2c0 9bb68814
...@@ -588,6 +588,7 @@ struct sctp6_sock { ...@@ -588,6 +588,7 @@ struct sctp6_sock {
#endif /* CONFIG_IPV6 */ #endif /* CONFIG_IPV6 */
#define sctp_sk(__sk) (&((struct sctp_sock *)__sk)->sctp) #define sctp_sk(__sk) (&((struct sctp_sock *)__sk)->sctp)
#define sctp_opt2sk(__sp) &container_of(__sp, struct sctp_sock, sctp)->sk
/* Is a socket of this style? */ /* Is a socket of this style? */
#define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style)) #define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style))
...@@ -611,4 +612,23 @@ int static inline __sctp_sstate(const struct sock *sk, sctp_sock_state_t state) ...@@ -611,4 +612,23 @@ int static inline __sctp_sstate(const struct sock *sk, sctp_sock_state_t state)
return sk->sk_state == state; return sk->sk_state == state;
} }
/* Map v4-mapped v6 address back to v4 address */
static inline void sctp_v6_map_v4(union sctp_addr *addr)
{
addr->v4.sin_family = AF_INET;
addr->v4.sin_port = addr->v6.sin6_port;
addr->v4.sin_addr.s_addr = addr->v6.sin6_addr.s6_addr32[3];
}
/* Map v4 address to v4-mapped v6 address */
static inline void sctp_v4_map_v6(union sctp_addr *addr)
{
addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_port = addr->v4.sin_port;
addr->v6.sin6_addr.s6_addr32[3] = addr->v4.sin_addr.s_addr;
addr->v6.sin6_addr.s6_addr32[0] = 0;
addr->v6.sin6_addr.s6_addr32[1] = 0;
addr->v6.sin6_addr.s6_addr32[2] = htonl(0x0000ffff);
}
#endif /* __net_sctp_h__ */ #endif /* __net_sctp_h__ */
...@@ -231,7 +231,8 @@ struct sctp_chunk *sctp_make_data_empty(struct sctp_association *, ...@@ -231,7 +231,8 @@ struct sctp_chunk *sctp_make_data_empty(struct sctp_association *,
struct sctp_chunk *sctp_make_ecne(const struct sctp_association *, struct sctp_chunk *sctp_make_ecne(const struct sctp_association *,
const __u32); const __u32);
struct sctp_chunk *sctp_make_sack(const struct sctp_association *); struct sctp_chunk *sctp_make_sack(const struct sctp_association *);
struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc); struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc,
const struct sctp_chunk *chunk);
struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc, struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc,
const struct sctp_chunk *); const struct sctp_chunk *);
struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *, struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *,
......
...@@ -260,11 +260,13 @@ struct sctp_af { ...@@ -260,11 +260,13 @@ struct sctp_af {
struct sock *sk); struct sock *sk);
void (*to_sk_daddr) (union sctp_addr *, void (*to_sk_daddr) (union sctp_addr *,
struct sock *sk); struct sock *sk);
int (*addr_valid) (union sctp_addr *); int (*addr_valid) (union sctp_addr *,
struct sctp_opt *);
sctp_scope_t (*scope) (union sctp_addr *); sctp_scope_t (*scope) (union sctp_addr *);
void (*inaddr_any) (union sctp_addr *, unsigned short); void (*inaddr_any) (union sctp_addr *, unsigned short);
int (*is_any) (const union sctp_addr *); int (*is_any) (const union sctp_addr *);
int (*available) (const union sctp_addr *); int (*available) (union sctp_addr *,
struct sctp_opt *);
int (*skb_iif) (const struct sk_buff *sk); int (*skb_iif) (const struct sk_buff *sk);
int (*is_ce) (const struct sk_buff *sk); int (*is_ce) (const struct sk_buff *sk);
void (*seq_dump_addr)(struct seq_file *seq, void (*seq_dump_addr)(struct seq_file *seq,
...@@ -282,7 +284,7 @@ int sctp_register_af(struct sctp_af *); ...@@ -282,7 +284,7 @@ int sctp_register_af(struct sctp_af *);
struct sctp_pf { struct sctp_pf {
void (*event_msgname)(struct sctp_ulpevent *, char *, int *); void (*event_msgname)(struct sctp_ulpevent *, char *, int *);
void (*skb_msgname) (struct sk_buff *, char *, int *); void (*skb_msgname) (struct sk_buff *, char *, int *);
int (*af_supported) (sa_family_t); int (*af_supported) (sa_family_t, struct sctp_opt *);
int (*cmp_addr) (const union sctp_addr *, int (*cmp_addr) (const union sctp_addr *,
const union sctp_addr *, const union sctp_addr *,
struct sctp_opt *); struct sctp_opt *);
...@@ -291,6 +293,7 @@ struct sctp_pf { ...@@ -291,6 +293,7 @@ struct sctp_pf {
int (*supported_addrs)(const struct sctp_opt *, __u16 *); int (*supported_addrs)(const struct sctp_opt *, __u16 *);
struct sock *(*create_accept_sk) (struct sock *sk, struct sock *(*create_accept_sk) (struct sock *sk,
struct sctp_association *asoc); struct sctp_association *asoc);
void (*addr_v4map) (struct sctp_opt *, union sctp_addr *);
struct sctp_af *af; struct sctp_af *af;
}; };
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Sridhar Samudrala <sri@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
...@@ -53,7 +54,6 @@ ...@@ -53,7 +54,6 @@
* growing this structure as it is at the maximum limit now. * growing this structure as it is at the maximum limit now.
*/ */
struct sctp_ulpevent { struct sctp_ulpevent {
struct sctp_association *asoc;
struct sctp_sndrcvinfo sndrcvinfo; struct sctp_sndrcvinfo sndrcvinfo;
int msg_flags; int msg_flags;
int iif; int iif;
...@@ -72,9 +72,10 @@ static inline struct sctp_ulpevent *sctp_skb2event(struct sk_buff *skb) ...@@ -72,9 +72,10 @@ static inline struct sctp_ulpevent *sctp_skb2event(struct sk_buff *skb)
} }
struct sctp_ulpevent *sctp_ulpevent_new(int size, int flags, int gfp); struct sctp_ulpevent *sctp_ulpevent_new(int size, int flags, int gfp);
struct sctp_ulpevent *sctp_ulpevent_init(struct sctp_ulpevent *, int flags); void sctp_ulpevent_init(struct sctp_ulpevent *, int flags);
void sctp_ulpevent_free(struct sctp_ulpevent *); void sctp_ulpevent_free(struct sctp_ulpevent *);
int sctp_ulpevent_is_notification(const struct sctp_ulpevent *); int sctp_ulpevent_is_notification(const struct sctp_ulpevent *);
void sctp_queue_purge_ulpevents(struct sk_buff_head *list);
struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
const struct sctp_association *asoc, const struct sctp_association *asoc,
......
This diff is collapsed.
...@@ -556,12 +556,12 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, ...@@ -556,12 +556,12 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
switch (command) { switch (command) {
case SCTP_TRANSPORT_UP: case SCTP_TRANSPORT_UP:
transport->active = SCTP_ACTIVE; transport->active = SCTP_ACTIVE;
spc_state = ADDRESS_AVAILABLE; spc_state = SCTP_ADDR_REACHABLE;
break; break;
case SCTP_TRANSPORT_DOWN: case SCTP_TRANSPORT_DOWN:
transport->active = SCTP_INACTIVE; transport->active = SCTP_INACTIVE;
spc_state = ADDRESS_UNREACHABLE; spc_state = SCTP_ADDR_UNREACHABLE;
break; break;
default: default:
...@@ -877,7 +877,7 @@ void sctp_assoc_migrate(struct sctp_association *assoc, struct sock *newsk) ...@@ -877,7 +877,7 @@ void sctp_assoc_migrate(struct sctp_association *assoc, struct sock *newsk)
/* Delete the association from the old endpoint's list of /* Delete the association from the old endpoint's list of
* associations. * associations.
*/ */
list_del(&assoc->asocs); list_del_init(&assoc->asocs);
/* Decrement the backlog value for a TCP-style socket. */ /* Decrement the backlog value for a TCP-style socket. */
if (sctp_style(oldsk, TCP)) if (sctp_style(oldsk, TCP))
......
...@@ -85,7 +85,7 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg) ...@@ -85,7 +85,7 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
/* Release all references. */ /* Release all references. */
list_for_each_safe(pos, temp, &msg->chunks) { list_for_each_safe(pos, temp, &msg->chunks) {
list_del(pos); list_del_init(pos);
chunk = list_entry(pos, struct sctp_chunk, frag_list); chunk = list_entry(pos, struct sctp_chunk, frag_list);
/* Check whether we _really_ need to notify. */ /* Check whether we _really_ need to notify. */
if (notify < 0) { if (notify < 0) {
...@@ -294,7 +294,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, ...@@ -294,7 +294,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
errout: errout:
list_for_each_safe(pos, temp, &msg->chunks) { list_for_each_safe(pos, temp, &msg->chunks) {
list_del(pos); list_del_init(pos);
chunk = list_entry(pos, struct sctp_chunk, frag_list); chunk = list_entry(pos, struct sctp_chunk, frag_list);
sctp_chunk_free(chunk); sctp_chunk_free(chunk);
} }
......
...@@ -150,7 +150,7 @@ int sctp_rcv(struct sk_buff *skb) ...@@ -150,7 +150,7 @@ int sctp_rcv(struct sk_buff *skb)
* IP broadcast addresses cannot be used in an SCTP transport * IP broadcast addresses cannot be used in an SCTP transport
* address." * address."
*/ */
if (!af->addr_valid(&src) || !af->addr_valid(&dest)) if (!af->addr_valid(&src, NULL) || !af->addr_valid(&dest, NULL))
goto discard_it; goto discard_it;
asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport); asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
* Copyright (c) 2002-2003 International Business Machines, Corp. * Copyright (c) 2002-2003 International Business Machines, Corp.
* Copyright (c) 2002-2003 Intel Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
...@@ -37,6 +38,7 @@ ...@@ -37,6 +38,7 @@
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.ibm.com>
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
* *
* Based on: * Based on:
* linux/net/ipv6/tcp_ipv6.c * linux/net/ipv6/tcp_ipv6.c
...@@ -192,6 +194,9 @@ struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, ...@@ -192,6 +194,9 @@ struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
memset(&fl, 0, sizeof(fl)); memset(&fl, 0, sizeof(fl));
ipv6_addr_copy(&fl.fl6_dst, &daddr->v6.sin6_addr); ipv6_addr_copy(&fl.fl6_dst, &daddr->v6.sin6_addr);
if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
fl.oif = daddr->v6.sin6_scope_id;
SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
__FUNCTION__, NIP6(fl.fl6_dst)); __FUNCTION__, NIP6(fl.fl6_dst));
...@@ -370,13 +375,28 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) ...@@ -370,13 +375,28 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk)
/* Initialize sk->sk_rcv_saddr from sctp_addr. */ /* Initialize sk->sk_rcv_saddr from sctp_addr. */
static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk) static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk)
{ {
if (addr->sa.sa_family == AF_INET && sctp_sk(sk)->v4mapped) {
inet6_sk(sk)->rcv_saddr.s6_addr32[0] = 0;
inet6_sk(sk)->rcv_saddr.s6_addr32[1] = 0;
inet6_sk(sk)->rcv_saddr.s6_addr32[2] = htonl(0x0000ffff);
inet6_sk(sk)->rcv_saddr.s6_addr32[3] =
addr->v4.sin_addr.s_addr;
} else {
inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr; inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr;
}
} }
/* Initialize sk->sk_daddr from sctp_addr. */ /* Initialize sk->sk_daddr from sctp_addr. */
static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
{ {
if (addr->sa.sa_family == AF_INET && sctp_sk(sk)->v4mapped) {
inet6_sk(sk)->daddr.s6_addr32[0] = 0;
inet6_sk(sk)->daddr.s6_addr32[1] = 0;
inet6_sk(sk)->daddr.s6_addr32[2] = htonl(0x0000ffff);
inet6_sk(sk)->daddr.s6_addr32[3] = addr->v4.sin_addr.s_addr;
} else {
inet6_sk(sk)->daddr = addr->v6.sin6_addr; inet6_sk(sk)->daddr = addr->v6.sin6_addr;
}
} }
/* Initialize a sctp_addr from a dst_entry. */ /* Initialize a sctp_addr from a dst_entry. */
...@@ -390,13 +410,30 @@ static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst, ...@@ -390,13 +410,30 @@ static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst,
} }
/* Compare addresses exactly. /* Compare addresses exactly.
* FIXME: v4-mapped-v6. * v4-mapped-v6 is also in consideration.
*/ */
static int sctp_v6_cmp_addr(const union sctp_addr *addr1, static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
const union sctp_addr *addr2) const union sctp_addr *addr2)
{ {
if (addr1->sa.sa_family != addr2->sa.sa_family) if (addr1->sa.sa_family != addr2->sa.sa_family) {
if (addr1->sa.sa_family == AF_INET &&
addr2->sa.sa_family == AF_INET6 &&
IPV6_ADDR_MAPPED == ipv6_addr_type(&addr2->v6.sin6_addr)) {
if (addr2->v6.sin6_port == addr1->v4.sin_port &&
addr2->v6.sin6_addr.s6_addr32[3] ==
addr1->v4.sin_addr.s_addr)
return 1;
}
if (addr2->sa.sa_family == AF_INET &&
addr1->sa.sa_family == AF_INET6 &&
IPV6_ADDR_MAPPED == ipv6_addr_type(&addr1->v6.sin6_addr)) {
if (addr1->v6.sin6_port == addr2->v4.sin_port &&
addr1->v6.sin6_addr.s6_addr32[3] ==
addr2->v4.sin_addr.s_addr)
return 1;
}
return 0; return 0;
}
if (ipv6_addr_cmp(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr)) if (ipv6_addr_cmp(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr))
return 0; return 0;
/* If this is a linklocal address, compare the scope_id. */ /* If this is a linklocal address, compare the scope_id. */
...@@ -427,7 +464,7 @@ static int sctp_v6_is_any(const union sctp_addr *addr) ...@@ -427,7 +464,7 @@ static int sctp_v6_is_any(const union sctp_addr *addr)
} }
/* Should this be available for binding? */ /* Should this be available for binding? */
static int sctp_v6_available(const union sctp_addr *addr) static int sctp_v6_available(union sctp_addr *addr, struct sctp_opt *sp)
{ {
int type; int type;
struct in6_addr *in6 = (struct in6_addr *)&addr->v6.sin6_addr; struct in6_addr *in6 = (struct in6_addr *)&addr->v6.sin6_addr;
...@@ -435,6 +472,14 @@ static int sctp_v6_available(const union sctp_addr *addr) ...@@ -435,6 +472,14 @@ static int sctp_v6_available(const union sctp_addr *addr)
type = ipv6_addr_type(in6); type = ipv6_addr_type(in6);
if (IPV6_ADDR_ANY == type) if (IPV6_ADDR_ANY == type)
return 1; return 1;
if (type == IPV6_ADDR_MAPPED) {
if (sp && !sp->v4mapped)
return 0;
if (sp && ipv6_only_sock(sctp_opt2sk(sp)))
return 0;
sctp_v6_map_v4(addr);
return sctp_get_af_specific(AF_INET)->available(addr, sp);
}
if (!(type & IPV6_ADDR_UNICAST)) if (!(type & IPV6_ADDR_UNICAST))
return 0; return 0;
...@@ -448,11 +493,22 @@ static int sctp_v6_available(const union sctp_addr *addr) ...@@ -448,11 +493,22 @@ static int sctp_v6_available(const union sctp_addr *addr)
* Return 0 - If the address is a non-unicast or an illegal address. * Return 0 - If the address is a non-unicast or an illegal address.
* Return 1 - If the address is a unicast. * Return 1 - If the address is a unicast.
*/ */
static int sctp_v6_addr_valid(union sctp_addr *addr) static int sctp_v6_addr_valid(union sctp_addr *addr, struct sctp_opt *sp)
{ {
int ret = ipv6_addr_type(&addr->v6.sin6_addr); int ret = ipv6_addr_type(&addr->v6.sin6_addr);
/* FIXME: v4-mapped-v6 address support. */ /* Support v4-mapped-v6 address. */
if (ret == IPV6_ADDR_MAPPED) {
/* Note: This routine is used in input, so v4-mapped-v6
* are disallowed here when there is no sctp_opt.
*/
if (!sp || !sp->v4mapped)
return 0;
if (sp && ipv6_only_sock(sctp_opt2sk(sp)))
return 0;
sctp_v6_map_v4(addr);
return sctp_get_af_specific(AF_INET)->addr_valid(addr, sp);
}
/* Is this a non-unicast address */ /* Is this a non-unicast address */
if (!(ret & IPV6_ADDR_UNICAST)) if (!(ret & IPV6_ADDR_UNICAST))
...@@ -536,7 +592,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk, ...@@ -536,7 +592,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
newnp->saddr = np->saddr; newnp->saddr = np->saddr;
newnp->rcv_saddr = np->rcv_saddr; newnp->rcv_saddr = np->rcv_saddr;
newinet->dport = htons(asoc->peer.port); newinet->dport = htons(asoc->peer.port);
newnp->daddr = asoc->peer.primary_addr.v6.sin6_addr; sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk);
/* Init the ipv4 part of the socket since we can have sockets /* Init the ipv4 part of the socket since we can have sockets
* using v6 API for ipv4. * using v6 API for ipv4.
...@@ -566,6 +622,13 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk, ...@@ -566,6 +622,13 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
return newsk; return newsk;
} }
/* Map v4 address to mapped v6 address */
static void sctp_v6_addr_v4map(struct sctp_opt *sp, union sctp_addr *addr)
{
if (sp->v4mapped && AF_INET == addr->sa.sa_family)
sctp_v4_map_v6(addr);
}
/* Where did this skb come from? */ /* Where did this skb come from? */
static int sctp_v6_skb_iif(const struct sk_buff *skb) static int sctp_v6_skb_iif(const struct sk_buff *skb)
{ {
...@@ -606,25 +669,28 @@ static void sctp_inet6_event_msgname(struct sctp_ulpevent *event, ...@@ -606,25 +669,28 @@ static void sctp_inet6_event_msgname(struct sctp_ulpevent *event,
if (msgname) { if (msgname) {
union sctp_addr *addr; union sctp_addr *addr;
struct sctp_association *asoc;
asoc = event->sndrcvinfo.sinfo_assoc_id;
sctp_inet6_msgname(msgname, addrlen); sctp_inet6_msgname(msgname, addrlen);
sin6 = (struct sockaddr_in6 *)msgname; sin6 = (struct sockaddr_in6 *)msgname;
sin6->sin6_port = htons(event->asoc->peer.port); sin6->sin6_port = htons(asoc->peer.port);
addr = &event->asoc->peer.primary_addr; addr = &asoc->peer.primary_addr;
/* Note: If we go to a common v6 format, this code /* Note: If we go to a common v6 format, this code
* will change. * will change.
*/ */
/* Map ipv4 address into v4-mapped-on-v6 address. */ /* Map ipv4 address into v4-mapped-on-v6 address. */
if (AF_INET == addr->sa.sa_family) { if (sctp_sk(asoc->base.sk)->v4mapped &&
/* FIXME: Easy, but there was no way to test this AF_INET == addr->sa.sa_family) {
* yet. sctp_v4_map_v6((union sctp_addr *)sin6);
*/ sin6->sin6_addr.s6_addr32[3] =
addr->v4.sin_addr.s_addr;
return; return;
} }
sin6from = &event->asoc->peer.primary_addr.v6; sin6from = &asoc->peer.primary_addr.v6;
ipv6_addr_copy(&sin6->sin6_addr, &sin6from->sin6_addr); ipv6_addr_copy(&sin6->sin6_addr, &sin6from->sin6_addr);
if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
sin6->sin6_scope_id = sin6from->sin6_scope_id; sin6->sin6_scope_id = sin6from->sin6_scope_id;
...@@ -644,16 +710,15 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname, ...@@ -644,16 +710,15 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
sh = (struct sctphdr *)skb->h.raw; sh = (struct sctphdr *)skb->h.raw;
sin6->sin6_port = sh->source; sin6->sin6_port = sh->source;
/* FIXME: Map ipv4 address into v4-mapped-on-v6 address. */ /* Map ipv4 address into v4-mapped-on-v6 address. */
if (__constant_htons(ETH_P_IP) == skb->protocol) { if (sctp_sk(skb->sk)->v4mapped &&
/* FIXME: The latest I-D added options for two skb->nh.iph->version == 4) {
* behaviors. sctp_v4_map_v6((union sctp_addr *)sin6);
*/ sin6->sin6_addr.s6_addr32[3] = skb->nh.iph->saddr;
return; return;
} }
/* Otherwise, just copy the v6 address. */ /* Otherwise, just copy the v6 address. */
ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr); ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr);
if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) { if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) {
struct sctp_ulpevent *ev = sctp_skb2event(skb); struct sctp_ulpevent *ev = sctp_skb2event(skb);
...@@ -663,15 +728,14 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname, ...@@ -663,15 +728,14 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
} }
/* Do we support this AF? */ /* Do we support this AF? */
static int sctp_inet6_af_supported(sa_family_t family) static int sctp_inet6_af_supported(sa_family_t family, struct sctp_opt *sp)
{ {
/* FIXME: v4-mapped-v6 addresses. The I-D is still waffling
* on what to do with sockaddr formats for PF_INET6 sockets.
* For now assume we'll support both.
*/
switch (family) { switch (family) {
case AF_INET6: case AF_INET6:
return 1;
/* v4-mapped-v6 addresses */
case AF_INET: case AF_INET:
if (!__ipv6_only_sock(sctp_opt2sk(sp)) && sp->v4mapped)
return 1; return 1;
default: default:
return 0; return 0;
...@@ -716,7 +780,7 @@ static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr) ...@@ -716,7 +780,7 @@ static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
else { else {
struct sock *sk; struct sock *sk;
int type = ipv6_addr_type(&addr->v6.sin6_addr); int type = ipv6_addr_type(&addr->v6.sin6_addr);
sk = &container_of(opt, struct sctp6_sock, sctp)->sk; sk = sctp_opt2sk(opt);
if (type & IPV6_ADDR_LINKLOCAL) { if (type & IPV6_ADDR_LINKLOCAL) {
/* Note: Behavior similar to af_inet6.c: /* Note: Behavior similar to af_inet6.c:
* 1) Overrides previous bound_dev_if * 1) Overrides previous bound_dev_if
...@@ -730,7 +794,7 @@ static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr) ...@@ -730,7 +794,7 @@ static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
} }
af = opt->pf->af; af = opt->pf->af;
} }
return af->available(addr); return af->available(addr, opt);
} }
/* Verify that the provided sockaddr looks bindable. Common verification, /* Verify that the provided sockaddr looks bindable. Common verification,
...@@ -746,7 +810,7 @@ static int sctp_inet6_send_verify(struct sctp_opt *opt, union sctp_addr *addr) ...@@ -746,7 +810,7 @@ static int sctp_inet6_send_verify(struct sctp_opt *opt, union sctp_addr *addr)
else { else {
struct sock *sk; struct sock *sk;
int type = ipv6_addr_type(&addr->v6.sin6_addr); int type = ipv6_addr_type(&addr->v6.sin6_addr);
sk = &container_of(opt, struct sctp6_sock, sctp)->sk; sk = sctp_opt2sk(opt);
if (type & IPV6_ADDR_LINKLOCAL) { if (type & IPV6_ADDR_LINKLOCAL) {
/* Note: Behavior similar to af_inet6.c: /* Note: Behavior similar to af_inet6.c:
* 1) Overrides previous bound_dev_if * 1) Overrides previous bound_dev_if
...@@ -863,6 +927,7 @@ static struct sctp_pf sctp_pf_inet6_specific = { ...@@ -863,6 +927,7 @@ static struct sctp_pf sctp_pf_inet6_specific = {
.send_verify = sctp_inet6_send_verify, .send_verify = sctp_inet6_send_verify,
.supported_addrs = sctp_inet6_supported_addrs, .supported_addrs = sctp_inet6_supported_addrs,
.create_accept_sk = sctp_v6_create_accept_sk, .create_accept_sk = sctp_v6_create_accept_sk,
.addr_v4map = sctp_v6_addr_v4map,
.af = &sctp_ipv6_specific, .af = &sctp_ipv6_specific,
}; };
......
...@@ -97,6 +97,7 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet, ...@@ -97,6 +97,7 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
packet->source_port = sport; packet->source_port = sport;
packet->destination_port = dport; packet->destination_port = dport;
skb_queue_head_init(&packet->chunks); skb_queue_head_init(&packet->chunks);
packet->size = SCTP_IP_OVERHEAD;
packet->vtag = 0; packet->vtag = 0;
packet->ecn_capable = 0; packet->ecn_capable = 0;
packet->get_prepend_chunk = NULL; packet->get_prepend_chunk = NULL;
...@@ -219,9 +220,8 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, ...@@ -219,9 +220,8 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
/* Both control chunks and data chunks with TSNs are /* Both control chunks and data chunks with TSNs are
* non-fragmentable. * non-fragmentable.
*/ */
if (packet_empty) { if (packet_empty || !sctp_chunk_is_data(chunk)) {
/* We no longer do re-fragmentation.
/* We no longer do refragmentation at all.
* Just fragment at the IP layer, if we * Just fragment at the IP layer, if we
* actually hit this condition * actually hit this condition
*/ */
...@@ -229,7 +229,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, ...@@ -229,7 +229,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
packet->ipfragok = 1; packet->ipfragok = 1;
goto append; goto append;
} else { /* !packet_empty */ } else {
retval = SCTP_XMIT_PMTU_FULL; retval = SCTP_XMIT_PMTU_FULL;
goto finish; goto finish;
} }
...@@ -283,20 +283,18 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -283,20 +283,18 @@ int sctp_packet_transmit(struct sctp_packet *packet)
__u8 has_data = 0; __u8 has_data = 0;
struct dst_entry *dst; struct dst_entry *dst;
/* Do NOT generate a chunkless packet... */ /* Do NOT generate a chunkless packet. */
if (skb_queue_empty(&packet->chunks)) chunk = (struct sctp_chunk *)skb_peek(&packet->chunks);
if (unlikely(!chunk))
return err; return err;
/* Set up convenience variables... */ /* Set up convenience variables... */
chunk = (struct sctp_chunk *) (packet->chunks.next);
sk = chunk->skb->sk; sk = chunk->skb->sk;
/* Allocate the new skb. */ /* Allocate the new skb. */
nskb = dev_alloc_skb(packet->size); nskb = dev_alloc_skb(packet->size);
if (!nskb) { if (!nskb)
err = -ENOMEM; goto nomem;
goto out;
}
/* Make sure the outbound skb has enough header room reserved. */ /* Make sure the outbound skb has enough header room reserved. */
skb_reserve(nskb, SCTP_IP_OVERHEAD); skb_reserve(nskb, SCTP_IP_OVERHEAD);
...@@ -468,9 +466,11 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -468,9 +466,11 @@ int sctp_packet_transmit(struct sctp_packet *packet)
if (!nskb->dst) if (!nskb->dst)
goto no_route; goto no_route;
SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb length %d\n", SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb len %d\n",
nskb->len); nskb->len);
(*tp->af_specific->sctp_xmit)(nskb, tp, packet->ipfragok); (*tp->af_specific->sctp_xmit)(nskb, tp, packet->ipfragok);
out: out:
packet->size = SCTP_IP_OVERHEAD; packet->size = SCTP_IP_OVERHEAD;
return err; return err;
...@@ -486,7 +486,20 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -486,7 +486,20 @@ int sctp_packet_transmit(struct sctp_packet *packet)
* required. * required.
*/ */
/* err = -EHOSTUNREACH; */ /* err = -EHOSTUNREACH; */
err:
/* Control chunks are unreliable so just drop them. DATA chunks
* will get resent or dropped later.
*/
while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) {
if (!sctp_chunk_is_data(chunk))
sctp_chunk_free(chunk);
}
goto out; goto out;
nomem:
err = -ENOMEM;
printk("%s alloc_skb failed.\n", __FUNCTION__);
goto err;
} }
/******************************************************************** /********************************************************************
......
...@@ -258,7 +258,7 @@ void sctp_outq_teardown(struct sctp_outq *q) ...@@ -258,7 +258,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
/* Throw away chunks that have been gap ACKed. */ /* Throw away chunks that have been gap ACKed. */
list_for_each_safe(lchunk, temp, &q->sacked) { list_for_each_safe(lchunk, temp, &q->sacked) {
list_del(lchunk); list_del_init(lchunk);
chunk = list_entry(lchunk, struct sctp_chunk, chunk = list_entry(lchunk, struct sctp_chunk,
transmitted_list); transmitted_list);
sctp_datamsg_fail(chunk, q->error); sctp_datamsg_fail(chunk, q->error);
...@@ -267,7 +267,7 @@ void sctp_outq_teardown(struct sctp_outq *q) ...@@ -267,7 +267,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
/* Throw away any chunks in the retransmit queue. */ /* Throw away any chunks in the retransmit queue. */
list_for_each_safe(lchunk, temp, &q->retransmit) { list_for_each_safe(lchunk, temp, &q->retransmit) {
list_del(lchunk); list_del_init(lchunk);
chunk = list_entry(lchunk, struct sctp_chunk, chunk = list_entry(lchunk, struct sctp_chunk,
transmitted_list); transmitted_list);
sctp_datamsg_fail(chunk, q->error); sctp_datamsg_fail(chunk, q->error);
...@@ -445,7 +445,7 @@ void sctp_retransmit_mark(struct sctp_outq *q, ...@@ -445,7 +445,7 @@ void sctp_retransmit_mark(struct sctp_outq *q,
/* Move the chunk to the retransmit queue. The chunks /* Move the chunk to the retransmit queue. The chunks
* on the retransmit queue is always kept in order. * on the retransmit queue is always kept in order.
*/ */
list_del(lchunk); list_del_init(lchunk);
sctp_retransmit_insert(lchunk, q); sctp_retransmit_insert(lchunk, q);
} }
} }
...@@ -1007,7 +1007,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) ...@@ -1007,7 +1007,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
struct sctp_association *asoc = q->asoc; struct sctp_association *asoc = q->asoc;
struct sctp_transport *transport; struct sctp_transport *transport;
struct sctp_chunk *tchunk; struct sctp_chunk *tchunk;
struct list_head *lchunk, *transport_list, *pos; struct list_head *lchunk, *transport_list, *pos, *temp;
sctp_sack_variable_t *frags = sack->variable; sctp_sack_variable_t *frags = sack->variable;
__u32 sack_ctsn, ctsn, tsn; __u32 sack_ctsn, ctsn, tsn;
__u32 highest_tsn, highest_new_tsn; __u32 highest_tsn, highest_new_tsn;
...@@ -1115,15 +1115,13 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) ...@@ -1115,15 +1115,13 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
"%p is 0x%x.\n", __FUNCTION__, asoc, ctsn); "%p is 0x%x.\n", __FUNCTION__, asoc, ctsn);
/* Throw away stuff rotting on the sack queue. */ /* Throw away stuff rotting on the sack queue. */
list_for_each(lchunk, &q->sacked) { list_for_each_safe(lchunk, temp, &q->sacked) {
tchunk = list_entry(lchunk, struct sctp_chunk, tchunk = list_entry(lchunk, struct sctp_chunk,
transmitted_list); transmitted_list);
tsn = ntohl(tchunk->subh.data_hdr->tsn); tsn = ntohl(tchunk->subh.data_hdr->tsn);
if (TSN_lte(tsn, ctsn)) { if (TSN_lte(tsn, ctsn))
lchunk = lchunk->prev;
sctp_chunk_free(tchunk); sctp_chunk_free(tchunk);
} }
}
/* ii) Set rwnd equal to the newly received a_rwnd minus the /* ii) Set rwnd equal to the newly received a_rwnd minus the
* number of bytes still outstanding after processing the * number of bytes still outstanding after processing the
......
...@@ -340,7 +340,7 @@ static int sctp_v4_is_any(const union sctp_addr *addr) ...@@ -340,7 +340,7 @@ static int sctp_v4_is_any(const union sctp_addr *addr)
* Return 0 - If the address is a non-unicast or an illegal address. * Return 0 - If the address is a non-unicast or an illegal address.
* Return 1 - If the address is a unicast. * Return 1 - If the address is a unicast.
*/ */
static int sctp_v4_addr_valid(union sctp_addr *addr) static int sctp_v4_addr_valid(union sctp_addr *addr, struct sctp_opt *sp)
{ {
/* Is this a non-unicast address or a unusable SCTP address? */ /* Is this a non-unicast address or a unusable SCTP address? */
if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr)) if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr))
...@@ -350,7 +350,7 @@ static int sctp_v4_addr_valid(union sctp_addr *addr) ...@@ -350,7 +350,7 @@ static int sctp_v4_addr_valid(union sctp_addr *addr)
} }
/* Should this be available for binding? */ /* Should this be available for binding? */
static int sctp_v4_available(const union sctp_addr *addr) static int sctp_v4_available(union sctp_addr *addr, struct sctp_opt *sp)
{ {
int ret = inet_addr_type(addr->v4.sin_addr.s_addr); int ret = inet_addr_type(addr->v4.sin_addr.s_addr);
...@@ -580,6 +580,12 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk, ...@@ -580,6 +580,12 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk,
return newsk; return newsk;
} }
/* Map address, empty for v4 family */
static void sctp_v4_addr_v4map(struct sctp_opt *sp, union sctp_addr *addr)
{
/* Empty */
}
/* Dump the v4 addr to the seq file. */ /* Dump the v4 addr to the seq file. */
static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
{ {
...@@ -685,10 +691,13 @@ static void sctp_inet_event_msgname(struct sctp_ulpevent *event, char *msgname, ...@@ -685,10 +691,13 @@ static void sctp_inet_event_msgname(struct sctp_ulpevent *event, char *msgname,
struct sockaddr_in *sin, *sinfrom; struct sockaddr_in *sin, *sinfrom;
if (msgname) { if (msgname) {
struct sctp_association *asoc;
asoc = event->sndrcvinfo.sinfo_assoc_id;
sctp_inet_msgname(msgname, addr_len); sctp_inet_msgname(msgname, addr_len);
sin = (struct sockaddr_in *)msgname; sin = (struct sockaddr_in *)msgname;
sinfrom = &event->asoc->peer.primary_addr.v4; sinfrom = &asoc->peer.primary_addr.v4;
sin->sin_port = htons(event->asoc->peer.port); sin->sin_port = htons(asoc->peer.port);
sin->sin_addr.s_addr = sinfrom->sin_addr.s_addr; sin->sin_addr.s_addr = sinfrom->sin_addr.s_addr;
} }
} }
...@@ -709,7 +718,7 @@ static void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *len) ...@@ -709,7 +718,7 @@ static void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *len)
} }
/* Do we support this AF? */ /* Do we support this AF? */
static int sctp_inet_af_supported(sa_family_t family) static int sctp_inet_af_supported(sa_family_t family, struct sctp_opt *sp)
{ {
/* PF_INET only supports AF_INET addresses. */ /* PF_INET only supports AF_INET addresses. */
return (AF_INET == family); return (AF_INET == family);
...@@ -737,7 +746,7 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1, ...@@ -737,7 +746,7 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1,
*/ */
static int sctp_inet_bind_verify(struct sctp_opt *opt, union sctp_addr *addr) static int sctp_inet_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
{ {
return sctp_v4_available(addr); return sctp_v4_available(addr, opt);
} }
/* Verify that sockaddr looks sendable. Common verification has already /* Verify that sockaddr looks sendable. Common verification has already
...@@ -783,6 +792,7 @@ static struct sctp_pf sctp_pf_inet = { ...@@ -783,6 +792,7 @@ static struct sctp_pf sctp_pf_inet = {
.send_verify = sctp_inet_send_verify, .send_verify = sctp_inet_send_verify,
.supported_addrs = sctp_inet_supported_addrs, .supported_addrs = sctp_inet_supported_addrs,
.create_accept_sk = sctp_v4_create_accept_sk, .create_accept_sk = sctp_v4_create_accept_sk,
.addr_v4map = sctp_v4_addr_v4map,
.af = &sctp_ipv4_specific, .af = &sctp_ipv4_specific,
}; };
......
...@@ -667,7 +667,8 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc) ...@@ -667,7 +667,8 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
} }
/* Make a SHUTDOWN chunk. */ /* Make a SHUTDOWN chunk. */
struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc) struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc,
const struct sctp_chunk *chunk)
{ {
struct sctp_chunk *retval; struct sctp_chunk *retval;
sctp_shutdownhdr_t shut; sctp_shutdownhdr_t shut;
...@@ -683,6 +684,9 @@ struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc) ...@@ -683,6 +684,9 @@ struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc)
retval->subh.shutdown_hdr = retval->subh.shutdown_hdr =
sctp_addto_chunk(retval, sizeof(shut), &shut); sctp_addto_chunk(retval, sizeof(shut), &shut);
if (chunk)
retval->transport = chunk->transport;
nodata: nodata:
return retval; return retval;
} }
...@@ -1089,7 +1093,7 @@ void sctp_chunk_free(struct sctp_chunk *chunk) ...@@ -1089,7 +1093,7 @@ void sctp_chunk_free(struct sctp_chunk *chunk)
{ {
/* Make sure that we are not on any list. */ /* Make sure that we are not on any list. */
skb_unlink((struct sk_buff *) chunk); skb_unlink((struct sk_buff *) chunk);
list_del(&chunk->transmitted_list); list_del_init(&chunk->transmitted_list);
/* Release our reference on the message tracker. */ /* Release our reference on the message tracker. */
if (chunk->msg) if (chunk->msg)
...@@ -1850,7 +1854,7 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, ...@@ -1850,7 +1854,7 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
/* Release the transport structures. */ /* Release the transport structures. */
list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
transport = list_entry(pos, struct sctp_transport, transports); transport = list_entry(pos, struct sctp_transport, transports);
list_del(pos); list_del_init(pos);
sctp_transport_free(transport); sctp_transport_free(transport);
} }
nomem: nomem:
......
...@@ -962,7 +962,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -962,7 +962,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
asoc->overall_error_count = 0; asoc->overall_error_count = 0;
/* Generate a SHUTDOWN chunk. */ /* Generate a SHUTDOWN chunk. */
new_obj = sctp_make_shutdown(asoc); new_obj = sctp_make_shutdown(asoc, chunk);
if (!new_obj) if (!new_obj)
goto nomem; goto nomem;
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
......
...@@ -3862,7 +3862,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown( ...@@ -3862,7 +3862,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown(
* in the Cumulative TSN Ack field the last sequential TSN it * in the Cumulative TSN Ack field the last sequential TSN it
* has received from the peer. * has received from the peer.
*/ */
reply = sctp_make_shutdown(asoc); reply = sctp_make_shutdown(asoc, NULL);
if (!reply) if (!reply)
goto nomem; goto nomem;
...@@ -4179,7 +4179,7 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep, ...@@ -4179,7 +4179,7 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
switch (asoc->state) { switch (asoc->state) {
case SCTP_STATE_SHUTDOWN_SENT: case SCTP_STATE_SHUTDOWN_SENT:
reply = sctp_make_shutdown(asoc); reply = sctp_make_shutdown(asoc, NULL);
break; break;
case SCTP_STATE_SHUTDOWN_ACK_SENT: case SCTP_STATE_SHUTDOWN_ACK_SENT:
......
This diff is collapsed.
...@@ -117,6 +117,7 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, ...@@ -117,6 +117,7 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
INIT_LIST_HEAD(&peer->transmitted); INIT_LIST_HEAD(&peer->transmitted);
INIT_LIST_HEAD(&peer->send_ready); INIT_LIST_HEAD(&peer->send_ready);
INIT_LIST_HEAD(&peer->transports); INIT_LIST_HEAD(&peer->transports);
sctp_packet_init(&peer->packet, peer, 0, 0);
/* Set up the retransmission timer. */ /* Set up the retransmission timer. */
init_timer(&peer->T3_rtx_timer); init_timer(&peer->T3_rtx_timer);
......
This diff is collapsed.
...@@ -235,9 +235,9 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) ...@@ -235,9 +235,9 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
out_free: out_free:
if (sctp_event2skb(event)->list) if (sctp_event2skb(event)->list)
skb_queue_purge(sctp_event2skb(event)->list); sctp_queue_purge_ulpevents(sctp_event2skb(event)->list);
else else
kfree_skb(sctp_event2skb(event)); sctp_ulpevent_free(event);
return 0; return 0;
} }
...@@ -289,7 +289,7 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq, ...@@ -289,7 +289,7 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
* payload was fragmented on the way and ip had to reassemble them. * payload was fragmented on the way and ip had to reassemble them.
* We add the rest of skb's to the first skb's fraglist. * We add the rest of skb's to the first skb's fraglist.
*/ */
static inline struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *f_frag, struct sk_buff *l_frag) static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *f_frag, struct sk_buff *l_frag)
{ {
struct sk_buff *pos; struct sk_buff *pos;
struct sctp_ulpevent *event; struct sctp_ulpevent *event;
...@@ -329,7 +329,6 @@ static inline struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff * ...@@ -329,7 +329,6 @@ static inline struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *
/* Break if we have reached the last fragment. */ /* Break if we have reached the last fragment. */
if (pos == l_frag) if (pos == l_frag)
break; break;
pos->next = pnext; pos->next = pnext;
pos = pnext; pos = pnext;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment