X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fx25%2Faf_x25.c;h=77fdf20f1284d2f7551fe84724d5d9dd60aea87f;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=be33fd881a741762aaf7630ffdbdd247d1ff7c94;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index be33fd881..77fdf20f1 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -34,28 +34,19 @@ #include #include #include -#include -#include -#include #include #include #include #include -#include #include -#include -#include #include #include #include #include #include -#include #include #include #include /* For TIOCINQ/OUTQ */ -#include -#include #include #include #include @@ -67,7 +58,7 @@ int sysctl_x25_clear_request_timeout = X25_DEFAULT_T23; int sysctl_x25_ack_holdback_timeout = X25_DEFAULT_T2; HLIST_HEAD(x25_list); -rwlock_t x25_list_lock = RW_LOCK_UNLOCKED; +DEFINE_RWLOCK(x25_list_lock); static struct proto_ops x25_proto_ops; @@ -223,14 +214,19 @@ static void x25_insert_socket(struct sock *sk) /* * Find a socket that wants to accept the Call Request we just - * received. + * received. Check the full list for an address/cud match. + * If no cuds match return the next_best thing, an address match. + * Note: if a listening socket has cud set it must only get calls + * with matching cud. */ -static struct sock *x25_find_listener(struct x25_address *addr) +static struct sock *x25_find_listener(struct x25_address *addr, struct x25_calluserdata *calluserdata) { struct sock *s; + struct sock *next_best; struct hlist_node *node; read_lock_bh(&x25_list_lock); + next_best = NULL; sk_for_each(s, node, &x25_list) if ((!strcmp(addr->x25_addr, @@ -238,9 +234,24 @@ static struct sock *x25_find_listener(struct x25_address *addr) !strcmp(addr->x25_addr, null_x25_address.x25_addr)) && s->sk_state == TCP_LISTEN) { - sock_hold(s); - goto found; + + /* + * Found a listening socket, now check the incoming + * call user data vs this sockets call user data + */ + if (x25_check_calluserdata(&x25_sk(s)->calluserdata, calluserdata)) { + sock_hold(s); + goto found; + } + if (x25_sk(s)->calluserdata.cudlength == 0) { + next_best = s; + } } + if (next_best) { + s = next_best; + sock_hold(s); + goto found; + } s = NULL; found: read_unlock_bh(&x25_list_lock); @@ -250,7 +261,7 @@ found: /* * Find a connected X.25 socket given my LCI and neighbour. */ -struct sock *__x25_find_socket(unsigned int lci, struct x25_neigh *nb) +static struct sock *__x25_find_socket(unsigned int lci, struct x25_neigh *nb) { struct sock *s; struct hlist_node *node; @@ -278,7 +289,7 @@ struct sock *x25_find_socket(unsigned int lci, struct x25_neigh *nb) /* * Find a unique LCI for a given device. */ -unsigned int x25_new_lci(struct x25_neigh *nb) +static unsigned int x25_new_lci(struct x25_neigh *nb) { unsigned int lci = 1; struct sock *sk; @@ -347,6 +358,7 @@ void x25_destroy_socket(struct sock *sk) /* Defer: outstanding buffers */ sk->sk_timer.expires = jiffies + 10 * HZ; sk->sk_timer.function = x25_destroy_timer; + sk->sk_timer.data = (unsigned long)sk; add_timer(&sk->sk_timer); } else { /* drop last reference so sock_put will free */ @@ -478,8 +490,10 @@ static int x25_create(struct socket *sock, int protocol) x25 = x25_sk(sk); - sock_init_data(sock, sk); - sk_set_owner(sk, THIS_MODULE); + sk->sk_socket = sock; + sk->sk_type = sock->type; + sk->sk_sleep = &sock->wait; + sock->sk = sk; x25_init_timers(sk); @@ -813,6 +827,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, struct x25_opt *makex25; struct x25_address source_addr, dest_addr; struct x25_facilities facilities; + struct x25_calluserdata calluserdata; int len, rc; /* @@ -827,9 +842,27 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); /* - * Find a listener for the particular address. + * Get the length of the facilities, skip past them for the moment + * get the call user data because this is needed to determine + * the correct listener */ - sk = x25_find_listener(&source_addr); + len = skb->data[0] + 1; + skb_pull(skb,len); + + /* + * Incoming Call User Data. + */ + if (skb->len >= 0) { + memcpy(calluserdata.cuddata, skb->data, skb->len); + calluserdata.cudlength = skb->len; + } + + skb_push(skb,len); + + /* + * Find a listener for the particular address/cud pair. + */ + sk = x25_find_listener(&source_addr,&calluserdata); /* * We can't accept the Call Request. @@ -858,7 +891,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, goto out_sock_put; /* - * Remove the facilities, leaving any Call User Data. + * Remove the facilities */ skb_pull(skb, len); @@ -872,17 +905,10 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, makex25->neighbour = nb; makex25->facilities = facilities; makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask; + makex25->calluserdata = calluserdata; x25_write_internal(make, X25_CALL_ACCEPTED); - /* - * Incoming Call User Data. - */ - if (skb->len >= 0) { - memcpy(makex25->calluserdata.cuddata, skb->data, skb->len); - makex25->calluserdata.cudlength = skb->len; - } - makex25->state = X25_STATE_3; sk->sk_ack_backlog++; @@ -1312,7 +1338,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return rc; } -struct net_proto_family x25_family_ops = { +static struct net_proto_family x25_family_ops = { .family = AF_X25, .create = x25_create, .owner = THIS_MODULE, @@ -1347,7 +1373,7 @@ static struct packet_type x25_packet_type = { .func = x25_lapb_receive_frame, }; -struct notifier_block x25_dev_notifier = { +static struct notifier_block x25_dev_notifier = { .notifier_call = x25_device_event, };