···5566/* This header used to share core functionality between the standalone77 NAT module, and the compatibility layer's use of NAT for masquerading. */88-extern int ip_nat_init(void);99-extern void ip_nat_cleanup(void);1081111-extern unsigned int nat_packet(struct ip_conntrack *ct,99+extern unsigned int ip_nat_packet(struct ip_conntrack *ct,1210 enum ip_conntrack_info conntrackinfo,1311 unsigned int hooknum,1412 struct sk_buff **pskb);15131616-extern int icmp_reply_translation(struct sk_buff **pskb,1717- struct ip_conntrack *ct,1818- enum ip_nat_manip_type manip,1919- enum ip_conntrack_dir dir);1414+extern int ip_nat_icmp_reply_translation(struct sk_buff **pskb,1515+ struct ip_conntrack *ct,1616+ enum ip_nat_manip_type manip,1717+ enum ip_conntrack_dir dir);2018#endif /* _IP_NAT_CORE_H */
···74747575 return p;7676}7777+EXPORT_SYMBOL_GPL(ip_nat_proto_find_get);77787879void7980ip_nat_proto_put(struct ip_nat_protocol *p)8081{8182 module_put(p->me);8283}8484+EXPORT_SYMBOL_GPL(ip_nat_proto_put);83858486/* We keep an extra hash for each conntrack, for fast searching. */8587static inline unsigned int···113111 return csum_fold(csum_partial((char *)diffs, sizeof(diffs),114112 oldcheck^0xFFFF));115113}114114+EXPORT_SYMBOL(ip_nat_cheat_check);116115117116/* Is this tuple already taken? (not by us) */118117int···130127 invert_tuplepr(&reply, tuple);131128 return ip_conntrack_tuple_taken(&reply, ignored_conntrack);132129}130130+EXPORT_SYMBOL(ip_nat_used_tuple);133131134132/* If we source map this tuple so reply looks like reply_tuple, will135133 * that meet the constraints of range. */···351347352348 return NF_ACCEPT;353349}350350+EXPORT_SYMBOL(ip_nat_setup_info);354351355352/* Returns true if succeeded. */356353static int···392387}393388394389/* Do packet manipulations according to ip_nat_setup_info. */395395-unsigned int nat_packet(struct ip_conntrack *ct,396396- enum ip_conntrack_info ctinfo,397397- unsigned int hooknum,398398- struct sk_buff **pskb)390390+unsigned int ip_nat_packet(struct ip_conntrack *ct,391391+ enum ip_conntrack_info ctinfo,392392+ unsigned int hooknum,393393+ struct sk_buff **pskb)399394{400395 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);401396 unsigned long statusbit;···422417 }423418 return NF_ACCEPT;424419}420420+EXPORT_SYMBOL_GPL(ip_nat_packet);425421426422/* Dir is direction ICMP is coming from (opposite to packet it contains) */427427-int icmp_reply_translation(struct sk_buff **pskb,428428- struct ip_conntrack *ct,429429- enum ip_nat_manip_type manip,430430- enum ip_conntrack_dir dir)423423+int ip_nat_icmp_reply_translation(struct sk_buff **pskb,424424+ struct ip_conntrack *ct,425425+ enum ip_nat_manip_type manip,426426+ enum ip_conntrack_dir dir)431427{432428 struct {433429 struct icmphdr icmp;···515509516510 return 1;517511}512512+EXPORT_SYMBOL_GPL(ip_nat_icmp_reply_translation);518513519514/* Protocol registration. */520515int ip_nat_protocol_register(struct ip_nat_protocol *proto)···532525 write_unlock_bh(&ip_nat_lock);533526 return ret;534527}528528+EXPORT_SYMBOL(ip_nat_protocol_register);535529536530/* Noone stores the protocol anywhere; simply delete it. */537531void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)···544536 /* Someone could be still looking at the proto in a bh. */545537 synchronize_net();546538}539539+EXPORT_SYMBOL(ip_nat_protocol_unregister);547540548541#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \549542 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)···591582EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr);592583#endif593584594594-int __init ip_nat_init(void)585585+static int __init ip_nat_init(void)595586{596587 size_t i;597588···633624 return 0;634625}635626636636-/* Not __exit: called from ip_nat_standalone.c:init_or_cleanup() --RR */637637-void ip_nat_cleanup(void)627627+static void __exit ip_nat_cleanup(void)638628{639629 ip_ct_iterate_cleanup(&clean_nat, NULL);640630 ip_conntrack_destroyed = NULL;641631 vfree(bysource);642632}633633+634634+MODULE_LICENSE("GPL");635635+636636+module_init(ip_nat_init);637637+module_exit(ip_nat_cleanup);
+4
net/ipv4/netfilter/ip_nat_helper.c
···199199 }200200 return 1;201201}202202+EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);202203203204/* Generic function for mangling variable-length address changes inside204205 * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX···257256258257 return 1;259258}259259+EXPORT_SYMBOL(ip_nat_mangle_udp_packet);260260261261/* Adjust one found SACK option including checksum correction */262262static void···401399402400 return 1;403401}402402+EXPORT_SYMBOL(ip_nat_seq_adjust);404403405404/* Setup NAT on this expected conntrack so it follows master. */406405/* If we fail to get a free NAT slot, we'll get dropped on confirm */···428425 /* hook doesn't matter, but it has to do destination manip */429426 ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);430427}428428+EXPORT_SYMBOL(ip_nat_follow_master);
+4-21
net/ipv4/netfilter/ip_nat_standalone.c
···108108 case IP_CT_RELATED:109109 case IP_CT_RELATED+IP_CT_IS_REPLY:110110 if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {111111- if (!icmp_reply_translation(pskb, ct, maniptype,112112- CTINFO2DIR(ctinfo)))111111+ if (!ip_nat_icmp_reply_translation(pskb, ct, maniptype,112112+ CTINFO2DIR(ctinfo)))113113 return NF_DROP;114114 else115115 return NF_ACCEPT;···152152 }153153154154 IP_NF_ASSERT(info);155155- return nat_packet(ct, ctinfo, hooknum, pskb);155155+ return ip_nat_packet(ct, ctinfo, hooknum, pskb);156156}157157158158static unsigned int···325325 printk("ip_nat_init: can't setup rules.\n");326326 goto cleanup_nothing;327327 }328328- ret = ip_nat_init();329329- if (ret < 0) {330330- printk("ip_nat_init: can't setup rules.\n");331331- goto cleanup_rule_init;332332- }333328 ret = nf_register_hook(&ip_nat_in_ops);334329 if (ret < 0) {335330 printk("ip_nat_init: can't register in hook.\n");336336- goto cleanup_nat;331331+ goto cleanup_rule_init;337332 }338333 ret = nf_register_hook(&ip_nat_out_ops);339334 if (ret < 0) {···369374 nf_unregister_hook(&ip_nat_out_ops);370375 cleanup_inops:371376 nf_unregister_hook(&ip_nat_in_ops);372372- cleanup_nat:373373- ip_nat_cleanup();374377 cleanup_rule_init:375378 ip_nat_rule_cleanup();376379 cleanup_nothing:···388395module_init(init);389396module_exit(fini);390397391391-EXPORT_SYMBOL(ip_nat_setup_info);392392-EXPORT_SYMBOL(ip_nat_protocol_register);393393-EXPORT_SYMBOL(ip_nat_protocol_unregister);394394-EXPORT_SYMBOL_GPL(ip_nat_proto_find_get);395395-EXPORT_SYMBOL_GPL(ip_nat_proto_put);396396-EXPORT_SYMBOL(ip_nat_cheat_check);397397-EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);398398-EXPORT_SYMBOL(ip_nat_mangle_udp_packet);399399-EXPORT_SYMBOL(ip_nat_used_tuple);400400-EXPORT_SYMBOL(ip_nat_follow_master);401398MODULE_LICENSE("GPL");
···2121 * See the GNU General Public License for more details.2222 */2323#include <linux/config.h>2424+#include <linux/compiler.h>2425#include <linux/kernel.h>2526#include <linux/module.h>2627#include <linux/rtnetlink.h>···3837static struct sockaddr_llc llc_ui_addrnull;3938static struct proto_ops llc_ui_ops;40394141-static int llc_ui_wait_for_conn(struct sock *sk, int timeout);4242-static int llc_ui_wait_for_disc(struct sock *sk, int timeout);4343-static int llc_ui_wait_for_data(struct sock *sk, int timeout);4444-static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout);4040+static int llc_ui_wait_for_conn(struct sock *sk, long timeout);4141+static int llc_ui_wait_for_disc(struct sock *sk, long timeout);4242+static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout);45434644#if 04745#define dprintk(args...) printk(KERN_DEBUG args)···116116 struct llc_sock* llc = llc_sk(sk);117117 int rc = 0;118118119119- if (llc_data_accept_state(llc->state) || llc->p_flag) {120120- int timeout = sock_sndtimeo(sk, noblock);119119+ if (unlikely(llc_data_accept_state(llc->state) || llc->p_flag)) {120120+ long timeout = sock_sndtimeo(sk, noblock);121121122122 rc = llc_ui_wait_for_busy_core(sk, timeout);123123 }124124- if (!rc)124124+ if (unlikely(!rc))125125 rc = llc_build_and_send_pkt(sk, skb);126126 return rc;127127}···155155 struct sock *sk;156156 int rc = -ESOCKTNOSUPPORT;157157158158- if (sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM) {158158+ if (likely(sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM)) {159159 rc = -ENOMEM;160160 sk = llc_sk_alloc(PF_LLC, GFP_KERNEL, &llc_proto);161161 if (sk) {···177177 struct sock *sk = sock->sk;178178 struct llc_sock *llc;179179180180- if (!sk)180180+ if (unlikely(sk == NULL))181181 goto out;182182 sock_hold(sk);183183 lock_sock(sk);···189189 if (!sock_flag(sk, SOCK_ZAPPED))190190 llc_sap_remove_socket(llc->sap, sk);191191 release_sock(sk);192192- if (llc->sap && hlist_empty(&llc->sap->sk_list.list)) {193193- llc_release_sockets(llc->sap);194194- llc_sap_close(llc->sap);195195- }196192 if (llc->dev)197193 dev_put(llc->dev);198194 sock_put(sk);···217221 llc_ui_sap_last_autoport = i + 2;218222 goto out;219223 }224224+ llc_sap_put(sap);220225 }221226 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;222227 tries++;···228231}229232230233/**231231- * llc_ui_autobind - Bind a socket to a specific address.232232- * @sk: Socket to bind an address to.233233- * @addr: Address the user wants the socket bound to.234234+ * llc_ui_autobind - automatically bind a socket to a sap235235+ * @sock: socket to bind236236+ * @addr: address to connect to234237 *235235- * Bind a socket to a specific address. For llc a user is able to bind to236236- * a specific sap only or mac + sap. If the user only specifies a sap and237237- * a null dmac (all zeros) the user is attempting to bind to an entire238238- * sap. This will stop anyone else on the local system from using that239239- * sap. If someone else has a mac + sap open the bind to null + sap will240240- * fail.241241- * If the user desires to bind to a specific mac + sap, it is possible to242242- * have multiple sap connections via multiple macs.243243- * Bind and autobind for that matter must enforce the correct sap usage244244- * otherwise all hell will break loose.238238+ * Used by llc_ui_connect and llc_ui_sendmsg when the user hasn't239239+ * specifically used llc_ui_bind to bind to an specific address/sap240240+ *245241 * Returns: 0 upon success, negative otherwise.246242 */247243static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)···275285 * @addrlen: Length of the uaddr structure.276286 *277287 * Bind a socket to a specific address. For llc a user is able to bind to278278- * a specific sap only or mac + sap. If the user only specifies a sap and279279- * a null dmac (all zeros) the user is attempting to bind to an entire280280- * sap. This will stop anyone else on the local system from using that281281- * sap. If someone else has a mac + sap open the bind to null + sap will282282- * fail.288288+ * a specific sap only or mac + sap.283289 * If the user desires to bind to a specific mac + sap, it is possible to284290 * have multiple sap connections via multiple macs.285291 * Bind and autobind for that matter must enforce the correct sap usage···291305 int rc = -EINVAL;292306293307 dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap);294294- if (!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr))308308+ if (unlikely(!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr)))295309 goto out;296310 rc = -EAFNOSUPPORT;297297- if (addr->sllc_family != AF_LLC)311311+ if (unlikely(addr->sllc_family != AF_LLC))312312+ goto out;313313+ rc = -ENODEV;314314+ rtnl_lock();315315+ llc->dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_mac);316316+ rtnl_unlock();317317+ if (!llc->dev)298318 goto out;299319 if (!addr->sllc_sap) {300320 rc = -EUSERS;···314322 rc = -EBUSY; /* some other network layer is using the sap */315323 if (!sap)316324 goto out;325325+ llc_sap_hold(sap);317326 } else {318327 struct llc_addr laddr, daddr;319328 struct sock *ask;···331338 ask = llc_lookup_established(sap, &daddr, &laddr);332339 if (ask) {333340 sock_put(ask);334334- goto out;341341+ goto out_put;335342 }336343 }337344 llc->laddr.lsap = addr->sllc_sap;···341348 llc_sap_add_socket(sap, sk);342349 sock_reset_flag(sk, SOCK_ZAPPED);343350 rc = 0;351351+out_put:352352+ llc_sap_put(sap);344353out:345354 return rc;346355}···364369 int rc = -ENOTCONN;365370366371 lock_sock(sk);367367- if (sk->sk_state != TCP_ESTABLISHED)372372+ if (unlikely(sk->sk_state != TCP_ESTABLISHED))368373 goto out;369374 rc = -EINVAL;370375 if (how != 2)···399404 struct sock *sk = sock->sk;400405 struct llc_sock *llc = llc_sk(sk);401406 struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;402402- struct net_device *dev;403407 int rc = -EINVAL;404408405409 lock_sock(sk);406406- if (addrlen != sizeof(*addr))410410+ if (unlikely(addrlen != sizeof(*addr)))407411 goto out;408412 rc = -EAFNOSUPPORT;409409- if (addr->sllc_family != AF_LLC)413413+ if (unlikely(addr->sllc_family != AF_LLC))414414+ goto out;415415+ if (unlikely(sk->sk_type != SOCK_STREAM))416416+ goto out;417417+ rc = -EALREADY;418418+ if (unlikely(sock->state == SS_CONNECTING))410419 goto out;411420 /* bind connection to sap if user hasn't done it. */412421 if (sock_flag(sk, SOCK_ZAPPED)) {···418419 rc = llc_ui_autobind(sock, addr);419420 if (rc)420421 goto out;421421- llc->daddr.lsap = addr->sllc_sap;422422- memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN);423422 }424424- dev = llc->dev;425425- if (sk->sk_type != SOCK_STREAM)426426- goto out;427427- rc = -EALREADY;428428- if (sock->state == SS_CONNECTING)429429- goto out;423423+ llc->daddr.lsap = addr->sllc_sap;424424+ memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN);430425 sock->state = SS_CONNECTING;431426 sk->sk_state = TCP_SYN_SENT;432427 llc->link = llc_ui_next_link_no(llc->sap->laddr.lsap);433433- rc = llc_establish_connection(sk, dev->dev_addr,428428+ rc = llc_establish_connection(sk, llc->dev->dev_addr,434429 addr->sllc_mac, addr->sllc_sap);435430 if (rc) {436431 dprintk("%s: llc_ui_send_conn failed :-(\n", __FUNCTION__);···432439 sk->sk_state = TCP_CLOSE;433440 goto out;434441 }435435- rc = llc_ui_wait_for_conn(sk, sk->sk_rcvtimeo);436436- if (rc)437437- dprintk("%s: llc_ui_wait_for_conn failed=%d\n", __FUNCTION__, rc);442442+443443+ if (sk->sk_state == TCP_SYN_SENT) {444444+ const long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);445445+446446+ if (!timeo || !llc_ui_wait_for_conn(sk, timeo))447447+ goto out;448448+449449+ rc = sock_intr_errno(timeo);450450+ if (signal_pending(current))451451+ goto out;452452+ }453453+454454+ if (sk->sk_state == TCP_CLOSE)455455+ goto sock_error;456456+457457+ sock->state = SS_CONNECTED;458458+ rc = 0;438459out:439460 release_sock(sk);440461 return rc;462462+sock_error:463463+ rc = sock_error(sk) ? : -ECONNABORTED;464464+ sock->state = SS_UNCONNECTED;465465+ goto out;441466}442467443468/**···472461 int rc = -EINVAL;473462474463 lock_sock(sk);475475- if (sock->state != SS_UNCONNECTED)464464+ if (unlikely(sock->state != SS_UNCONNECTED))476465 goto out;477466 rc = -EOPNOTSUPP;478478- if (sk->sk_type != SOCK_STREAM)467467+ if (unlikely(sk->sk_type != SOCK_STREAM))479468 goto out;480469 rc = -EAGAIN;481470 if (sock_flag(sk, SOCK_ZAPPED))···494483 return rc;495484}496485497497-static int llc_ui_wait_for_disc(struct sock *sk, int timeout)486486+static int llc_ui_wait_for_disc(struct sock *sk, long timeout)498487{499499- DECLARE_WAITQUEUE(wait, current);500500- int rc;501501-502502- add_wait_queue_exclusive(sk->sk_sleep, &wait);503503- for (;;) {504504- __set_current_state(TASK_INTERRUPTIBLE);505505- rc = 0;506506- if (sk->sk_state != TCP_CLOSE) {507507- release_sock(sk);508508- timeout = schedule_timeout(timeout);509509- lock_sock(sk);510510- } else511511- break;512512- rc = -ERESTARTSYS;513513- if (signal_pending(current))514514- break;515515- rc = -EAGAIN;516516- if (!timeout)517517- break;518518- }519519- __set_current_state(TASK_RUNNING);520520- remove_wait_queue(sk->sk_sleep, &wait);521521- return rc;522522-}523523-524524-static int llc_ui_wait_for_conn(struct sock *sk, int timeout)525525-{526526- DECLARE_WAITQUEUE(wait, current);527527- int rc;528528-529529- add_wait_queue_exclusive(sk->sk_sleep, &wait);530530- for (;;) {531531- __set_current_state(TASK_INTERRUPTIBLE);532532- rc = -EAGAIN;533533- if (sk->sk_state == TCP_CLOSE)534534- break;535535- rc = 0;536536- if (sk->sk_state != TCP_ESTABLISHED) {537537- release_sock(sk);538538- timeout = schedule_timeout(timeout);539539- lock_sock(sk);540540- } else541541- break;542542- rc = -ERESTARTSYS;543543- if (signal_pending(current))544544- break;545545- rc = -EAGAIN;546546- if (!timeout)547547- break;548548- }549549- __set_current_state(TASK_RUNNING);550550- remove_wait_queue(sk->sk_sleep, &wait);551551- return rc;552552-}553553-554554-static int llc_ui_wait_for_data(struct sock *sk, int timeout)555555-{556556- DECLARE_WAITQUEUE(wait, current);488488+ DEFINE_WAIT(wait);557489 int rc = 0;558490559559- add_wait_queue_exclusive(sk->sk_sleep, &wait);560560- for (;;) {561561- __set_current_state(TASK_INTERRUPTIBLE);562562- if (sk->sk_shutdown & RCV_SHUTDOWN)563563- break;564564- /*565565- * Well, if we have backlog, try to process it now.566566- */567567- if (sk->sk_backlog.tail) {568568- release_sock(sk);569569- lock_sock(sk);570570- }571571- rc = 0;572572- if (skb_queue_empty(&sk->sk_receive_queue)) {573573- release_sock(sk);574574- timeout = schedule_timeout(timeout);575575- lock_sock(sk);576576- } else491491+ while (1) {492492+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);493493+ if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE))577494 break;578495 rc = -ERESTARTSYS;579496 if (signal_pending(current))···509570 rc = -EAGAIN;510571 if (!timeout)511572 break;573573+ rc = 0;512574 }513513- __set_current_state(TASK_RUNNING);514514- remove_wait_queue(sk->sk_sleep, &wait);575575+ finish_wait(sk->sk_sleep, &wait);515576 return rc;516577}517578518518-static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout)579579+static int llc_ui_wait_for_conn(struct sock *sk, long timeout)519580{520520- DECLARE_WAITQUEUE(wait, current);581581+ DEFINE_WAIT(wait);582582+583583+ while (1) {584584+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);585585+ if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT))586586+ break;587587+ if (signal_pending(current) || !timeout)588588+ break;589589+ }590590+ finish_wait(sk->sk_sleep, &wait);591591+ return timeout;592592+}593593+594594+static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout)595595+{596596+ DEFINE_WAIT(wait);521597 struct llc_sock *llc = llc_sk(sk);522598 int rc;523599524524- add_wait_queue_exclusive(sk->sk_sleep, &wait);525525- for (;;) {526526- dprintk("%s: looping...\n", __FUNCTION__);527527- __set_current_state(TASK_INTERRUPTIBLE);528528- rc = -ENOTCONN;529529- if (sk->sk_shutdown & RCV_SHUTDOWN)530530- break;600600+ while (1) {601601+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);531602 rc = 0;532532- if (llc_data_accept_state(llc->state) || llc->p_flag) {533533- release_sock(sk);534534- timeout = schedule_timeout(timeout);535535- lock_sock(sk);536536- } else603603+ if (sk_wait_event(sk, &timeout,604604+ (sk->sk_shutdown & RCV_SHUTDOWN) ||605605+ (!llc_data_accept_state(llc->state) &&606606+ !llc->p_flag)))537607 break;538608 rc = -ERESTARTSYS;539609 if (signal_pending(current))···551603 if (!timeout)552604 break;553605 }554554- __set_current_state(TASK_RUNNING);555555- remove_wait_queue(sk->sk_sleep, &wait);606606+ finish_wait(sk->sk_sleep, &wait);607607+ return rc;608608+}609609+610610+static int llc_wait_data(struct sock *sk, long timeo)611611+{612612+ int rc;613613+614614+ while (1) {615615+ /*616616+ * POSIX 1003.1g mandates this order.617617+ */618618+ if (sk->sk_err) {619619+ rc = sock_error(sk);620620+ break;621621+ }622622+ rc = 0;623623+ if (sk->sk_shutdown & RCV_SHUTDOWN)624624+ break;625625+ rc = -EAGAIN;626626+ if (!timeo)627627+ break;628628+ rc = sock_intr_errno(timeo);629629+ if (signal_pending(current))630630+ break;631631+ rc = 0;632632+ if (sk_wait_data(sk, &timeo))633633+ break;634634+ }556635 return rc;557636}558637···602627 dprintk("%s: accepting on %02X\n", __FUNCTION__,603628 llc_sk(sk)->laddr.lsap);604629 lock_sock(sk);605605- if (sk->sk_type != SOCK_STREAM)630630+ if (unlikely(sk->sk_type != SOCK_STREAM))606631 goto out;607632 rc = -EINVAL;608608- if (sock->state != SS_UNCONNECTED || sk->sk_state != TCP_LISTEN)633633+ if (unlikely(sock->state != SS_UNCONNECTED ||634634+ sk->sk_state != TCP_LISTEN))609635 goto out;610636 /* wait for a connection to arrive. */611611- rc = llc_ui_wait_for_data(sk, sk->sk_rcvtimeo);612612- if (rc)613613- goto out;637637+ if (skb_queue_empty(&sk->sk_receive_queue)) {638638+ rc = llc_wait_data(sk, sk->sk_rcvtimeo);639639+ if (rc)640640+ goto out;641641+ }614642 dprintk("%s: got a new connection on %02X\n", __FUNCTION__,615643 llc_sk(sk)->laddr.lsap);616644 skb = skb_dequeue(&sk->sk_receive_queue);···635657 /* put original socket back into a clean listen state. */636658 sk->sk_state = TCP_LISTEN;637659 sk->sk_ack_backlog--;638638- skb->sk = NULL;639660 dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__,640661 llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap);641662frees:···648671 * llc_ui_recvmsg - copy received data to the socket user.649672 * @sock: Socket to copy data from.650673 * @msg: Various user space related information.651651- * @size: Size of user buffer.674674+ * @len: Size of user buffer.652675 * @flags: User specified flags.653676 *654677 * Copy received data to the socket user.655678 * Returns non-negative upon success, negative otherwise.656679 */657680static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,658658- struct msghdr *msg, size_t size, int flags)681681+ struct msghdr *msg, size_t len, int flags)659682{660660- struct sock *sk = sock->sk;661683 struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name;662662- struct sk_buff *skb;684684+ const int nonblock = flags & MSG_DONTWAIT;685685+ struct sk_buff *skb = NULL;686686+ struct sock *sk = sock->sk;687687+ struct llc_sock *llc = llc_sk(sk);663688 size_t copied = 0;664664- int rc = -ENOMEM, timeout;665665- int noblock = flags & MSG_DONTWAIT;689689+ u32 peek_seq = 0;690690+ u32 *seq;691691+ unsigned long used;692692+ int target; /* Read at least this many bytes */693693+ long timeo;666694667667- dprintk("%s: receiving in %02X from %02X\n", __FUNCTION__,668668- llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap);669695 lock_sock(sk);670670- timeout = sock_rcvtimeo(sk, noblock);671671- rc = llc_ui_wait_for_data(sk, timeout);672672- if (rc) {673673- dprintk("%s: llc_ui_wait_for_data failed recv "674674- "in %02X from %02X\n", __FUNCTION__,675675- llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap);696696+ copied = -ENOTCONN;697697+ if (sk->sk_state == TCP_LISTEN)676698 goto out;677677- }678678- skb = skb_dequeue(&sk->sk_receive_queue);679679- if (!skb) /* shutdown */680680- goto out;681681- copied = skb->len;682682- if (copied > size)683683- copied = size;684684- rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);685685- if (rc)686686- goto dgram_free;687687- if (skb->len > copied) {688688- skb_pull(skb, copied);689689- skb_queue_head(&sk->sk_receive_queue, skb);690690- }691691- if (uaddr)692692- memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));693693- msg->msg_namelen = sizeof(*uaddr);694694- if (!skb->next) {695695-dgram_free:696696- kfree_skb(skb);697697- }699699+700700+ timeo = sock_rcvtimeo(sk, nonblock);701701+702702+ seq = &llc->copied_seq;703703+ if (flags & MSG_PEEK) {704704+ peek_seq = llc->copied_seq;705705+ seq = &peek_seq;706706+ }707707+708708+ target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);709709+ copied = 0;710710+711711+ do {712712+ u32 offset;713713+714714+ /*715715+ * We need to check signals first, to get correct SIGURG716716+ * handling. FIXME: Need to check this doesn't impact 1003.1g717717+ * and move it down to the bottom of the loop718718+ */719719+ if (signal_pending(current)) {720720+ if (copied)721721+ break;722722+ copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;723723+ break;724724+ }725725+726726+ /* Next get a buffer. */727727+728728+ skb = skb_peek(&sk->sk_receive_queue);729729+ if (skb) {730730+ offset = *seq;731731+ goto found_ok_skb;732732+ }733733+ /* Well, if we have backlog, try to process it now yet. */734734+735735+ if (copied >= target && !sk->sk_backlog.tail)736736+ break;737737+738738+ if (copied) {739739+ if (sk->sk_err ||740740+ sk->sk_state == TCP_CLOSE ||741741+ (sk->sk_shutdown & RCV_SHUTDOWN) ||742742+ !timeo ||743743+ (flags & MSG_PEEK))744744+ break;745745+ } else {746746+ if (sock_flag(sk, SOCK_DONE))747747+ break;748748+749749+ if (sk->sk_err) {750750+ copied = sock_error(sk);751751+ break;752752+ }753753+ if (sk->sk_shutdown & RCV_SHUTDOWN)754754+ break;755755+756756+ if (sk->sk_state == TCP_CLOSE) {757757+ if (!sock_flag(sk, SOCK_DONE)) {758758+ /*759759+ * This occurs when user tries to read760760+ * from never connected socket.761761+ */762762+ copied = -ENOTCONN;763763+ break;764764+ }765765+ break;766766+ }767767+ if (!timeo) {768768+ copied = -EAGAIN;769769+ break;770770+ }771771+ }772772+773773+ if (copied >= target) { /* Do not sleep, just process backlog. */774774+ release_sock(sk);775775+ lock_sock(sk);776776+ } else777777+ sk_wait_data(sk, &timeo);778778+779779+ if ((flags & MSG_PEEK) && peek_seq != llc->copied_seq) {780780+ if (net_ratelimit())781781+ printk(KERN_DEBUG "LLC(%s:%d): Application "782782+ "bug, race in MSG_PEEK.\n",783783+ current->comm, current->pid);784784+ peek_seq = llc->copied_seq;785785+ }786786+ continue;787787+ found_ok_skb:788788+ /* Ok so how much can we use? */789789+ used = skb->len - offset;790790+ if (len < used)791791+ used = len;792792+793793+ if (!(flags & MSG_TRUNC)) {794794+ int rc = skb_copy_datagram_iovec(skb, offset,795795+ msg->msg_iov, used);796796+ if (rc) {797797+ /* Exception. Bailout! */798798+ if (!copied)799799+ copied = -EFAULT;800800+ break;801801+ }802802+ }803803+804804+ *seq += used;805805+ copied += used;806806+ len -= used;807807+808808+ if (used + offset < skb->len)809809+ continue;810810+811811+ if (!(flags & MSG_PEEK)) {812812+ sk_eat_skb(sk, skb);813813+ *seq = 0;814814+ }815815+ } while (len > 0);816816+817817+ /* 818818+ * According to UNIX98, msg_name/msg_namelen are ignored819819+ * on connected socket. -ANK820820+ * But... af_llc still doesn't have separate sets of methods for821821+ * SOCK_DGRAM and SOCK_STREAM :-( So we have to do this test, will822822+ * eventually fix this tho :-) -acme823823+ */824824+ if (sk->sk_type == SOCK_DGRAM)825825+ goto copy_uaddr;698826out:699827 release_sock(sk);700700- return rc ? : copied;828828+ return copied;829829+copy_uaddr:830830+ if (uaddr != NULL && skb != NULL) {831831+ memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));832832+ msg->msg_namelen = sizeof(*uaddr);833833+ }834834+ goto out;701835}702836703837/**···828740 struct sockaddr_llc *addr = (struct sockaddr_llc *)msg->msg_name;829741 int flags = msg->msg_flags;830742 int noblock = flags & MSG_DONTWAIT;831831- struct net_device *dev;832743 struct sk_buff *skb;833744 size_t size = 0;834745 int rc = -EINVAL, copied = 0, hdrlen;···850763 if (rc)851764 goto release;852765 }853853- dev = llc->dev;854854- hdrlen = dev->hard_header_len + llc_ui_header_len(sk, addr);766766+ hdrlen = llc->dev->hard_header_len + llc_ui_header_len(sk, addr);855767 size = hdrlen + len;856856- if (size > dev->mtu)857857- size = dev->mtu;768768+ if (size > llc->dev->mtu)769769+ size = llc->dev->mtu;858770 copied = size - hdrlen;859771 release_sock(sk);860772 skb = sock_alloc_send_skb(sk, size, noblock, &rc);861773 lock_sock(sk);862774 if (!skb)863775 goto release;864864- skb->sk = sk;865865- skb->dev = dev;776776+ skb->dev = llc->dev;866777 skb->protocol = llc_proto_type(addr->sllc_arphrd);867778 skb_reserve(skb, hdrlen); 868779 rc = memcpy_fromiovec(skb_put(skb, copied), msg->msg_iov, copied);···885800 if (!(sk->sk_type == SOCK_STREAM && !addr->sllc_ua))886801 goto out;887802 rc = llc_ui_send_data(sk, skb, noblock);888888- if (rc)889889- dprintk("%s: llc_ui_send_data failed: %d\n", __FUNCTION__, rc);890803out:891891- if (rc)804804+ if (rc) {892805 kfree_skb(skb);893806release:894894- if (rc)895807 dprintk("%s: failed sending from %02X to %02X: %d\n",896808 __FUNCTION__, llc->laddr.lsap, llc->daddr.lsap, rc);809809+ }897810 release_sock(sk);898811 return rc ? : copied;899812}···978895 int rc = -EINVAL, opt;979896980897 lock_sock(sk);981981- if (level != SOL_LLC || optlen != sizeof(int))898898+ if (unlikely(level != SOL_LLC || optlen != sizeof(int)))982899 goto out;983900 rc = get_user(opt, (int __user *)optval);984901 if (rc)···998915 case LLC_OPT_ACK_TMR_EXP:999916 if (opt > LLC_OPT_MAX_ACK_TMR_EXP)1000917 goto out;10011001- llc->ack_timer.expire = opt;918918+ llc->ack_timer.expire = opt * HZ;1002919 break;1003920 case LLC_OPT_P_TMR_EXP:1004921 if (opt > LLC_OPT_MAX_P_TMR_EXP)1005922 goto out;10061006- llc->pf_cycle_timer.expire = opt;923923+ llc->pf_cycle_timer.expire = opt * HZ;1007924 break;1008925 case LLC_OPT_REJ_TMR_EXP:1009926 if (opt > LLC_OPT_MAX_REJ_TMR_EXP)1010927 goto out;10111011- llc->rej_sent_timer.expire = opt;928928+ llc->rej_sent_timer.expire = opt * HZ;1012929 break;1013930 case LLC_OPT_BUSY_TMR_EXP:1014931 if (opt > LLC_OPT_MAX_BUSY_TMR_EXP)1015932 goto out;10161016- llc->busy_state_timer.expire = opt;933933+ llc->busy_state_timer.expire = opt * HZ;1017934 break;1018935 case LLC_OPT_TX_WIN:1019936 if (opt > LLC_OPT_MAX_WIN)···1053970 int val = 0, len = 0, rc = -EINVAL;10549711055972 lock_sock(sk);10561056- if (level != SOL_LLC)973973+ if (unlikely(level != SOL_LLC))1057974 goto out;1058975 rc = get_user(len, optlen);1059976 if (rc)···1063980 goto out;1064981 switch (optname) {1065982 case LLC_OPT_RETRY:10661066- val = llc->n2; break;983983+ val = llc->n2; break;1067984 case LLC_OPT_SIZE:10681068- val = llc->n1; break;985985+ val = llc->n1; break;1069986 case LLC_OPT_ACK_TMR_EXP:10701070- val = llc->ack_timer.expire; break;987987+ val = llc->ack_timer.expire / HZ; break;1071988 case LLC_OPT_P_TMR_EXP:10721072- val = llc->pf_cycle_timer.expire; break;989989+ val = llc->pf_cycle_timer.expire / HZ; break;1073990 case LLC_OPT_REJ_TMR_EXP:10741074- val = llc->rej_sent_timer.expire; break;991991+ val = llc->rej_sent_timer.expire / HZ; break;1075992 case LLC_OPT_BUSY_TMR_EXP:10761076- val = llc->busy_state_timer.expire; break;993993+ val = llc->busy_state_timer.expire / HZ; break;1077994 case LLC_OPT_TX_WIN:1078995 val = llc->k; break;1079996 case LLC_OPT_RX_WIN:···11171034 .sendpage = sock_no_sendpage,11181035};1119103611201120-extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb);11211121-extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb);10371037+static char llc_proc_err_msg[] __initdata =10381038+ KERN_CRIT "LLC: Unable to register the proc_fs entries\n";10391039+static char llc_sysctl_err_msg[] __initdata =10401040+ KERN_CRIT "LLC: Unable to register the sysctl entries\n";10411041+static char llc_sock_err_msg[] __initdata =10421042+ KERN_CRIT "LLC: Unable to register the network family\n";1122104311231044static int __init llc2_init(void)11241045{···11351048 llc_station_init();11361049 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;11371050 rc = llc_proc_init();11381138- if (rc != 0)10511051+ if (rc != 0) {10521052+ printk(llc_proc_err_msg);11391053 goto out_unregister_llc_proto;11401140- sock_register(&llc_ui_family_ops);10541054+ }10551055+ rc = llc_sysctl_init();10561056+ if (rc) {10571057+ printk(llc_sysctl_err_msg);10581058+ goto out_proc;10591059+ }10601060+ rc = sock_register(&llc_ui_family_ops);10611061+ if (rc) {10621062+ printk(llc_sock_err_msg);10631063+ goto out_sysctl;10641064+ }11411065 llc_add_pack(LLC_DEST_SAP, llc_sap_handler);11421066 llc_add_pack(LLC_DEST_CONN, llc_conn_handler);11431067out:11441068 return rc;10691069+out_sysctl:10701070+ llc_sysctl_exit();10711071+out_proc:10721072+ llc_proc_exit();11451073out_unregister_llc_proto:11461074 proto_unregister(&llc_proto);11471075 goto out;···11691067 llc_remove_pack(LLC_DEST_CONN);11701068 sock_unregister(PF_LLC);11711069 llc_proc_exit();10701070+ llc_sysctl_exit();11721071 proto_unregister(&llc_proto);11731072}11741073
···4040/* Offset table on connection states transition diagram */4141static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];42424343+int sysctl_llc2_ack_timeout = LLC2_ACK_TIME * HZ;4444+int sysctl_llc2_p_timeout = LLC2_P_TIME * HZ;4545+int sysctl_llc2_rej_timeout = LLC2_REJ_TIME * HZ;4646+int sysctl_llc2_busy_timeout = LLC2_BUSY_TIME * HZ;4747+4348/**4449 * llc_conn_state_process - sends event to connection state machine4550 * @sk: connection···5853int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)5954{6055 int rc;6161- struct llc_sock *llc = llc_sk(sk);5656+ struct llc_sock *llc = llc_sk(skb->sk);6257 struct llc_conn_state_ev *ev = llc_conn_ev(skb);63586459 /*···6863 */6964 skb_get(skb);7065 ev->ind_prim = ev->cfm_prim = 0;7171- rc = llc_conn_service(sk, skb); /* sending event to state machine */7272- if (rc) {6666+ /*6767+ * Send event to state machine6868+ */6969+ rc = llc_conn_service(skb->sk, skb);7070+ if (unlikely(rc != 0)) {7371 printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__);7472 goto out_kfree_skb;7573 }76747777- if (!ev->ind_prim && !ev->cfm_prim) {7575+ if (unlikely(!ev->ind_prim && !ev->cfm_prim)) {7876 /* indicate or confirm not required */7977 /* XXX this is not very pretty, perhaps we should store8078 * XXX indicate/confirm-needed state in the llc_conn_state_ev···8880 goto out_skb_put;8981 }90829191- if (ev->ind_prim && ev->cfm_prim) /* Paranoia */8383+ if (unlikely(ev->ind_prim && ev->cfm_prim)) /* Paranoia */9284 skb_get(skb);93859486 switch (ev->ind_prim) {9587 case LLC_DATA_PRIM:9696- llc_save_primitive(skb, LLC_DATA_PRIM);9797- if (sock_queue_rcv_skb(sk, skb)) {8888+ llc_save_primitive(sk, skb, LLC_DATA_PRIM);8989+ if (unlikely(sock_queue_rcv_skb(sk, skb))) {9890 /*9991 * shouldn't happen10092 */···10395 kfree_skb(skb);10496 }10597 break;106106- case LLC_CONN_PRIM: {107107- struct sock *parent = skb->sk;108108-109109- skb->sk = sk;110110- skb_queue_tail(&parent->sk_receive_queue, skb);111111- sk->sk_state_change(parent);112112- }9898+ case LLC_CONN_PRIM:9999+ /*100100+ * Can't be sock_queue_rcv_skb, because we have to leave the101101+ * skb->sk pointing to the newly created struct sock in102102+ * llc_conn_handler. -acme103103+ */104104+ skb_queue_tail(&sk->sk_receive_queue, skb);105105+ sk->sk_state_change(sk);113106 break;114107 case LLC_DISC_PRIM:115108 sock_hold(sk);···120111 sk->sk_socket->state = SS_UNCONNECTED;121112 sk->sk_state = TCP_CLOSE;122113 if (!sock_flag(sk, SOCK_DEAD)) {123123- sk->sk_state_change(sk);124114 sock_set_flag(sk, SOCK_DEAD);115115+ sk->sk_state_change(sk);125116 }126117 }127118 kfree_skb(skb);···474465}475466476467/**477477- * llc_lookup_established - Finds connection for the remote/local sap/mac468468+ * __llc_lookup_established - Finds connection for the remote/local sap/mac478469 * @sap: SAP479470 * @daddr: address of remote LLC (MAC + SAP)480471 * @laddr: address of local LLC (MAC + SAP)···482473 * Search connection list of the SAP and finds connection using the remote483474 * mac, remote sap, local mac, and local sap. Returns pointer for484475 * connection found, %NULL otherwise.476476+ * Caller has to make sure local_bh is disabled.485477 */486486-struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,487487- struct llc_addr *laddr)478478+static struct sock *__llc_lookup_established(struct llc_sap *sap,479479+ struct llc_addr *daddr,480480+ struct llc_addr *laddr)488481{489482 struct sock *rc;490483 struct hlist_node *node;491484492492- read_lock_bh(&sap->sk_list.lock);485485+ read_lock(&sap->sk_list.lock);493486 sk_for_each(rc, node, &sap->sk_list.list) {494487 struct llc_sock *llc = llc_sk(rc);495488···505494 }506495 rc = NULL;507496found:508508- read_unlock_bh(&sap->sk_list.lock);497497+ read_unlock(&sap->sk_list.lock);509498 return rc;499499+}500500+501501+struct sock *llc_lookup_established(struct llc_sap *sap,502502+ struct llc_addr *daddr,503503+ struct llc_addr *laddr)504504+{505505+ struct sock *sk;506506+507507+ local_bh_disable();508508+ sk = __llc_lookup_established(sap, daddr, laddr);509509+ local_bh_enable();510510+ return sk;510511}511512512513/**···529506 * Search connection list of the SAP and finds connection listening on530507 * local mac, and local sap. Returns pointer for parent socket found,531508 * %NULL otherwise.509509+ * Caller has to make sure local_bh is disabled.532510 */533511static struct sock *llc_lookup_listener(struct llc_sap *sap,534512 struct llc_addr *laddr)···537513 struct sock *rc;538514 struct hlist_node *node;539515540540- read_lock_bh(&sap->sk_list.lock);516516+ read_lock(&sap->sk_list.lock);541517 sk_for_each(rc, node, &sap->sk_list.list) {542518 struct llc_sock *llc = llc_sk(rc);543519···551527 }552528 rc = NULL;553529found:554554- read_unlock_bh(&sap->sk_list.lock);530530+ read_unlock(&sap->sk_list.lock);555531 return rc;532532+}533533+534534+static struct sock *__llc_lookup(struct llc_sap *sap,535535+ struct llc_addr *daddr,536536+ struct llc_addr *laddr)537537+{538538+ struct sock *sk = __llc_lookup_established(sap, daddr, laddr);539539+540540+ return sk ? : llc_lookup_listener(sap, laddr);556541}557542558543/**···577544}578545579546/**580580- * find_next_offset - finds offset for next category of transitions547547+ * llc_find_next_offset - finds offset for next category of transitions581548 * @state: state table.582549 * @offset: start offset.583550 *584551 * Finds offset of next category of transitions in transition table.585552 * Returns the start index of next category.586553 */587587-static u16 find_next_offset(struct llc_conn_state *state, u16 offset)554554+static u16 __init llc_find_next_offset(struct llc_conn_state *state, u16 offset)588555{589556 u16 cnt = 0;590557 struct llc_conn_state_trans **next_trans;···611578 next_offset = 0;612579 for (ev_type = 0; ev_type < NBR_CONN_EV; ev_type++) {613580 llc_offset_table[state][ev_type] = next_offset;614614- next_offset += find_next_offset(curr_state,615615- next_offset) + 1;581581+ next_offset += llc_find_next_offset(curr_state,582582+ next_offset) + 1;616583 }617584 }618585}···656623 */657624void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk)658625{626626+ llc_sap_hold(sap);659627 write_lock_bh(&sap->sk_list.lock);660628 llc_sk(sk)->sap = sap;661629 sk_add_node(sk, &sap->sk_list.list);···676642 write_lock_bh(&sap->sk_list.lock);677643 sk_del_node_init(sk);678644 write_unlock_bh(&sap->sk_list.lock);645645+ llc_sap_put(sap);679646}680647681648/**···689654static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb)690655{691656 struct llc_conn_state_ev *ev = llc_conn_ev(skb);692692- struct llc_sock *llc = llc_sk(sk);693657694694- if (!llc->dev)695695- llc->dev = skb->dev;696658 ev->type = LLC_CONN_EV_TYPE_PDU;697659 ev->reason = 0;698660 return llc_conn_state_process(sk, skb);661661+}662662+663663+static struct sock *llc_create_incoming_sock(struct sock *sk,664664+ struct net_device *dev,665665+ struct llc_addr *saddr,666666+ struct llc_addr *daddr)667667+{668668+ struct sock *newsk = llc_sk_alloc(sk->sk_family, GFP_ATOMIC,669669+ sk->sk_prot);670670+ struct llc_sock *newllc, *llc = llc_sk(sk);671671+672672+ if (!newsk)673673+ goto out;674674+ newllc = llc_sk(newsk);675675+ memcpy(&newllc->laddr, daddr, sizeof(newllc->laddr));676676+ memcpy(&newllc->daddr, saddr, sizeof(newllc->daddr));677677+ newllc->dev = dev;678678+ dev_hold(dev);679679+ llc_sap_add_socket(llc->sap, newsk);680680+ llc_sap_hold(llc->sap);681681+out:682682+ return newsk;699683}700684701685void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)···727673 llc_pdu_decode_da(skb, daddr.mac);728674 llc_pdu_decode_dsap(skb, &daddr.lsap);729675730730- sk = llc_lookup_established(sap, &saddr, &daddr);731731- if (!sk) {732732- /*733733- * Didn't find an active connection; verify if there734734- * is a listening socket for this llc addr735735- */736736- struct llc_sock *llc;737737- struct sock *parent = llc_lookup_listener(sap, &daddr);676676+ sk = __llc_lookup(sap, &saddr, &daddr);677677+ if (!sk)678678+ goto drop;738679739739- if (!parent) {740740- dprintk("llc_lookup_listener failed!\n");741741- goto drop;742742- }743743-744744- sk = llc_sk_alloc(parent->sk_family, GFP_ATOMIC, parent->sk_prot);745745- if (!sk) {746746- sock_put(parent);747747- goto drop;748748- }749749- llc = llc_sk(sk);750750- memcpy(&llc->laddr, &daddr, sizeof(llc->laddr));751751- memcpy(&llc->daddr, &saddr, sizeof(llc->daddr));752752- llc_sap_add_socket(sap, sk);753753- sock_hold(sk);754754- sock_put(parent);755755- skb->sk = parent;756756- } else757757- skb->sk = sk;758680 bh_lock_sock(sk);681681+ /*682682+ * This has to be done here and not at the upper layer ->accept683683+ * method because of the way the PROCOM state machine works:684684+ * it needs to set several state variables (see, for instance,685685+ * llc_adm_actions_2 in net/llc/llc_c_st.c) and send a packet to686686+ * the originator of the new connection, and this state has to be687687+ * in the newly created struct sock private area. -acme688688+ */689689+ if (unlikely(sk->sk_state == TCP_LISTEN)) {690690+ struct sock *newsk = llc_create_incoming_sock(sk, skb->dev,691691+ &saddr, &daddr);692692+ if (!newsk)693693+ goto drop_unlock;694694+ skb_set_owner_r(skb, newsk);695695+ } else {696696+ /*697697+ * Can't be skb_set_owner_r, this will be done at the698698+ * llc_conn_state_process function, later on, when we will use699699+ * skb_queue_rcv_skb to send it to upper layers, this is700700+ * another trick required to cope with how the PROCOM state701701+ * machine works. -acme702702+ */703703+ skb->sk = sk;704704+ }759705 if (!sock_owned_by_user(sk))760706 llc_conn_rcv(sk, skb);761707 else {···763709 llc_set_backlog_type(skb, LLC_PACKET);764710 sk_add_backlog(sk, skb);765711 }712712+out:766713 bh_unlock_sock(sk);767714 sock_put(sk);768715 return;769716drop:770717 kfree_skb(skb);718718+ return;719719+drop_unlock:720720+ kfree_skb(skb);721721+ goto out;771722}772723773724#undef LLC_REFCNT_DEBUG774725#ifdef LLC_REFCNT_DEBUG775726static atomic_t llc_sock_nr;776727#endif777777-778778-/**779779- * llc_release_sockets - releases all sockets in a sap780780- * @sap: sap to release its sockets781781- *782782- * Releases all connections of a sap. Returns 0 if all actions complete783783- * successfully, nonzero otherwise784784- */785785-int llc_release_sockets(struct llc_sap *sap)786786-{787787- int rc = 0;788788- struct sock *sk;789789- struct hlist_node *node;790790-791791- write_lock_bh(&sap->sk_list.lock);792792-793793- sk_for_each(sk, node, &sap->sk_list.list) {794794- llc_sk(sk)->state = LLC_CONN_STATE_TEMP;795795-796796- if (llc_send_disc(sk))797797- rc = 1;798798- }799799-800800- write_unlock_bh(&sap->sk_list.lock);801801- return rc;802802-}803728804729/**805730 * llc_backlog_rcv - Processes rx frames and expired timers.···795762 int rc = 0;796763 struct llc_sock *llc = llc_sk(sk);797764798798- if (llc_backlog_type(skb) == LLC_PACKET) {799799- if (llc->state > 1) /* not closed */765765+ if (likely(llc_backlog_type(skb) == LLC_PACKET)) {766766+ if (likely(llc->state > 1)) /* not closed */800767 rc = llc_conn_rcv(sk, skb);801768 else802769 goto out_kfree_skb;803770 } else if (llc_backlog_type(skb) == LLC_EVENT) {804771 /* timer expiration event */805805- if (llc->state > 1) /* not closed */772772+ if (likely(llc->state > 1)) /* not closed */806773 rc = llc_conn_state_process(sk, skb);807774 else808775 goto out_kfree_skb;···832799 llc->dec_step = llc->connect_step = 1;833800834801 init_timer(&llc->ack_timer.timer);835835- llc->ack_timer.expire = LLC_ACK_TIME;802802+ llc->ack_timer.expire = sysctl_llc2_ack_timeout;836803 llc->ack_timer.timer.data = (unsigned long)sk;837804 llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;838805839806 init_timer(&llc->pf_cycle_timer.timer);840840- llc->pf_cycle_timer.expire = LLC_P_TIME;807807+ llc->pf_cycle_timer.expire = sysctl_llc2_p_timeout;841808 llc->pf_cycle_timer.timer.data = (unsigned long)sk;842809 llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;843810844811 init_timer(&llc->rej_sent_timer.timer);845845- llc->rej_sent_timer.expire = LLC_REJ_TIME;812812+ llc->rej_sent_timer.expire = sysctl_llc2_rej_timeout;846813 llc->rej_sent_timer.timer.data = (unsigned long)sk;847814 llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;848815849816 init_timer(&llc->busy_state_timer.timer);850850- llc->busy_state_timer.expire = LLC_BUSY_TIME;817817+ llc->busy_state_timer.expire = sysctl_llc2_busy_timeout;851818 llc->busy_state_timer.timer.data = (unsigned long)sk;852819 llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;853820···867834 * Allocates a LLC sock and initializes it. Returns the new LLC sock868835 * or %NULL if there's no memory available for one869836 */870870-struct sock *llc_sk_alloc(int family, int priority, struct proto *prot)837837+struct sock *llc_sk_alloc(int family, unsigned int __nocast priority,838838+ struct proto *prot)871839{872840 struct sock *sk = sk_alloc(family, priority, prot, 1);873841
+23-11
net/llc/llc_core.c
···4040 sap->state = LLC_SAP_STATE_ACTIVE;4141 memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN);4242 rwlock_init(&sap->sk_list.lock);4343+ atomic_set(&sap->refcnt, 1);4344 }4445 return sap;4546}···5352 */5453static void llc_add_sap(struct llc_sap *sap)5554{5656- write_lock_bh(&llc_sap_list_lock);5755 list_add_tail(&sap->node, &llc_sap_list);5858- write_unlock_bh(&llc_sap_list_lock);5956}60576158/**···6970 write_unlock_bh(&llc_sap_list_lock);7071}71727373+static struct llc_sap *__llc_sap_find(unsigned char sap_value)7474+{7575+ struct llc_sap* sap;7676+7777+ list_for_each_entry(sap, &llc_sap_list, node)7878+ if (sap->laddr.lsap == sap_value)7979+ goto out;8080+ sap = NULL;8181+out:8282+ return sap;8383+}8484+7285/**7386 * llc_sap_find - searchs a SAP in station7487 * @sap_value: sap to be found7588 *7689 * Searchs for a sap in the sap list of the LLC's station upon the sap ID.9090+ * If the sap is found it will be refcounted and the user will have to do9191+ * a llc_sap_put after use.7792 * Returns the sap or %NULL if not found.7893 */7994struct llc_sap *llc_sap_find(unsigned char sap_value)···9582 struct llc_sap* sap;96839784 read_lock_bh(&llc_sap_list_lock);9898- list_for_each_entry(sap, &llc_sap_list, node)9999- if (sap->laddr.lsap == sap_value)100100- goto out;101101- sap = NULL;102102-out:8585+ sap = __llc_sap_find(sap_value);8686+ if (sap)8787+ llc_sap_hold(sap);10388 read_unlock_bh(&llc_sap_list_lock);10489 return sap;10590}···117106 struct packet_type *pt,118107 struct net_device *orig_dev))119108{120120- struct llc_sap *sap = llc_sap_find(lsap);109109+ struct llc_sap *sap = NULL;121110122122- if (sap) { /* SAP already exists */123123- sap = NULL;111111+ write_lock_bh(&llc_sap_list_lock);112112+ if (__llc_sap_find(lsap)) /* SAP already exists */124113 goto out;125125- }126114 sap = llc_sap_alloc();127115 if (!sap)128116 goto out;129117 sap->laddr.lsap = lsap;130118 sap->rcv_func = func;119119+ llc_sap_hold(sap);131120 llc_add_sap(sap);132121out:122122+ write_unlock_bh(&llc_sap_list_lock);133123 return sap;134124}135125