···56/* This header used to share core functionality between the standalone7 NAT module, and the compatibility layer's use of NAT for masquerading. */8-extern int ip_nat_init(void);9-extern void ip_nat_cleanup(void);1011-extern unsigned int nat_packet(struct ip_conntrack *ct,12 enum ip_conntrack_info conntrackinfo,13 unsigned int hooknum,14 struct sk_buff **pskb);1516-extern int icmp_reply_translation(struct sk_buff **pskb,17- struct ip_conntrack *ct,18- enum ip_nat_manip_type manip,19- enum ip_conntrack_dir dir);20#endif /* _IP_NAT_CORE_H */
···56/* This header used to share core functionality between the standalone7 NAT module, and the compatibility layer's use of NAT for masquerading. */0089+extern unsigned int ip_nat_packet(struct ip_conntrack *ct,10 enum ip_conntrack_info conntrackinfo,11 unsigned int hooknum,12 struct sk_buff **pskb);1314+extern int ip_nat_icmp_reply_translation(struct sk_buff **pskb,15+ struct ip_conntrack *ct,16+ enum ip_nat_manip_type manip,17+ enum ip_conntrack_dir dir);18#endif /* _IP_NAT_CORE_H */
···574 return dev;575}57600577struct net_device *dev_getfirstbyhwtype(unsigned short type)578{579 struct net_device *dev;
···574 return dev;575}576577+EXPORT_SYMBOL(dev_getbyhwaddr);578+579struct net_device *dev_getfirstbyhwtype(unsigned short type)580{581 struct net_device *dev;
+3-2
net/ipv4/netfilter/Makefile
···45# objects for the standalone - connection tracking / NAT6ip_conntrack-objs := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o7-iptable_nat-objs := ip_nat_standalone.o ip_nat_rule.o ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o089ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o10ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o···41# the three instances of ip_tables42obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o43obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o44-obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o45obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o4647# matches
···45# objects for the standalone - connection tracking / NAT6ip_conntrack-objs := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o7+ip_nat-objs := ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o8+iptable_nat-objs := ip_nat_rule.o ip_nat_standalone.o910ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o11ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o···40# the three instances of ip_tables41obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o42obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o43+obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o ip_nat.o44obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o4546# matches
+24-11
net/ipv4/netfilter/ip_nat_core.c
···7475 return p;76}07778void79ip_nat_proto_put(struct ip_nat_protocol *p)80{81 module_put(p->me);82}08384/* We keep an extra hash for each conntrack, for fast searching. */85static inline unsigned int···113 return csum_fold(csum_partial((char *)diffs, sizeof(diffs),114 oldcheck^0xFFFF));115}0116117/* Is this tuple already taken? (not by us) */118int···130 invert_tuplepr(&reply, tuple);131 return ip_conntrack_tuple_taken(&reply, ignored_conntrack);132}0133134/* If we source map this tuple so reply looks like reply_tuple, will135 * that meet the constraints of range. */···351352 return NF_ACCEPT;353}0354355/* Returns true if succeeded. */356static int···392}393394/* Do packet manipulations according to ip_nat_setup_info. */395-unsigned int nat_packet(struct ip_conntrack *ct,396- enum ip_conntrack_info ctinfo,397- unsigned int hooknum,398- struct sk_buff **pskb)399{400 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);401 unsigned long statusbit;···422 }423 return NF_ACCEPT;424}0425426/* Dir is direction ICMP is coming from (opposite to packet it contains) */427-int icmp_reply_translation(struct sk_buff **pskb,428- struct ip_conntrack *ct,429- enum ip_nat_manip_type manip,430- enum ip_conntrack_dir dir)431{432 struct {433 struct icmphdr icmp;···515516 return 1;517}0518519/* Protocol registration. */520int ip_nat_protocol_register(struct ip_nat_protocol *proto)···532 write_unlock_bh(&ip_nat_lock);533 return ret;534}0535536/* Noone stores the protocol anywhere; simply delete it. */537void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)···544 /* Someone could be still looking at the proto in a bh. */545 synchronize_net();546}0547548#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \549 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)···591EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr);592#endif593594-int __init ip_nat_init(void)595{596 size_t i;597···633 return 0;634}635636-/* Not __exit: called from ip_nat_standalone.c:init_or_cleanup() --RR */637-void ip_nat_cleanup(void)638{639 ip_ct_iterate_cleanup(&clean_nat, NULL);640 ip_conntrack_destroyed = NULL;641 vfree(bysource);642}00000
···7475 return p;76}77+EXPORT_SYMBOL_GPL(ip_nat_proto_find_get);7879void80ip_nat_proto_put(struct ip_nat_protocol *p)81{82 module_put(p->me);83}84+EXPORT_SYMBOL_GPL(ip_nat_proto_put);8586/* We keep an extra hash for each conntrack, for fast searching. */87static inline unsigned int···111 return csum_fold(csum_partial((char *)diffs, sizeof(diffs),112 oldcheck^0xFFFF));113}114+EXPORT_SYMBOL(ip_nat_cheat_check);115116/* Is this tuple already taken? (not by us) */117int···127 invert_tuplepr(&reply, tuple);128 return ip_conntrack_tuple_taken(&reply, ignored_conntrack);129}130+EXPORT_SYMBOL(ip_nat_used_tuple);131132/* If we source map this tuple so reply looks like reply_tuple, will133 * that meet the constraints of range. */···347348 return NF_ACCEPT;349}350+EXPORT_SYMBOL(ip_nat_setup_info);351352/* Returns true if succeeded. */353static int···387}388389/* Do packet manipulations according to ip_nat_setup_info. */390+unsigned int ip_nat_packet(struct ip_conntrack *ct,391+ enum ip_conntrack_info ctinfo,392+ unsigned int hooknum,393+ struct sk_buff **pskb)394{395 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);396 unsigned long statusbit;···417 }418 return NF_ACCEPT;419}420+EXPORT_SYMBOL_GPL(ip_nat_packet);421422/* Dir is direction ICMP is coming from (opposite to packet it contains) */423+int ip_nat_icmp_reply_translation(struct sk_buff **pskb,424+ struct ip_conntrack *ct,425+ enum ip_nat_manip_type manip,426+ enum ip_conntrack_dir dir)427{428 struct {429 struct icmphdr icmp;···509510 return 1;511}512+EXPORT_SYMBOL_GPL(ip_nat_icmp_reply_translation);513514/* Protocol registration. */515int ip_nat_protocol_register(struct ip_nat_protocol *proto)···525 write_unlock_bh(&ip_nat_lock);526 return ret;527}528+EXPORT_SYMBOL(ip_nat_protocol_register);529530/* Noone stores the protocol anywhere; simply delete it. */531void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)···536 /* Someone could be still looking at the proto in a bh. */537 synchronize_net();538}539+EXPORT_SYMBOL(ip_nat_protocol_unregister);540541#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \542 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)···582EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr);583#endif584585+static int __init ip_nat_init(void)586{587 size_t i;588···624 return 0;625}626627+static void __exit ip_nat_cleanup(void)0628{629 ip_ct_iterate_cleanup(&clean_nat, NULL);630 ip_conntrack_destroyed = NULL;631 vfree(bysource);632}633+634+MODULE_LICENSE("GPL");635+636+module_init(ip_nat_init);637+module_exit(ip_nat_cleanup);
+4
net/ipv4/netfilter/ip_nat_helper.c
···199 }200 return 1;201}0202203/* Generic function for mangling variable-length address changes inside204 * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX···257258 return 1;259}0260261/* Adjust one found SACK option including checksum correction */262static void···401402 return 1;403}0404405/* Setup NAT on this expected conntrack so it follows master. */406/* If we fail to get a free NAT slot, we'll get dropped on confirm */···428 /* hook doesn't matter, but it has to do destination manip */429 ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);430}0
···199 }200 return 1;201}202+EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);203204/* Generic function for mangling variable-length address changes inside205 * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX···256257 return 1;258}259+EXPORT_SYMBOL(ip_nat_mangle_udp_packet);260261/* Adjust one found SACK option including checksum correction */262static void···399400 return 1;401}402+EXPORT_SYMBOL(ip_nat_seq_adjust);403404/* Setup NAT on this expected conntrack so it follows master. */405/* If we fail to get a free NAT slot, we'll get dropped on confirm */···425 /* hook doesn't matter, but it has to do destination manip */426 ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);427}428+EXPORT_SYMBOL(ip_nat_follow_master);
+4-21
net/ipv4/netfilter/ip_nat_standalone.c
···108 case IP_CT_RELATED:109 case IP_CT_RELATED+IP_CT_IS_REPLY:110 if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {111- if (!icmp_reply_translation(pskb, ct, maniptype,112- CTINFO2DIR(ctinfo)))113 return NF_DROP;114 else115 return NF_ACCEPT;···152 }153154 IP_NF_ASSERT(info);155- return nat_packet(ct, ctinfo, hooknum, pskb);156}157158static unsigned int···325 printk("ip_nat_init: can't setup rules.\n");326 goto cleanup_nothing;327 }328- ret = ip_nat_init();329- if (ret < 0) {330- printk("ip_nat_init: can't setup rules.\n");331- goto cleanup_rule_init;332- }333 ret = nf_register_hook(&ip_nat_in_ops);334 if (ret < 0) {335 printk("ip_nat_init: can't register in hook.\n");336- goto cleanup_nat;337 }338 ret = nf_register_hook(&ip_nat_out_ops);339 if (ret < 0) {···369 nf_unregister_hook(&ip_nat_out_ops);370 cleanup_inops:371 nf_unregister_hook(&ip_nat_in_ops);372- cleanup_nat:373- ip_nat_cleanup();374 cleanup_rule_init:375 ip_nat_rule_cleanup();376 cleanup_nothing:···388module_init(init);389module_exit(fini);390391-EXPORT_SYMBOL(ip_nat_setup_info);392-EXPORT_SYMBOL(ip_nat_protocol_register);393-EXPORT_SYMBOL(ip_nat_protocol_unregister);394-EXPORT_SYMBOL_GPL(ip_nat_proto_find_get);395-EXPORT_SYMBOL_GPL(ip_nat_proto_put);396-EXPORT_SYMBOL(ip_nat_cheat_check);397-EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);398-EXPORT_SYMBOL(ip_nat_mangle_udp_packet);399-EXPORT_SYMBOL(ip_nat_used_tuple);400-EXPORT_SYMBOL(ip_nat_follow_master);401MODULE_LICENSE("GPL");
···108 case IP_CT_RELATED:109 case IP_CT_RELATED+IP_CT_IS_REPLY:110 if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {111+ if (!ip_nat_icmp_reply_translation(pskb, ct, maniptype,112+ CTINFO2DIR(ctinfo)))113 return NF_DROP;114 else115 return NF_ACCEPT;···152 }153154 IP_NF_ASSERT(info);155+ return ip_nat_packet(ct, ctinfo, hooknum, pskb);156}157158static unsigned int···325 printk("ip_nat_init: can't setup rules.\n");326 goto cleanup_nothing;327 }00000328 ret = nf_register_hook(&ip_nat_in_ops);329 if (ret < 0) {330 printk("ip_nat_init: can't register in hook.\n");331+ goto cleanup_rule_init;332 }333 ret = nf_register_hook(&ip_nat_out_ops);334 if (ret < 0) {···374 nf_unregister_hook(&ip_nat_out_ops);375 cleanup_inops:376 nf_unregister_hook(&ip_nat_in_ops);00377 cleanup_rule_init:378 ip_nat_rule_cleanup();379 cleanup_nothing:···395module_init(init);396module_exit(fini);3970000000000398MODULE_LICENSE("GPL");
+2
net/ipv6/addrconf.c
···3520 if (err)3521 return err;3522003523 register_netdevice_notifier(&ipv6_dev_notf);35243525#ifdef CONFIG_IPV6_PRIVACY
···3520 if (err)3521 return err;35223523+ ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev);3524+3525 register_netdevice_notifier(&ipv6_dev_notf);35263527#ifdef CONFIG_IPV6_PRIVACY
···21 * See the GNU General Public License for more details.22 */23#include <linux/config.h>024#include <linux/kernel.h>25#include <linux/module.h>26#include <linux/rtnetlink.h>···38static struct sockaddr_llc llc_ui_addrnull;39static struct proto_ops llc_ui_ops;4041-static int llc_ui_wait_for_conn(struct sock *sk, int timeout);42-static int llc_ui_wait_for_disc(struct sock *sk, int timeout);43-static int llc_ui_wait_for_data(struct sock *sk, int timeout);44-static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout);4546#if 047#define dprintk(args...) printk(KERN_DEBUG args)···116 struct llc_sock* llc = llc_sk(sk);117 int rc = 0;118119- if (llc_data_accept_state(llc->state) || llc->p_flag) {120- int timeout = sock_sndtimeo(sk, noblock);121122 rc = llc_ui_wait_for_busy_core(sk, timeout);123 }124- if (!rc)125 rc = llc_build_and_send_pkt(sk, skb);126 return rc;127}···155 struct sock *sk;156 int rc = -ESOCKTNOSUPPORT;157158- if (sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM) {159 rc = -ENOMEM;160 sk = llc_sk_alloc(PF_LLC, GFP_KERNEL, &llc_proto);161 if (sk) {···177 struct sock *sk = sock->sk;178 struct llc_sock *llc;179180- if (!sk)181 goto out;182 sock_hold(sk);183 lock_sock(sk);···189 if (!sock_flag(sk, SOCK_ZAPPED))190 llc_sap_remove_socket(llc->sap, sk);191 release_sock(sk);192- if (llc->sap && hlist_empty(&llc->sap->sk_list.list)) {193- llc_release_sockets(llc->sap);194- llc_sap_close(llc->sap);195- }196 if (llc->dev)197 dev_put(llc->dev);198 sock_put(sk);···217 llc_ui_sap_last_autoport = i + 2;218 goto out;219 }0220 }221 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;222 tries++;···228}229230/**231- * llc_ui_autobind - Bind a socket to a specific address.232- * @sk: Socket to bind an address to.233- * @addr: Address the user wants the socket bound to.234 *235- * Bind a socket to a specific address. For llc a user is able to bind to236- * a specific sap only or mac + sap. If the user only specifies a sap and237- * a null dmac (all zeros) the user is attempting to bind to an entire238- * sap. This will stop anyone else on the local system from using that239- * sap. If someone else has a mac + sap open the bind to null + sap will240- * fail.241- * If the user desires to bind to a specific mac + sap, it is possible to242- * have multiple sap connections via multiple macs.243- * Bind and autobind for that matter must enforce the correct sap usage244- * otherwise all hell will break loose.245 * Returns: 0 upon success, negative otherwise.246 */247static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)···275 * @addrlen: Length of the uaddr structure.276 *277 * Bind a socket to a specific address. For llc a user is able to bind to278- * a specific sap only or mac + sap. If the user only specifies a sap and279- * a null dmac (all zeros) the user is attempting to bind to an entire280- * sap. This will stop anyone else on the local system from using that281- * sap. If someone else has a mac + sap open the bind to null + sap will282- * fail.283 * If the user desires to bind to a specific mac + sap, it is possible to284 * have multiple sap connections via multiple macs.285 * Bind and autobind for that matter must enforce the correct sap usage···291 int rc = -EINVAL;292293 dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap);294- if (!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr))295 goto out;296 rc = -EAFNOSUPPORT;297- if (addr->sllc_family != AF_LLC)000000298 goto out;299 if (!addr->sllc_sap) {300 rc = -EUSERS;···314 rc = -EBUSY; /* some other network layer is using the sap */315 if (!sap)316 goto out;0317 } else {318 struct llc_addr laddr, daddr;319 struct sock *ask;···331 ask = llc_lookup_established(sap, &daddr, &laddr);332 if (ask) {333 sock_put(ask);334- goto out;335 }336 }337 llc->laddr.lsap = addr->sllc_sap;···341 llc_sap_add_socket(sap, sk);342 sock_reset_flag(sk, SOCK_ZAPPED);343 rc = 0;00344out:345 return rc;346}···364 int rc = -ENOTCONN;365366 lock_sock(sk);367- if (sk->sk_state != TCP_ESTABLISHED)368 goto out;369 rc = -EINVAL;370 if (how != 2)···399 struct sock *sk = sock->sk;400 struct llc_sock *llc = llc_sk(sk);401 struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;402- struct net_device *dev;403 int rc = -EINVAL;404405 lock_sock(sk);406- if (addrlen != sizeof(*addr))407 goto out;408 rc = -EAFNOSUPPORT;409- if (addr->sllc_family != AF_LLC)00000410 goto out;411 /* bind connection to sap if user hasn't done it. */412 if (sock_flag(sk, SOCK_ZAPPED)) {···418 rc = llc_ui_autobind(sock, addr);419 if (rc)420 goto out;421- llc->daddr.lsap = addr->sllc_sap;422- memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN);423 }424- dev = llc->dev;425- if (sk->sk_type != SOCK_STREAM)426- goto out;427- rc = -EALREADY;428- if (sock->state == SS_CONNECTING)429- goto out;430 sock->state = SS_CONNECTING;431 sk->sk_state = TCP_SYN_SENT;432 llc->link = llc_ui_next_link_no(llc->sap->laddr.lsap);433- rc = llc_establish_connection(sk, dev->dev_addr,434 addr->sllc_mac, addr->sllc_sap);435 if (rc) {436 dprintk("%s: llc_ui_send_conn failed :-(\n", __FUNCTION__);···432 sk->sk_state = TCP_CLOSE;433 goto out;434 }435- rc = llc_ui_wait_for_conn(sk, sk->sk_rcvtimeo);436- if (rc)437- dprintk("%s: llc_ui_wait_for_conn failed=%d\n", __FUNCTION__, rc);00000000000000438out:439 release_sock(sk);440 return rc;0000441}442443/**···472 int rc = -EINVAL;473474 lock_sock(sk);475- if (sock->state != SS_UNCONNECTED)476 goto out;477 rc = -EOPNOTSUPP;478- if (sk->sk_type != SOCK_STREAM)479 goto out;480 rc = -EAGAIN;481 if (sock_flag(sk, SOCK_ZAPPED))···494 return rc;495}496497-static int llc_ui_wait_for_disc(struct sock *sk, int timeout)498{499- DECLARE_WAITQUEUE(wait, current);500- int rc;501-502- add_wait_queue_exclusive(sk->sk_sleep, &wait);503- for (;;) {504- __set_current_state(TASK_INTERRUPTIBLE);505- rc = 0;506- if (sk->sk_state != TCP_CLOSE) {507- release_sock(sk);508- timeout = schedule_timeout(timeout);509- lock_sock(sk);510- } else511- break;512- rc = -ERESTARTSYS;513- if (signal_pending(current))514- break;515- rc = -EAGAIN;516- if (!timeout)517- break;518- }519- __set_current_state(TASK_RUNNING);520- remove_wait_queue(sk->sk_sleep, &wait);521- return rc;522-}523-524-static int llc_ui_wait_for_conn(struct sock *sk, int timeout)525-{526- DECLARE_WAITQUEUE(wait, current);527- int rc;528-529- add_wait_queue_exclusive(sk->sk_sleep, &wait);530- for (;;) {531- __set_current_state(TASK_INTERRUPTIBLE);532- rc = -EAGAIN;533- if (sk->sk_state == TCP_CLOSE)534- break;535- rc = 0;536- if (sk->sk_state != TCP_ESTABLISHED) {537- release_sock(sk);538- timeout = schedule_timeout(timeout);539- lock_sock(sk);540- } else541- break;542- rc = -ERESTARTSYS;543- if (signal_pending(current))544- break;545- rc = -EAGAIN;546- if (!timeout)547- break;548- }549- __set_current_state(TASK_RUNNING);550- remove_wait_queue(sk->sk_sleep, &wait);551- return rc;552-}553-554-static int llc_ui_wait_for_data(struct sock *sk, int timeout)555-{556- DECLARE_WAITQUEUE(wait, current);557 int rc = 0;558559- add_wait_queue_exclusive(sk->sk_sleep, &wait);560- for (;;) {561- __set_current_state(TASK_INTERRUPTIBLE);562- if (sk->sk_shutdown & RCV_SHUTDOWN)563- break;564- /*565- * Well, if we have backlog, try to process it now.566- */567- if (sk->sk_backlog.tail) {568- release_sock(sk);569- lock_sock(sk);570- }571- rc = 0;572- if (skb_queue_empty(&sk->sk_receive_queue)) {573- release_sock(sk);574- timeout = schedule_timeout(timeout);575- lock_sock(sk);576- } else577 break;578 rc = -ERESTARTSYS;579 if (signal_pending(current))···509 rc = -EAGAIN;510 if (!timeout)511 break;0512 }513- __set_current_state(TASK_RUNNING);514- remove_wait_queue(sk->sk_sleep, &wait);515 return rc;516}517518-static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout)519{520- DECLARE_WAITQUEUE(wait, current);000000000000000521 struct llc_sock *llc = llc_sk(sk);522 int rc;523524- add_wait_queue_exclusive(sk->sk_sleep, &wait);525- for (;;) {526- dprintk("%s: looping...\n", __FUNCTION__);527- __set_current_state(TASK_INTERRUPTIBLE);528- rc = -ENOTCONN;529- if (sk->sk_shutdown & RCV_SHUTDOWN)530- break;531 rc = 0;532- if (llc_data_accept_state(llc->state) || llc->p_flag) {533- release_sock(sk);534- timeout = schedule_timeout(timeout);535- lock_sock(sk);536- } else537 break;538 rc = -ERESTARTSYS;539 if (signal_pending(current))···551 if (!timeout)552 break;553 }554- __set_current_state(TASK_RUNNING);555- remove_wait_queue(sk->sk_sleep, &wait);000000000000000000000000000556 return rc;557}558···602 dprintk("%s: accepting on %02X\n", __FUNCTION__,603 llc_sk(sk)->laddr.lsap);604 lock_sock(sk);605- if (sk->sk_type != SOCK_STREAM)606 goto out;607 rc = -EINVAL;608- if (sock->state != SS_UNCONNECTED || sk->sk_state != TCP_LISTEN)0609 goto out;610 /* wait for a connection to arrive. */611- rc = llc_ui_wait_for_data(sk, sk->sk_rcvtimeo);612- if (rc)613- goto out;00614 dprintk("%s: got a new connection on %02X\n", __FUNCTION__,615 llc_sk(sk)->laddr.lsap);616 skb = skb_dequeue(&sk->sk_receive_queue);···635 /* put original socket back into a clean listen state. */636 sk->sk_state = TCP_LISTEN;637 sk->sk_ack_backlog--;638- skb->sk = NULL;639 dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__,640 llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap);641frees:···648 * llc_ui_recvmsg - copy received data to the socket user.649 * @sock: Socket to copy data from.650 * @msg: Various user space related information.651- * @size: Size of user buffer.652 * @flags: User specified flags.653 *654 * Copy received data to the socket user.655 * Returns non-negative upon success, negative otherwise.656 */657static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,658- struct msghdr *msg, size_t size, int flags)659{660- struct sock *sk = sock->sk;661 struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name;662- struct sk_buff *skb;000663 size_t copied = 0;664- int rc = -ENOMEM, timeout;665- int noblock = flags & MSG_DONTWAIT;000666667- dprintk("%s: receiving in %02X from %02X\n", __FUNCTION__,668- llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap);669 lock_sock(sk);670- timeout = sock_rcvtimeo(sk, noblock);671- rc = llc_ui_wait_for_data(sk, timeout);672- if (rc) {673- dprintk("%s: llc_ui_wait_for_data failed recv "674- "in %02X from %02X\n", __FUNCTION__,675- llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap);676 goto out;677- }678- skb = skb_dequeue(&sk->sk_receive_queue);679- if (!skb) /* shutdown */680- goto out;681- copied = skb->len;682- if (copied > size)683- copied = size;684- rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);685- if (rc)686- goto dgram_free;687- if (skb->len > copied) {688- skb_pull(skb, copied);689- skb_queue_head(&sk->sk_receive_queue, skb);690- }691- if (uaddr)692- memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));693- msg->msg_namelen = sizeof(*uaddr);694- if (!skb->next) {695-dgram_free:696- kfree_skb(skb);697- }0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000698out:699 release_sock(sk);700- return rc ? : copied;000000701}702703/**···828 struct sockaddr_llc *addr = (struct sockaddr_llc *)msg->msg_name;829 int flags = msg->msg_flags;830 int noblock = flags & MSG_DONTWAIT;831- struct net_device *dev;832 struct sk_buff *skb;833 size_t size = 0;834 int rc = -EINVAL, copied = 0, hdrlen;···850 if (rc)851 goto release;852 }853- dev = llc->dev;854- hdrlen = dev->hard_header_len + llc_ui_header_len(sk, addr);855 size = hdrlen + len;856- if (size > dev->mtu)857- size = dev->mtu;858 copied = size - hdrlen;859 release_sock(sk);860 skb = sock_alloc_send_skb(sk, size, noblock, &rc);861 lock_sock(sk);862 if (!skb)863 goto release;864- skb->sk = sk;865- skb->dev = dev;866 skb->protocol = llc_proto_type(addr->sllc_arphrd);867 skb_reserve(skb, hdrlen); 868 rc = memcpy_fromiovec(skb_put(skb, copied), msg->msg_iov, copied);···885 if (!(sk->sk_type == SOCK_STREAM && !addr->sllc_ua))886 goto out;887 rc = llc_ui_send_data(sk, skb, noblock);888- if (rc)889- dprintk("%s: llc_ui_send_data failed: %d\n", __FUNCTION__, rc);890out:891- if (rc)892 kfree_skb(skb);893release:894- if (rc)895 dprintk("%s: failed sending from %02X to %02X: %d\n",896 __FUNCTION__, llc->laddr.lsap, llc->daddr.lsap, rc);0897 release_sock(sk);898 return rc ? : copied;899}···978 int rc = -EINVAL, opt;979980 lock_sock(sk);981- if (level != SOL_LLC || optlen != sizeof(int))982 goto out;983 rc = get_user(opt, (int __user *)optval);984 if (rc)···998 case LLC_OPT_ACK_TMR_EXP:999 if (opt > LLC_OPT_MAX_ACK_TMR_EXP)1000 goto out;1001- llc->ack_timer.expire = opt;1002 break;1003 case LLC_OPT_P_TMR_EXP:1004 if (opt > LLC_OPT_MAX_P_TMR_EXP)1005 goto out;1006- llc->pf_cycle_timer.expire = opt;1007 break;1008 case LLC_OPT_REJ_TMR_EXP:1009 if (opt > LLC_OPT_MAX_REJ_TMR_EXP)1010 goto out;1011- llc->rej_sent_timer.expire = opt;1012 break;1013 case LLC_OPT_BUSY_TMR_EXP:1014 if (opt > LLC_OPT_MAX_BUSY_TMR_EXP)1015 goto out;1016- llc->busy_state_timer.expire = opt;1017 break;1018 case LLC_OPT_TX_WIN:1019 if (opt > LLC_OPT_MAX_WIN)···1053 int val = 0, len = 0, rc = -EINVAL;10541055 lock_sock(sk);1056- if (level != SOL_LLC)1057 goto out;1058 rc = get_user(len, optlen);1059 if (rc)···1063 goto out;1064 switch (optname) {1065 case LLC_OPT_RETRY:1066- val = llc->n2; break;1067 case LLC_OPT_SIZE:1068- val = llc->n1; break;1069 case LLC_OPT_ACK_TMR_EXP:1070- val = llc->ack_timer.expire; break;1071 case LLC_OPT_P_TMR_EXP:1072- val = llc->pf_cycle_timer.expire; break;1073 case LLC_OPT_REJ_TMR_EXP:1074- val = llc->rej_sent_timer.expire; break;1075 case LLC_OPT_BUSY_TMR_EXP:1076- val = llc->busy_state_timer.expire; break;1077 case LLC_OPT_TX_WIN:1078 val = llc->k; break;1079 case LLC_OPT_RX_WIN:···1117 .sendpage = sock_no_sendpage,1118};11191120-extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb);1121-extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb);000011221123static int __init llc2_init(void)1124{···1135 llc_station_init();1136 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;1137 rc = llc_proc_init();1138- if (rc != 0)01139 goto out_unregister_llc_proto;1140- sock_register(&llc_ui_family_ops);00000000001141 llc_add_pack(LLC_DEST_SAP, llc_sap_handler);1142 llc_add_pack(LLC_DEST_CONN, llc_conn_handler);1143out:1144 return rc;00001145out_unregister_llc_proto:1146 proto_unregister(&llc_proto);1147 goto out;···1169 llc_remove_pack(LLC_DEST_CONN);1170 sock_unregister(PF_LLC);1171 llc_proc_exit();01172 proto_unregister(&llc_proto);1173}1174
···21 * See the GNU General Public License for more details.22 */23#include <linux/config.h>24+#include <linux/compiler.h>25#include <linux/kernel.h>26#include <linux/module.h>27#include <linux/rtnetlink.h>···37static struct sockaddr_llc llc_ui_addrnull;38static struct proto_ops llc_ui_ops;3940+static int llc_ui_wait_for_conn(struct sock *sk, long timeout);41+static int llc_ui_wait_for_disc(struct sock *sk, long timeout);42+static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout);04344#if 045#define dprintk(args...) printk(KERN_DEBUG args)···116 struct llc_sock* llc = llc_sk(sk);117 int rc = 0;118119+ if (unlikely(llc_data_accept_state(llc->state) || llc->p_flag)) {120+ long timeout = sock_sndtimeo(sk, noblock);121122 rc = llc_ui_wait_for_busy_core(sk, timeout);123 }124+ if (unlikely(!rc))125 rc = llc_build_and_send_pkt(sk, skb);126 return rc;127}···155 struct sock *sk;156 int rc = -ESOCKTNOSUPPORT;157158+ if (likely(sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM)) {159 rc = -ENOMEM;160 sk = llc_sk_alloc(PF_LLC, GFP_KERNEL, &llc_proto);161 if (sk) {···177 struct sock *sk = sock->sk;178 struct llc_sock *llc;179180+ if (unlikely(sk == NULL))181 goto out;182 sock_hold(sk);183 lock_sock(sk);···189 if (!sock_flag(sk, SOCK_ZAPPED))190 llc_sap_remove_socket(llc->sap, sk);191 release_sock(sk);0000192 if (llc->dev)193 dev_put(llc->dev);194 sock_put(sk);···221 llc_ui_sap_last_autoport = i + 2;222 goto out;223 }224+ llc_sap_put(sap);225 }226 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;227 tries++;···231}232233/**234+ * llc_ui_autobind - automatically bind a socket to a sap235+ * @sock: socket to bind236+ * @addr: address to connect to237 *238+ * Used by llc_ui_connect and llc_ui_sendmsg when the user hasn't239+ * specifically used llc_ui_bind to bind to an specific address/sap240+ *0000000241 * Returns: 0 upon success, negative otherwise.242 */243static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)···285 * @addrlen: Length of the uaddr structure.286 *287 * Bind a socket to a specific address. For llc a user is able to bind to288+ * a specific sap only or mac + sap.0000289 * If the user desires to bind to a specific mac + sap, it is possible to290 * have multiple sap connections via multiple macs.291 * Bind and autobind for that matter must enforce the correct sap usage···305 int rc = -EINVAL;306307 dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap);308+ if (unlikely(!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr)))309 goto out;310 rc = -EAFNOSUPPORT;311+ if (unlikely(addr->sllc_family != AF_LLC))312+ goto out;313+ rc = -ENODEV;314+ rtnl_lock();315+ llc->dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_mac);316+ rtnl_unlock();317+ if (!llc->dev)318 goto out;319 if (!addr->sllc_sap) {320 rc = -EUSERS;···322 rc = -EBUSY; /* some other network layer is using the sap */323 if (!sap)324 goto out;325+ llc_sap_hold(sap);326 } else {327 struct llc_addr laddr, daddr;328 struct sock *ask;···338 ask = llc_lookup_established(sap, &daddr, &laddr);339 if (ask) {340 sock_put(ask);341+ goto out_put;342 }343 }344 llc->laddr.lsap = addr->sllc_sap;···348 llc_sap_add_socket(sap, sk);349 sock_reset_flag(sk, SOCK_ZAPPED);350 rc = 0;351+out_put:352+ llc_sap_put(sap);353out:354 return rc;355}···369 int rc = -ENOTCONN;370371 lock_sock(sk);372+ if (unlikely(sk->sk_state != TCP_ESTABLISHED))373 goto out;374 rc = -EINVAL;375 if (how != 2)···404 struct sock *sk = sock->sk;405 struct llc_sock *llc = llc_sk(sk);406 struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;0407 int rc = -EINVAL;408409 lock_sock(sk);410+ if (unlikely(addrlen != sizeof(*addr)))411 goto out;412 rc = -EAFNOSUPPORT;413+ if (unlikely(addr->sllc_family != AF_LLC))414+ goto out;415+ if (unlikely(sk->sk_type != SOCK_STREAM))416+ goto out;417+ rc = -EALREADY;418+ if (unlikely(sock->state == SS_CONNECTING))419 goto out;420 /* bind connection to sap if user hasn't done it. */421 if (sock_flag(sk, SOCK_ZAPPED)) {···419 rc = llc_ui_autobind(sock, addr);420 if (rc)421 goto out;00422 }423+ llc->daddr.lsap = addr->sllc_sap;424+ memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN);0000425 sock->state = SS_CONNECTING;426 sk->sk_state = TCP_SYN_SENT;427 llc->link = llc_ui_next_link_no(llc->sap->laddr.lsap);428+ rc = llc_establish_connection(sk, llc->dev->dev_addr,429 addr->sllc_mac, addr->sllc_sap);430 if (rc) {431 dprintk("%s: llc_ui_send_conn failed :-(\n", __FUNCTION__);···439 sk->sk_state = TCP_CLOSE;440 goto out;441 }442+443+ if (sk->sk_state == TCP_SYN_SENT) {444+ const long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);445+446+ if (!timeo || !llc_ui_wait_for_conn(sk, timeo))447+ goto out;448+449+ rc = sock_intr_errno(timeo);450+ if (signal_pending(current))451+ goto out;452+ }453+454+ if (sk->sk_state == TCP_CLOSE)455+ goto sock_error;456+457+ sock->state = SS_CONNECTED;458+ rc = 0;459out:460 release_sock(sk);461 return rc;462+sock_error:463+ rc = sock_error(sk) ? : -ECONNABORTED;464+ sock->state = SS_UNCONNECTED;465+ goto out;466}467468/**···461 int rc = -EINVAL;462463 lock_sock(sk);464+ if (unlikely(sock->state != SS_UNCONNECTED))465 goto out;466 rc = -EOPNOTSUPP;467+ if (unlikely(sk->sk_type != SOCK_STREAM))468 goto out;469 rc = -EAGAIN;470 if (sock_flag(sk, SOCK_ZAPPED))···483 return rc;484}485486+static int llc_ui_wait_for_disc(struct sock *sk, long timeout)487{488+ DEFINE_WAIT(wait);000000000000000000000000000000000000000000000000000000000489 int rc = 0;490491+ while (1) {492+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);493+ if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE))000000000000000494 break;495 rc = -ERESTARTSYS;496 if (signal_pending(current))···570 rc = -EAGAIN;571 if (!timeout)572 break;573+ rc = 0;574 }575+ finish_wait(sk->sk_sleep, &wait);0576 return rc;577}578579+static int llc_ui_wait_for_conn(struct sock *sk, long timeout)580{581+ DEFINE_WAIT(wait);582+583+ while (1) {584+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);585+ if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT))586+ break;587+ if (signal_pending(current) || !timeout)588+ break;589+ }590+ finish_wait(sk->sk_sleep, &wait);591+ return timeout;592+}593+594+static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout)595+{596+ DEFINE_WAIT(wait);597 struct llc_sock *llc = llc_sk(sk);598 int rc;599600+ while (1) {601+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);00000602 rc = 0;603+ if (sk_wait_event(sk, &timeout,604+ (sk->sk_shutdown & RCV_SHUTDOWN) ||605+ (!llc_data_accept_state(llc->state) &&606+ !llc->p_flag)))0607 break;608 rc = -ERESTARTSYS;609 if (signal_pending(current))···603 if (!timeout)604 break;605 }606+ finish_wait(sk->sk_sleep, &wait);607+ return rc;608+}609+610+static int llc_wait_data(struct sock *sk, long timeo)611+{612+ int rc;613+614+ while (1) {615+ /*616+ * POSIX 1003.1g mandates this order.617+ */618+ if (sk->sk_err) {619+ rc = sock_error(sk);620+ break;621+ }622+ rc = 0;623+ if (sk->sk_shutdown & RCV_SHUTDOWN)624+ break;625+ rc = -EAGAIN;626+ if (!timeo)627+ break;628+ rc = sock_intr_errno(timeo);629+ if (signal_pending(current))630+ break;631+ rc = 0;632+ if (sk_wait_data(sk, &timeo))633+ break;634+ }635 return rc;636}637···627 dprintk("%s: accepting on %02X\n", __FUNCTION__,628 llc_sk(sk)->laddr.lsap);629 lock_sock(sk);630+ if (unlikely(sk->sk_type != SOCK_STREAM))631 goto out;632 rc = -EINVAL;633+ if (unlikely(sock->state != SS_UNCONNECTED ||634+ sk->sk_state != TCP_LISTEN))635 goto out;636 /* wait for a connection to arrive. */637+ if (skb_queue_empty(&sk->sk_receive_queue)) {638+ rc = llc_wait_data(sk, sk->sk_rcvtimeo);639+ if (rc)640+ goto out;641+ }642 dprintk("%s: got a new connection on %02X\n", __FUNCTION__,643 llc_sk(sk)->laddr.lsap);644 skb = skb_dequeue(&sk->sk_receive_queue);···657 /* put original socket back into a clean listen state. */658 sk->sk_state = TCP_LISTEN;659 sk->sk_ack_backlog--;0660 dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__,661 llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap);662frees:···671 * llc_ui_recvmsg - copy received data to the socket user.672 * @sock: Socket to copy data from.673 * @msg: Various user space related information.674+ * @len: Size of user buffer.675 * @flags: User specified flags.676 *677 * Copy received data to the socket user.678 * Returns non-negative upon success, negative otherwise.679 */680static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,681+ struct msghdr *msg, size_t len, int flags)682{0683 struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name;684+ const int nonblock = flags & MSG_DONTWAIT;685+ struct sk_buff *skb = NULL;686+ struct sock *sk = sock->sk;687+ struct llc_sock *llc = llc_sk(sk);688 size_t copied = 0;689+ u32 peek_seq = 0;690+ u32 *seq;691+ unsigned long used;692+ int target; /* Read at least this many bytes */693+ long timeo;69400695 lock_sock(sk);696+ copied = -ENOTCONN;697+ if (sk->sk_state == TCP_LISTEN)0000698 goto out;699+700+ timeo = sock_rcvtimeo(sk, nonblock);701+702+ seq = &llc->copied_seq;703+ if (flags & MSG_PEEK) {704+ peek_seq = llc->copied_seq;705+ seq = &peek_seq;706+ }707+708+ target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);709+ copied = 0;710+711+ do {712+ u32 offset;713+714+ /*715+ * We need to check signals first, to get correct SIGURG716+ * handling. FIXME: Need to check this doesn't impact 1003.1g717+ * and move it down to the bottom of the loop718+ */719+ if (signal_pending(current)) {720+ if (copied)721+ break;722+ copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;723+ break;724+ }725+726+ /* Next get a buffer. */727+728+ skb = skb_peek(&sk->sk_receive_queue);729+ if (skb) {730+ offset = *seq;731+ goto found_ok_skb;732+ }733+ /* Well, if we have backlog, try to process it now yet. */734+735+ if (copied >= target && !sk->sk_backlog.tail)736+ break;737+738+ if (copied) {739+ if (sk->sk_err ||740+ sk->sk_state == TCP_CLOSE ||741+ (sk->sk_shutdown & RCV_SHUTDOWN) ||742+ !timeo ||743+ (flags & MSG_PEEK))744+ break;745+ } else {746+ if (sock_flag(sk, SOCK_DONE))747+ break;748+749+ if (sk->sk_err) {750+ copied = sock_error(sk);751+ break;752+ }753+ if (sk->sk_shutdown & RCV_SHUTDOWN)754+ break;755+756+ if (sk->sk_state == TCP_CLOSE) {757+ if (!sock_flag(sk, SOCK_DONE)) {758+ /*759+ * This occurs when user tries to read760+ * from never connected socket.761+ */762+ copied = -ENOTCONN;763+ break;764+ }765+ break;766+ }767+ if (!timeo) {768+ copied = -EAGAIN;769+ break;770+ }771+ }772+773+ if (copied >= target) { /* Do not sleep, just process backlog. */774+ release_sock(sk);775+ lock_sock(sk);776+ } else777+ sk_wait_data(sk, &timeo);778+779+ if ((flags & MSG_PEEK) && peek_seq != llc->copied_seq) {780+ if (net_ratelimit())781+ printk(KERN_DEBUG "LLC(%s:%d): Application "782+ "bug, race in MSG_PEEK.\n",783+ current->comm, current->pid);784+ peek_seq = llc->copied_seq;785+ }786+ continue;787+ found_ok_skb:788+ /* Ok so how much can we use? */789+ used = skb->len - offset;790+ if (len < used)791+ used = len;792+793+ if (!(flags & MSG_TRUNC)) {794+ int rc = skb_copy_datagram_iovec(skb, offset,795+ msg->msg_iov, used);796+ if (rc) {797+ /* Exception. Bailout! */798+ if (!copied)799+ copied = -EFAULT;800+ break;801+ }802+ }803+804+ *seq += used;805+ copied += used;806+ len -= used;807+808+ if (used + offset < skb->len)809+ continue;810+811+ if (!(flags & MSG_PEEK)) {812+ sk_eat_skb(sk, skb);813+ *seq = 0;814+ }815+ } while (len > 0);816+817+ /* 818+ * According to UNIX98, msg_name/msg_namelen are ignored819+ * on connected socket. -ANK820+ * But... af_llc still doesn't have separate sets of methods for821+ * SOCK_DGRAM and SOCK_STREAM :-( So we have to do this test, will822+ * eventually fix this tho :-) -acme823+ */824+ if (sk->sk_type == SOCK_DGRAM)825+ goto copy_uaddr;826out:827 release_sock(sk);828+ return copied;829+copy_uaddr:830+ if (uaddr != NULL && skb != NULL) {831+ memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));832+ msg->msg_namelen = sizeof(*uaddr);833+ }834+ goto out;835}836837/**···740 struct sockaddr_llc *addr = (struct sockaddr_llc *)msg->msg_name;741 int flags = msg->msg_flags;742 int noblock = flags & MSG_DONTWAIT;0743 struct sk_buff *skb;744 size_t size = 0;745 int rc = -EINVAL, copied = 0, hdrlen;···763 if (rc)764 goto release;765 }766+ hdrlen = llc->dev->hard_header_len + llc_ui_header_len(sk, addr);0767 size = hdrlen + len;768+ if (size > llc->dev->mtu)769+ size = llc->dev->mtu;770 copied = size - hdrlen;771 release_sock(sk);772 skb = sock_alloc_send_skb(sk, size, noblock, &rc);773 lock_sock(sk);774 if (!skb)775 goto release;776+ skb->dev = llc->dev;0777 skb->protocol = llc_proto_type(addr->sllc_arphrd);778 skb_reserve(skb, hdrlen); 779 rc = memcpy_fromiovec(skb_put(skb, copied), msg->msg_iov, copied);···800 if (!(sk->sk_type == SOCK_STREAM && !addr->sllc_ua))801 goto out;802 rc = llc_ui_send_data(sk, skb, noblock);00803out:804+ if (rc) {805 kfree_skb(skb);806release:0807 dprintk("%s: failed sending from %02X to %02X: %d\n",808 __FUNCTION__, llc->laddr.lsap, llc->daddr.lsap, rc);809+ }810 release_sock(sk);811 return rc ? : copied;812}···895 int rc = -EINVAL, opt;896897 lock_sock(sk);898+ if (unlikely(level != SOL_LLC || optlen != sizeof(int)))899 goto out;900 rc = get_user(opt, (int __user *)optval);901 if (rc)···915 case LLC_OPT_ACK_TMR_EXP:916 if (opt > LLC_OPT_MAX_ACK_TMR_EXP)917 goto out;918+ llc->ack_timer.expire = opt * HZ;919 break;920 case LLC_OPT_P_TMR_EXP:921 if (opt > LLC_OPT_MAX_P_TMR_EXP)922 goto out;923+ llc->pf_cycle_timer.expire = opt * HZ;924 break;925 case LLC_OPT_REJ_TMR_EXP:926 if (opt > LLC_OPT_MAX_REJ_TMR_EXP)927 goto out;928+ llc->rej_sent_timer.expire = opt * HZ;929 break;930 case LLC_OPT_BUSY_TMR_EXP:931 if (opt > LLC_OPT_MAX_BUSY_TMR_EXP)932 goto out;933+ llc->busy_state_timer.expire = opt * HZ;934 break;935 case LLC_OPT_TX_WIN:936 if (opt > LLC_OPT_MAX_WIN)···970 int val = 0, len = 0, rc = -EINVAL;971972 lock_sock(sk);973+ if (unlikely(level != SOL_LLC))974 goto out;975 rc = get_user(len, optlen);976 if (rc)···980 goto out;981 switch (optname) {982 case LLC_OPT_RETRY:983+ val = llc->n2; break;984 case LLC_OPT_SIZE:985+ val = llc->n1; break;986 case LLC_OPT_ACK_TMR_EXP:987+ val = llc->ack_timer.expire / HZ; break;988 case LLC_OPT_P_TMR_EXP:989+ val = llc->pf_cycle_timer.expire / HZ; break;990 case LLC_OPT_REJ_TMR_EXP:991+ val = llc->rej_sent_timer.expire / HZ; break;992 case LLC_OPT_BUSY_TMR_EXP:993+ val = llc->busy_state_timer.expire / HZ; break;994 case LLC_OPT_TX_WIN:995 val = llc->k; break;996 case LLC_OPT_RX_WIN:···1034 .sendpage = sock_no_sendpage,1035};10361037+static char llc_proc_err_msg[] __initdata =1038+ KERN_CRIT "LLC: Unable to register the proc_fs entries\n";1039+static char llc_sysctl_err_msg[] __initdata =1040+ KERN_CRIT "LLC: Unable to register the sysctl entries\n";1041+static char llc_sock_err_msg[] __initdata =1042+ KERN_CRIT "LLC: Unable to register the network family\n";10431044static int __init llc2_init(void)1045{···1048 llc_station_init();1049 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;1050 rc = llc_proc_init();1051+ if (rc != 0) {1052+ printk(llc_proc_err_msg);1053 goto out_unregister_llc_proto;1054+ }1055+ rc = llc_sysctl_init();1056+ if (rc) {1057+ printk(llc_sysctl_err_msg);1058+ goto out_proc;1059+ }1060+ rc = sock_register(&llc_ui_family_ops);1061+ if (rc) {1062+ printk(llc_sock_err_msg);1063+ goto out_sysctl;1064+ }1065 llc_add_pack(LLC_DEST_SAP, llc_sap_handler);1066 llc_add_pack(LLC_DEST_CONN, llc_conn_handler);1067out:1068 return rc;1069+out_sysctl:1070+ llc_sysctl_exit();1071+out_proc:1072+ llc_proc_exit();1073out_unregister_llc_proto:1074 proto_unregister(&llc_proto);1075 goto out;···1067 llc_remove_pack(LLC_DEST_CONN);1068 sock_unregister(PF_LLC);1069 llc_proc_exit();1070+ llc_sysctl_exit();1071 proto_unregister(&llc_proto);1072}1073
···40/* Offset table on connection states transition diagram */41static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];420000043/**44 * llc_conn_state_process - sends event to connection state machine45 * @sk: connection···58int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)59{60 int rc;61- struct llc_sock *llc = llc_sk(sk);62 struct llc_conn_state_ev *ev = llc_conn_ev(skb);6364 /*···68 */69 skb_get(skb);70 ev->ind_prim = ev->cfm_prim = 0;71- rc = llc_conn_service(sk, skb); /* sending event to state machine */72- if (rc) {00073 printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__);74 goto out_kfree_skb;75 }7677- if (!ev->ind_prim && !ev->cfm_prim) {78 /* indicate or confirm not required */79 /* XXX this is not very pretty, perhaps we should store80 * XXX indicate/confirm-needed state in the llc_conn_state_ev···88 goto out_skb_put;89 }9091- if (ev->ind_prim && ev->cfm_prim) /* Paranoia */92 skb_get(skb);9394 switch (ev->ind_prim) {95 case LLC_DATA_PRIM:96- llc_save_primitive(skb, LLC_DATA_PRIM);97- if (sock_queue_rcv_skb(sk, skb)) {98 /*99 * shouldn't happen100 */···103 kfree_skb(skb);104 }105 break;106- case LLC_CONN_PRIM: {107- struct sock *parent = skb->sk;108-109- skb->sk = sk;110- skb_queue_tail(&parent->sk_receive_queue, skb);111- sk->sk_state_change(parent);112- }0113 break;114 case LLC_DISC_PRIM:115 sock_hold(sk);···120 sk->sk_socket->state = SS_UNCONNECTED;121 sk->sk_state = TCP_CLOSE;122 if (!sock_flag(sk, SOCK_DEAD)) {123- sk->sk_state_change(sk);124 sock_set_flag(sk, SOCK_DEAD);0125 }126 }127 kfree_skb(skb);···474}475476/**477- * llc_lookup_established - Finds connection for the remote/local sap/mac478 * @sap: SAP479 * @daddr: address of remote LLC (MAC + SAP)480 * @laddr: address of local LLC (MAC + SAP)···482 * Search connection list of the SAP and finds connection using the remote483 * mac, remote sap, local mac, and local sap. Returns pointer for484 * connection found, %NULL otherwise.0485 */486-struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,487- struct llc_addr *laddr)0488{489 struct sock *rc;490 struct hlist_node *node;491492- read_lock_bh(&sap->sk_list.lock);493 sk_for_each(rc, node, &sap->sk_list.list) {494 struct llc_sock *llc = llc_sk(rc);495···505 }506 rc = NULL;507found:508- read_unlock_bh(&sap->sk_list.lock);509 return rc;000000000000510}511512/**···529 * Search connection list of the SAP and finds connection listening on530 * local mac, and local sap. Returns pointer for parent socket found,531 * %NULL otherwise.0532 */533static struct sock *llc_lookup_listener(struct llc_sap *sap,534 struct llc_addr *laddr)···537 struct sock *rc;538 struct hlist_node *node;539540- read_lock_bh(&sap->sk_list.lock);541 sk_for_each(rc, node, &sap->sk_list.list) {542 struct llc_sock *llc = llc_sk(rc);543···551 }552 rc = NULL;553found:554- read_unlock_bh(&sap->sk_list.lock);555 return rc;000000000556}557558/**···577}578579/**580- * find_next_offset - finds offset for next category of transitions581 * @state: state table.582 * @offset: start offset.583 *584 * Finds offset of next category of transitions in transition table.585 * Returns the start index of next category.586 */587-static u16 find_next_offset(struct llc_conn_state *state, u16 offset)588{589 u16 cnt = 0;590 struct llc_conn_state_trans **next_trans;···611 next_offset = 0;612 for (ev_type = 0; ev_type < NBR_CONN_EV; ev_type++) {613 llc_offset_table[state][ev_type] = next_offset;614- next_offset += find_next_offset(curr_state,615- next_offset) + 1;616 }617 }618}···656 */657void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk)658{0659 write_lock_bh(&sap->sk_list.lock);660 llc_sk(sk)->sap = sap;661 sk_add_node(sk, &sap->sk_list.list);···676 write_lock_bh(&sap->sk_list.lock);677 sk_del_node_init(sk);678 write_unlock_bh(&sap->sk_list.lock);0679}680681/**···689static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb)690{691 struct llc_conn_state_ev *ev = llc_conn_ev(skb);692- struct llc_sock *llc = llc_sk(sk);693694- if (!llc->dev)695- llc->dev = skb->dev;696 ev->type = LLC_CONN_EV_TYPE_PDU;697 ev->reason = 0;698 return llc_conn_state_process(sk, skb);0000000000000000000000699}700701void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)···727 llc_pdu_decode_da(skb, daddr.mac);728 llc_pdu_decode_dsap(skb, &daddr.lsap);729730- sk = llc_lookup_established(sap, &saddr, &daddr);731- if (!sk) {732- /*733- * Didn't find an active connection; verify if there734- * is a listening socket for this llc addr735- */736- struct llc_sock *llc;737- struct sock *parent = llc_lookup_listener(sap, &daddr);738739- if (!parent) {740- dprintk("llc_lookup_listener failed!\n");741- goto drop;742- }743-744- sk = llc_sk_alloc(parent->sk_family, GFP_ATOMIC, parent->sk_prot);745- if (!sk) {746- sock_put(parent);747- goto drop;748- }749- llc = llc_sk(sk);750- memcpy(&llc->laddr, &daddr, sizeof(llc->laddr));751- memcpy(&llc->daddr, &saddr, sizeof(llc->daddr));752- llc_sap_add_socket(sap, sk);753- sock_hold(sk);754- sock_put(parent);755- skb->sk = parent;756- } else757- skb->sk = sk;758 bh_lock_sock(sk);000000000000000000000000759 if (!sock_owned_by_user(sk))760 llc_conn_rcv(sk, skb);761 else {···763 llc_set_backlog_type(skb, LLC_PACKET);764 sk_add_backlog(sk, skb);765 }0766 bh_unlock_sock(sk);767 sock_put(sk);768 return;769drop:770 kfree_skb(skb);0000771}772773#undef LLC_REFCNT_DEBUG774#ifdef LLC_REFCNT_DEBUG775static atomic_t llc_sock_nr;776#endif777-778-/**779- * llc_release_sockets - releases all sockets in a sap780- * @sap: sap to release its sockets781- *782- * Releases all connections of a sap. Returns 0 if all actions complete783- * successfully, nonzero otherwise784- */785-int llc_release_sockets(struct llc_sap *sap)786-{787- int rc = 0;788- struct sock *sk;789- struct hlist_node *node;790-791- write_lock_bh(&sap->sk_list.lock);792-793- sk_for_each(sk, node, &sap->sk_list.list) {794- llc_sk(sk)->state = LLC_CONN_STATE_TEMP;795-796- if (llc_send_disc(sk))797- rc = 1;798- }799-800- write_unlock_bh(&sap->sk_list.lock);801- return rc;802-}803804/**805 * llc_backlog_rcv - Processes rx frames and expired timers.···795 int rc = 0;796 struct llc_sock *llc = llc_sk(sk);797798- if (llc_backlog_type(skb) == LLC_PACKET) {799- if (llc->state > 1) /* not closed */800 rc = llc_conn_rcv(sk, skb);801 else802 goto out_kfree_skb;803 } else if (llc_backlog_type(skb) == LLC_EVENT) {804 /* timer expiration event */805- if (llc->state > 1) /* not closed */806 rc = llc_conn_state_process(sk, skb);807 else808 goto out_kfree_skb;···832 llc->dec_step = llc->connect_step = 1;833834 init_timer(&llc->ack_timer.timer);835- llc->ack_timer.expire = LLC_ACK_TIME;836 llc->ack_timer.timer.data = (unsigned long)sk;837 llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;838839 init_timer(&llc->pf_cycle_timer.timer);840- llc->pf_cycle_timer.expire = LLC_P_TIME;841 llc->pf_cycle_timer.timer.data = (unsigned long)sk;842 llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;843844 init_timer(&llc->rej_sent_timer.timer);845- llc->rej_sent_timer.expire = LLC_REJ_TIME;846 llc->rej_sent_timer.timer.data = (unsigned long)sk;847 llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;848849 init_timer(&llc->busy_state_timer.timer);850- llc->busy_state_timer.expire = LLC_BUSY_TIME;851 llc->busy_state_timer.timer.data = (unsigned long)sk;852 llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;853···867 * Allocates a LLC sock and initializes it. Returns the new LLC sock868 * or %NULL if there's no memory available for one869 */870-struct sock *llc_sk_alloc(int family, int priority, struct proto *prot)0871{872 struct sock *sk = sk_alloc(family, priority, prot, 1);873
···40/* Offset table on connection states transition diagram */41static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];4243+int sysctl_llc2_ack_timeout = LLC2_ACK_TIME * HZ;44+int sysctl_llc2_p_timeout = LLC2_P_TIME * HZ;45+int sysctl_llc2_rej_timeout = LLC2_REJ_TIME * HZ;46+int sysctl_llc2_busy_timeout = LLC2_BUSY_TIME * HZ;47+48/**49 * llc_conn_state_process - sends event to connection state machine50 * @sk: connection···53int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)54{55 int rc;56+ struct llc_sock *llc = llc_sk(skb->sk);57 struct llc_conn_state_ev *ev = llc_conn_ev(skb);5859 /*···63 */64 skb_get(skb);65 ev->ind_prim = ev->cfm_prim = 0;66+ /*67+ * Send event to state machine68+ */69+ rc = llc_conn_service(skb->sk, skb);70+ if (unlikely(rc != 0)) {71 printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__);72 goto out_kfree_skb;73 }7475+ if (unlikely(!ev->ind_prim && !ev->cfm_prim)) {76 /* indicate or confirm not required */77 /* XXX this is not very pretty, perhaps we should store78 * XXX indicate/confirm-needed state in the llc_conn_state_ev···80 goto out_skb_put;81 }8283+ if (unlikely(ev->ind_prim && ev->cfm_prim)) /* Paranoia */84 skb_get(skb);8586 switch (ev->ind_prim) {87 case LLC_DATA_PRIM:88+ llc_save_primitive(sk, skb, LLC_DATA_PRIM);89+ if (unlikely(sock_queue_rcv_skb(sk, skb))) {90 /*91 * shouldn't happen92 */···95 kfree_skb(skb);96 }97 break;98+ case LLC_CONN_PRIM:99+ /*100+ * Can't be sock_queue_rcv_skb, because we have to leave the101+ * skb->sk pointing to the newly created struct sock in102+ * llc_conn_handler. -acme103+ */104+ skb_queue_tail(&sk->sk_receive_queue, skb);105+ sk->sk_state_change(sk);106 break;107 case LLC_DISC_PRIM:108 sock_hold(sk);···111 sk->sk_socket->state = SS_UNCONNECTED;112 sk->sk_state = TCP_CLOSE;113 if (!sock_flag(sk, SOCK_DEAD)) {0114 sock_set_flag(sk, SOCK_DEAD);115+ sk->sk_state_change(sk);116 }117 }118 kfree_skb(skb);···465}466467/**468+ * __llc_lookup_established - Finds connection for the remote/local sap/mac469 * @sap: SAP470 * @daddr: address of remote LLC (MAC + SAP)471 * @laddr: address of local LLC (MAC + SAP)···473 * Search connection list of the SAP and finds connection using the remote474 * mac, remote sap, local mac, and local sap. Returns pointer for475 * connection found, %NULL otherwise.476+ * Caller has to make sure local_bh is disabled.477 */478+static struct sock *__llc_lookup_established(struct llc_sap *sap,479+ struct llc_addr *daddr,480+ struct llc_addr *laddr)481{482 struct sock *rc;483 struct hlist_node *node;484485+ read_lock(&sap->sk_list.lock);486 sk_for_each(rc, node, &sap->sk_list.list) {487 struct llc_sock *llc = llc_sk(rc);488···494 }495 rc = NULL;496found:497+ read_unlock(&sap->sk_list.lock);498 return rc;499+}500+501+struct sock *llc_lookup_established(struct llc_sap *sap,502+ struct llc_addr *daddr,503+ struct llc_addr *laddr)504+{505+ struct sock *sk;506+507+ local_bh_disable();508+ sk = __llc_lookup_established(sap, daddr, laddr);509+ local_bh_enable();510+ return sk;511}512513/**···506 * Search connection list of the SAP and finds connection listening on507 * local mac, and local sap. Returns pointer for parent socket found,508 * %NULL otherwise.509+ * Caller has to make sure local_bh is disabled.510 */511static struct sock *llc_lookup_listener(struct llc_sap *sap,512 struct llc_addr *laddr)···513 struct sock *rc;514 struct hlist_node *node;515516+ read_lock(&sap->sk_list.lock);517 sk_for_each(rc, node, &sap->sk_list.list) {518 struct llc_sock *llc = llc_sk(rc);519···527 }528 rc = NULL;529found:530+ read_unlock(&sap->sk_list.lock);531 return rc;532+}533+534+static struct sock *__llc_lookup(struct llc_sap *sap,535+ struct llc_addr *daddr,536+ struct llc_addr *laddr)537+{538+ struct sock *sk = __llc_lookup_established(sap, daddr, laddr);539+540+ return sk ? : llc_lookup_listener(sap, laddr);541}542543/**···544}545546/**547+ * llc_find_next_offset - finds offset for next category of transitions548 * @state: state table.549 * @offset: start offset.550 *551 * Finds offset of next category of transitions in transition table.552 * Returns the start index of next category.553 */554+static u16 __init llc_find_next_offset(struct llc_conn_state *state, u16 offset)555{556 u16 cnt = 0;557 struct llc_conn_state_trans **next_trans;···578 next_offset = 0;579 for (ev_type = 0; ev_type < NBR_CONN_EV; ev_type++) {580 llc_offset_table[state][ev_type] = next_offset;581+ next_offset += llc_find_next_offset(curr_state,582+ next_offset) + 1;583 }584 }585}···623 */624void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk)625{626+ llc_sap_hold(sap);627 write_lock_bh(&sap->sk_list.lock);628 llc_sk(sk)->sap = sap;629 sk_add_node(sk, &sap->sk_list.list);···642 write_lock_bh(&sap->sk_list.lock);643 sk_del_node_init(sk);644 write_unlock_bh(&sap->sk_list.lock);645+ llc_sap_put(sap);646}647648/**···654static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb)655{656 struct llc_conn_state_ev *ev = llc_conn_ev(skb);065700658 ev->type = LLC_CONN_EV_TYPE_PDU;659 ev->reason = 0;660 return llc_conn_state_process(sk, skb);661+}662+663+static struct sock *llc_create_incoming_sock(struct sock *sk,664+ struct net_device *dev,665+ struct llc_addr *saddr,666+ struct llc_addr *daddr)667+{668+ struct sock *newsk = llc_sk_alloc(sk->sk_family, GFP_ATOMIC,669+ sk->sk_prot);670+ struct llc_sock *newllc, *llc = llc_sk(sk);671+672+ if (!newsk)673+ goto out;674+ newllc = llc_sk(newsk);675+ memcpy(&newllc->laddr, daddr, sizeof(newllc->laddr));676+ memcpy(&newllc->daddr, saddr, sizeof(newllc->daddr));677+ newllc->dev = dev;678+ dev_hold(dev);679+ llc_sap_add_socket(llc->sap, newsk);680+ llc_sap_hold(llc->sap);681+out:682+ return newsk;683}684685void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)···673 llc_pdu_decode_da(skb, daddr.mac);674 llc_pdu_decode_dsap(skb, &daddr.lsap);675676+ sk = __llc_lookup(sap, &saddr, &daddr);677+ if (!sk)678+ goto drop;000006790000000000000000000680 bh_lock_sock(sk);681+ /*682+ * This has to be done here and not at the upper layer ->accept683+ * method because of the way the PROCOM state machine works:684+ * it needs to set several state variables (see, for instance,685+ * llc_adm_actions_2 in net/llc/llc_c_st.c) and send a packet to686+ * the originator of the new connection, and this state has to be687+ * in the newly created struct sock private area. -acme688+ */689+ if (unlikely(sk->sk_state == TCP_LISTEN)) {690+ struct sock *newsk = llc_create_incoming_sock(sk, skb->dev,691+ &saddr, &daddr);692+ if (!newsk)693+ goto drop_unlock;694+ skb_set_owner_r(skb, newsk);695+ } else {696+ /*697+ * Can't be skb_set_owner_r, this will be done at the698+ * llc_conn_state_process function, later on, when we will use699+ * skb_queue_rcv_skb to send it to upper layers, this is700+ * another trick required to cope with how the PROCOM state701+ * machine works. -acme702+ */703+ skb->sk = sk;704+ }705 if (!sock_owned_by_user(sk))706 llc_conn_rcv(sk, skb);707 else {···709 llc_set_backlog_type(skb, LLC_PACKET);710 sk_add_backlog(sk, skb);711 }712+out:713 bh_unlock_sock(sk);714 sock_put(sk);715 return;716drop:717 kfree_skb(skb);718+ return;719+drop_unlock:720+ kfree_skb(skb);721+ goto out;722}723724#undef LLC_REFCNT_DEBUG725#ifdef LLC_REFCNT_DEBUG726static atomic_t llc_sock_nr;727#endif00000000000000000000000000728729/**730 * llc_backlog_rcv - Processes rx frames and expired timers.···762 int rc = 0;763 struct llc_sock *llc = llc_sk(sk);764765+ if (likely(llc_backlog_type(skb) == LLC_PACKET)) {766+ if (likely(llc->state > 1)) /* not closed */767 rc = llc_conn_rcv(sk, skb);768 else769 goto out_kfree_skb;770 } else if (llc_backlog_type(skb) == LLC_EVENT) {771 /* timer expiration event */772+ if (likely(llc->state > 1)) /* not closed */773 rc = llc_conn_state_process(sk, skb);774 else775 goto out_kfree_skb;···799 llc->dec_step = llc->connect_step = 1;800801 init_timer(&llc->ack_timer.timer);802+ llc->ack_timer.expire = sysctl_llc2_ack_timeout;803 llc->ack_timer.timer.data = (unsigned long)sk;804 llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;805806 init_timer(&llc->pf_cycle_timer.timer);807+ llc->pf_cycle_timer.expire = sysctl_llc2_p_timeout;808 llc->pf_cycle_timer.timer.data = (unsigned long)sk;809 llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;810811 init_timer(&llc->rej_sent_timer.timer);812+ llc->rej_sent_timer.expire = sysctl_llc2_rej_timeout;813 llc->rej_sent_timer.timer.data = (unsigned long)sk;814 llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;815816 init_timer(&llc->busy_state_timer.timer);817+ llc->busy_state_timer.expire = sysctl_llc2_busy_timeout;818 llc->busy_state_timer.timer.data = (unsigned long)sk;819 llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;820···834 * Allocates a LLC sock and initializes it. Returns the new LLC sock835 * or %NULL if there's no memory available for one836 */837+struct sock *llc_sk_alloc(int family, unsigned int __nocast priority,838+ struct proto *prot)839{840 struct sock *sk = sk_alloc(family, priority, prot, 1);841
+23-11
net/llc/llc_core.c
···40 sap->state = LLC_SAP_STATE_ACTIVE;41 memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN);42 rwlock_init(&sap->sk_list.lock);043 }44 return sap;45}···53 */54static void llc_add_sap(struct llc_sap *sap)55{56- write_lock_bh(&llc_sap_list_lock);57 list_add_tail(&sap->node, &llc_sap_list);58- write_unlock_bh(&llc_sap_list_lock);59}6061/**···69 write_unlock_bh(&llc_sap_list_lock);70}7100000000000072/**73 * llc_sap_find - searchs a SAP in station74 * @sap_value: sap to be found75 *76 * Searchs for a sap in the sap list of the LLC's station upon the sap ID.0077 * Returns the sap or %NULL if not found.78 */79struct llc_sap *llc_sap_find(unsigned char sap_value)···95 struct llc_sap* sap;9697 read_lock_bh(&llc_sap_list_lock);98- list_for_each_entry(sap, &llc_sap_list, node)99- if (sap->laddr.lsap == sap_value)100- goto out;101- sap = NULL;102-out:103 read_unlock_bh(&llc_sap_list_lock);104 return sap;105}···117 struct packet_type *pt,118 struct net_device *orig_dev))119{120- struct llc_sap *sap = llc_sap_find(lsap);121122- if (sap) { /* SAP already exists */123- sap = NULL;124 goto out;125- }126 sap = llc_sap_alloc();127 if (!sap)128 goto out;129 sap->laddr.lsap = lsap;130 sap->rcv_func = func;0131 llc_add_sap(sap);132out:0133 return sap;134}135
···40 sap->state = LLC_SAP_STATE_ACTIVE;41 memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN);42 rwlock_init(&sap->sk_list.lock);43+ atomic_set(&sap->refcnt, 1);44 }45 return sap;46}···52 */53static void llc_add_sap(struct llc_sap *sap)54{055 list_add_tail(&sap->node, &llc_sap_list);056}5758/**···70 write_unlock_bh(&llc_sap_list_lock);71}7273+static struct llc_sap *__llc_sap_find(unsigned char sap_value)74+{75+ struct llc_sap* sap;76+77+ list_for_each_entry(sap, &llc_sap_list, node)78+ if (sap->laddr.lsap == sap_value)79+ goto out;80+ sap = NULL;81+out:82+ return sap;83+}84+85/**86 * llc_sap_find - searchs a SAP in station87 * @sap_value: sap to be found88 *89 * Searchs for a sap in the sap list of the LLC's station upon the sap ID.90+ * If the sap is found it will be refcounted and the user will have to do91+ * a llc_sap_put after use.92 * Returns the sap or %NULL if not found.93 */94struct llc_sap *llc_sap_find(unsigned char sap_value)···82 struct llc_sap* sap;8384 read_lock_bh(&llc_sap_list_lock);85+ sap = __llc_sap_find(sap_value);86+ if (sap)87+ llc_sap_hold(sap);0088 read_unlock_bh(&llc_sap_list_lock);89 return sap;90}···106 struct packet_type *pt,107 struct net_device *orig_dev))108{109+ struct llc_sap *sap = NULL;110111+ write_lock_bh(&llc_sap_list_lock);112+ if (__llc_sap_find(lsap)) /* SAP already exists */113 goto out;0114 sap = llc_sap_alloc();115 if (!sap)116 goto out;117 sap->laddr.lsap = lsap;118 sap->rcv_func = func;119+ llc_sap_hold(sap);120 llc_add_sap(sap);121out:122+ write_unlock_bh(&llc_sap_list_lock);123 return sap;124}125