Index: kernel-acme/Makefile diff -u kernel-acme/Makefile:1.1.1.13 kernel-acme/Makefile:1.1.1.13.2.2 --- kernel-acme/Makefile:1.1.1.13 Thu Nov 29 16:52:21 2001 +++ kernel-acme/Makefile Fri Dec 21 13:39:14 2001 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 16 -EXTRAVERSION = +EXTRAVERSION = -acme6 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) Index: kernel-acme/Documentation/Configure.help diff -u kernel-acme/Documentation/Configure.help:1.1.1.10 kernel-acme/Documentation/Configure.help:1.1.1.10.4.1 --- kernel-acme/Documentation/Configure.help:1.1.1.10 Fri Nov 23 22:26:32 2001 +++ kernel-acme/Documentation/Configure.help Thu Nov 29 20:36:51 2001 @@ -5841,6 +5841,12 @@ This is a Logical Link Layer protocol used for X.25 connections over Ethernet, using ordinary Ethernet cards. +ANSI/IEEE 802.2 Data link layer User Interface SAPs (EXPERIMENTAL) +CONFIG_LLC_UI + LLC User Interface SAPs is a Linux socket interface into the LLC datalink + layer. This allows a user to create entire user space network layers tied + to a real SAP. + Frame Diverter CONFIG_NET_DIVERT The Frame Diverter allows you to divert packets from the Index: kernel-acme/arch/i386/kernel/dmi_scan.c diff -u kernel-acme/arch/i386/kernel/dmi_scan.c:1.1.1.7 kernel-acme/arch/i386/kernel/dmi_scan.c:1.1.1.7.4.1 --- kernel-acme/arch/i386/kernel/dmi_scan.c:1.1.1.7 Fri Nov 23 18:42:31 2001 +++ kernel-acme/arch/i386/kernel/dmi_scan.c Fri Dec 21 12:43:32 2001 @@ -190,7 +190,7 @@ * rule needs to be improved to match specific BIOS revisions with * corruption problems */ - +#if 0 static __init int disable_ide_dma(struct dmi_blacklist *d) { #ifdef CONFIG_BLK_DEV_IDE @@ -203,6 +203,7 @@ #endif return 0; } +#endif /* * Reboot options and system auto-detection code provided by Index: kernel-acme/drivers/net/pppoe.c diff -u kernel-acme/drivers/net/pppoe.c:1.1.1.4 kernel-acme/drivers/net/pppoe.c:1.1.1.4.4.2 --- kernel-acme/drivers/net/pppoe.c:1.1.1.4 Fri Nov 23 19:55:47 2001 +++ kernel-acme/drivers/net/pppoe.c Fri Dec 21 02:12:13 2001 @@ -127,7 +127,8 @@ return hash & ( PPPOE_HASH_SIZE - 1 ); } -static struct pppox_opt *item_hash_table[PPPOE_HASH_SIZE] = { 0, }; +/* zeroed because its in .bss */ +static struct pppox_opt *item_hash_table[PPPOE_HASH_SIZE]; /********************************************************************** * @@ -340,7 +341,7 @@ ***********************************************************************/ int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) { - struct pppox_opt *po = sk->protinfo.pppox; + struct pppox_opt *po = PPPOX_SK(sk); struct pppox_opt *relay_po = NULL; if (sk->state & PPPOX_BOUND) { @@ -468,8 +469,8 @@ **********************************************************************/ void pppoe_sock_destruct(struct sock *sk) { - if (sk->protinfo.destruct_hook) - kfree(sk->protinfo.destruct_hook); + if (PPPOX_SK(sk)) + kfree(PPPOX_SK(sk)); MOD_DEC_USE_COUNT; } @@ -486,7 +487,7 @@ MOD_INC_USE_COUNT; - sk = sk_alloc(PF_PPPOX, GFP_KERNEL, 1); + sk = sk_alloc(PF_PPPOX, GFP_KERNEL, 1, NULL); if (!sk) return -ENOMEM; @@ -505,17 +506,15 @@ sk->type = SOCK_STREAM; sk->destruct = pppoe_sock_destruct; - sk->protinfo.pppox = kmalloc(sizeof(struct pppox_opt), GFP_KERNEL); - if (!sk->protinfo.pppox) { + PPPOX_SK(sk) = kmalloc(sizeof(struct pppox_opt), GFP_KERNEL); + if (!PPPOX_SK(sk)) { error = -ENOMEM; goto free_sk; } - memset((void *) sk->protinfo.pppox, 0, sizeof(struct pppox_opt)); - sk->protinfo.pppox->sk = sk; + memset(PPPOX_SK(sk), 0, sizeof(struct pppox_opt)); + PPPOX_SK(sk)->sk = sk; - /* Delete the protinfo when it is time to do so. */ - sk->protinfo.destruct_hook = sk->protinfo.pppox; sock->sk = sk; return 0; @@ -542,7 +541,7 @@ /* Signal the death of the socket. */ sk->state = PPPOX_DEAD; - po = sk->protinfo.pppox; + po = PPPOX_SK(sk); if (po->pppoe_pa.sid) { delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote); } @@ -568,7 +567,7 @@ struct sock *sk = sock->sk; struct net_device *dev = NULL; struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr; - struct pppox_opt *po = sk->protinfo.pppox; + struct pppox_opt *po = PPPOX_SK(sk); int error; lock_sock(sk); @@ -657,7 +656,7 @@ sp.sa_family = AF_PPPOX; sp.sa_protocol = PX_PROTO_OE; - memcpy(&sp.sa_addr.pppoe, &sock->sk->protinfo.pppox->pppoe_pa, + memcpy(&sp.sa_addr.pppoe, &PPPOX_SK(sock->sk)->pppoe_pa, sizeof(struct pppoe_addr)); memcpy(uaddr, &sp, len); @@ -672,11 +671,10 @@ unsigned long arg) { struct sock *sk = sock->sk; - struct pppox_opt *po; + struct pppox_opt *po = PPPOX_SK(sk); int val = 0; int err = 0; - po = sk->protinfo.pppox; switch (cmd) { case PPPIOCGMRU: err = -ENXIO; @@ -794,7 +792,7 @@ lock_sock(sk); - dev = sk->protinfo.pppox->pppoe_dev; + dev = PPPOX_SK(sk)->pppoe_dev; error = -EMSGSIZE; if (total_len > (dev->mtu + dev->hard_header_len)) @@ -829,8 +827,7 @@ error = total_len; dev->hard_header(skb, dev, ETH_P_PPP_SES, - sk->protinfo.pppox->pppoe_pa.remote, - NULL, total_len); + PPPOX_SK(sk)->pppoe_pa.remote, NULL, total_len); memcpy(ph, &hdr, sizeof(struct pppoe_hdr)); @@ -851,7 +848,7 @@ ***********************************************************************/ int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) { - struct net_device *dev = sk->protinfo.pppox->pppoe_dev; + struct net_device *dev = PPPOX_SK(sk)->pppoe_dev; struct pppoe_hdr hdr; struct pppoe_hdr *ph; int headroom = skb_headroom(skb); @@ -897,8 +894,7 @@ skb2->dev = dev; dev->hard_header(skb2, dev, ETH_P_PPP_SES, - sk->protinfo.pppox->pppoe_pa.remote, - NULL, data_len); + PPPOX_SK(sk)->pppoe_pa.remote, NULL, data_len); /* We're transmitting skb2, and assuming that dev_queue_xmit * will free it. The generic ppp layer however, is expecting Index: kernel-acme/drivers/net/pppox.c diff -u kernel-acme/drivers/net/pppox.c:1.1.1.3 kernel-acme/drivers/net/pppox.c:1.1.1.3.4.1 --- kernel-acme/drivers/net/pppox.c:1.1.1.3 Fri Nov 23 19:55:50 2001 +++ kernel-acme/drivers/net/pppox.c Tue Dec 11 00:26:44 2001 @@ -68,7 +68,7 @@ /* Clear connection to ppp device, if attached. */ if (sk->state & PPPOX_BOUND) { - ppp_unregister_channel(&sk->protinfo.pppox->chan); + ppp_unregister_channel(&PPPOX_SK(sk)->chan); sk->state &= ~PPPOX_BOUND; } } @@ -81,10 +81,8 @@ unsigned long arg) { struct sock *sk = sock->sk; - struct pppox_opt *po; + struct pppox_opt *po = PPPOX_SK(sk); int err = 0; - - po = sk->protinfo.pppox; lock_sock(sk); Index: kernel-acme/drivers/net/hamradio/6pack.c diff -u kernel-acme/drivers/net/hamradio/6pack.c:1.1.1.2 kernel-acme/drivers/net/hamradio/6pack.c:1.1.1.2.8.1 --- kernel-acme/drivers/net/hamradio/6pack.c:1.1.1.2 Wed Sep 26 22:02:27 2001 +++ kernel-acme/drivers/net/hamradio/6pack.c Sat Dec 22 00:21:21 2001 @@ -700,7 +700,6 @@ /* Initialize 6pack control device -- register 6pack line discipline */ static char msg_banner[] __initdata = KERN_INFO "AX.25: 6pack driver, " SIXPACK_VERSION " (dynamic channels, max=%d)\n"; -static char msg_invparm[] __initdata = KERN_ERR "6pack: sixpack_maxdev parameter too large.\n"; static char msg_nomem[] __initdata = KERN_ERR "6pack: can't allocate sixpack_ctrls[] array! No 6pack available.\n"; static char msg_regfail[] __initdata = KERN_ERR "6pack: can't register line discipline (err = %d)\n"; Index: kernel-acme/drivers/net/wan/comx-hw-mixcom.c diff -u kernel-acme/drivers/net/wan/comx-hw-mixcom.c:1.1.1.4 kernel-acme/drivers/net/wan/comx-hw-mixcom.c:1.1.1.4.8.1 --- kernel-acme/drivers/net/wan/comx-hw-mixcom.c:1.1.1.4 Wed Sep 26 22:02:19 2001 +++ kernel-acme/drivers/net/wan/comx-hw-mixcom.c Sat Dec 22 00:21:21 2001 @@ -565,9 +565,6 @@ } return 0; - -err_restore_flags: - restore_flags(flags); err_release_region: release_region(dev->base_addr, MIXCOM_IO_EXTENT); err_ret: Index: kernel-acme/drivers/net/wan/cycx_drv.c diff -u kernel-acme/drivers/net/wan/cycx_drv.c:1.1.1.2 kernel-acme/drivers/net/wan/cycx_drv.c:1.1.1.2.6.1 --- kernel-acme/drivers/net/wan/cycx_drv.c:1.1.1.2 Tue Nov 6 18:57:10 2001 +++ kernel-acme/drivers/net/wan/cycx_drv.c Sat Dec 22 02:19:28 2001 @@ -47,7 +47,6 @@ * Dec 8, 1998 Ivan Passos Cyclom-2X firmware load implementation. * Aug 8, 1998 acme Initial version. */ - #include /* __init */ #include #include /* printk(), and other useful stuff */ @@ -66,7 +65,6 @@ MODULE_DESCRIPTION("Cyclom 2x Sync Card Driver"); MODULE_LICENSE("GPL"); - /* Function Prototypes */ /* Module entry points. These are called by the OS and must be public. */ int init_module(void); @@ -86,13 +84,6 @@ #define wait_cyc(addr) cycx_exec(addr + CMD_OFFSET) -#define cyc2x_readb(b) readb(b) -#define cyc2x_readw(b) readw(b) -#define cyc2x_writeb(b, addr) writeb(b, addr) -#define cyc2x_writew(w, addr) writew(w, addr) -#define cyc2x_memcpy_toio(addr, buf, len) memcpy_toio((addr), buf, len) -#define cyc2x_memcpy_fromio(buf, addr, len) memcpy_fromio(buf, (addr), len) - /* Global Data */ /* private data */ @@ -100,19 +91,15 @@ static char fullname[] = "Cyclom 2X Support Module"; static char copyright[] = "(c) 1998-2000 Arnaldo Carvalho de Melo " ""; - /* Hardware configuration options. * These are arrays of configuration options used by verification routines. - * The first element of each array is its size (i.e. number of options). - */ -static u32 cyc2x_dpmbase_options[] = -{ + * The first element of each array is its size (i.e. number of options). */ +static u32 cyc2x_dpmbase_options[] = { 20, 0xA0000, 0xA4000, 0xA8000, 0xAC000, 0xB0000, 0xB4000, 0xB8000, 0xBC000, 0xC0000, 0xC4000, 0xC8000, 0xCC000, 0xD0000, 0xD4000, 0xD8000, 0xDC000, 0xE0000, 0xE4000, 0xE8000, 0xEC000 }; - static u32 cycx_2x_irq_options[] = { 7, 3, 5, 9, 10, 11, 12, 15 }; /* Kernel Loadable Module Entry Points */ @@ -128,7 +115,6 @@ { printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE, copyright); - return 0; } @@ -152,51 +138,43 @@ int cycx_setup(cycxhw_t *hw, void *cfm, u32 len) { unsigned long dpmbase = hw->dpmbase; - int err; + int err = -EINVAL; /* Verify IRQ configuration options */ if (!get_option_index(cycx_2x_irq_options, hw->irq)) { printk(KERN_ERR "%s: IRQ %d is illegal!\n", modname, hw->irq); - return -EINVAL; + goto out; } - /* Setup adapter dual-port memory window and test memory */ if (!hw->dpmbase) { printk(KERN_ERR "%s: you must specify the dpm address!\n", modname); - return -EINVAL; + goto out; } else if (!get_option_index(cyc2x_dpmbase_options, hw->dpmbase)) { printk(KERN_ERR "%s: memory address 0x%lX is illegal!\n", modname, dpmbase); - return -EINVAL; + goto out; } - hw->dpmbase = (u32)ioremap(dpmbase, CYCX_WINDOWSIZE); hw->dpmsize = CYCX_WINDOWSIZE; - if (!detect_cyc2x(hw->dpmbase)) { printk(KERN_ERR "%s: adapter Cyclom 2X not found at " "address 0x%lX!\n", modname, dpmbase); - return -EINVAL; + goto out; } - printk(KERN_INFO "%s: found Cyclom 2X card at address 0x%lX.\n", modname, dpmbase); - /* Load firmware. If loader fails then shut down adapter */ err = load_cyc2x(hw, cfm, len); - if (err) cycx_down(hw); /* shutdown adapter */ - - return err; +out: return err; } EXPORT_SYMBOL(cycx_down); int cycx_down(cycxhw_t *hw) { iounmap((u32 *)hw->dpmbase); - return 0; } @@ -204,14 +182,14 @@ EXPORT_SYMBOL(cycx_inten); void cycx_inten(cycxhw_t *hw) { - cyc2x_writeb(0, hw->dpmbase); + writeb(0, hw->dpmbase); } /* Generate an interrupt to adapter's CPU. */ EXPORT_SYMBOL(cycx_intr); void cycx_intr(cycxhw_t *hw) { - cyc2x_writew(0, hw->dpmbase + GEN_CYCX_INTR); + writew(0, hw->dpmbase + GEN_CYCX_INTR); } /* Execute Adapter Command. @@ -225,11 +203,9 @@ while (cyc2x_readw(addr)) { udelay(1000); - if (++i > 50) return -1; } - return 0; } @@ -239,10 +215,9 @@ int cycx_peek(cycxhw_t *hw, u32 addr, void *buf, u32 len) { if (len == 1) - *(u8*)buf = cyc2x_readb(hw->dpmbase + addr); + *(u8*)buf = readb(hw->dpmbase + addr); else - cyc2x_memcpy_fromio(buf, hw->dpmbase + addr, len); - + memcpy_fromio(buf, hw->dpmbase + addr, len); return 0; } @@ -252,10 +227,9 @@ int cycx_poke(cycxhw_t *hw, u32 addr, void *buf, u32 len) { if (len == 1) - cyc2x_writeb(*(u8*)buf, hw->dpmbase + addr); + writeb(*(u8*)buf, hw->dpmbase + addr); else - cyc2x_memcpy_toio(hw->dpmbase + addr, buf, len); - + memcpy_toio(hw->dpmbase + addr, buf, len); return 0; } @@ -269,15 +243,13 @@ int tries = 0; for (; tries < 3 ; tries++) { - cyc2x_writew(TEST_PATTERN, addr + 0x10); + writew(TEST_PATTERN, addr + 0x10); - if (cyc2x_readw(addr + 0x10) == TEST_PATTERN) - if (cyc2x_readw(addr + 0x10) == TEST_PATTERN) + if (readw(addr + 0x10) == TEST_PATTERN) + if (readw(addr + 0x10) == TEST_PATTERN) return 1; - delay_cycx(1); } - return 0; } @@ -285,12 +257,10 @@ static void reset_load(u32 addr, u8 *buffer, u32 cnt) { u32 pt_code = addr + RESET_OFFSET; - u16 i; /*, j; */ + u16 i = 0; - for (i = 0 ; i < cnt ; i++) { -/* for (j = 0 ; j < 50 ; j++); Delay - FIXME busy waiting... */ - cyc2x_writeb(*buffer++, pt_code++); - } + for (;i < cnt ; i++) + writeb(*buffer++, pt_code++); } /* Load buffer using boot interface. @@ -298,9 +268,8 @@ * o wait for reset code to copy it to right portion of memory */ static int buffer_load(u32 addr, u8 *buffer, u32 cnt) { - cyc2x_memcpy_toio(addr + DATA_OFFSET, buffer, cnt); - cyc2x_writew(GEN_BOOT_DAT, addr + CMD_OFFSET); - + memcpy_toio(addr + DATA_OFFSET, buffer, cnt); + writew(GEN_BOOT_DAT, addr + CMD_OFFSET); return wait_cyc(addr); } @@ -308,14 +277,13 @@ static void cycx_start(u32 addr) { /* put in 0x30 offset the jump instruction to the code entry point */ - cyc2x_writeb(0xea, addr + 0x30); - cyc2x_writeb(0x00, addr + 0x31); - cyc2x_writeb(0xc4, addr + 0x32); - cyc2x_writeb(0x00, addr + 0x33); - cyc2x_writeb(0x00, addr + 0x34); - + writeb(0xea, addr + 0x30); + writeb(0x00, addr + 0x31); + writeb(0xc4, addr + 0x32); + writeb(0x00, addr + 0x33); + writeb(0x00, addr + 0x34); /* cmd to start executing code */ - cyc2x_writew(GEN_START, addr + CMD_OFFSET); + writew(GEN_START, addr + CMD_OFFSET); } /* Load and boot reset code. */ @@ -323,15 +291,14 @@ { u32 pt_start = addr + START_OFFSET; - cyc2x_writeb(0xea, pt_start++); /* jmp to f000:3f00 */ - cyc2x_writeb(0x00, pt_start++); - cyc2x_writeb(0xfc, pt_start++); - cyc2x_writeb(0x00, pt_start++); - cyc2x_writeb(0xf0, pt_start); + writeb(0xea, pt_start++); /* jmp to f000:3f00 */ + writeb(0x00, pt_start++); + writeb(0xfc, pt_start++); + writeb(0x00, pt_start++); + writeb(0xf0, pt_start); reset_load(addr, code, len); - /* 80186 was in hold, go */ - cyc2x_writeb(0, addr + START_CPU); + writeb(0, addr + START_CPU); delay_cycx(1); } @@ -342,26 +309,22 @@ u32 i; /* boot buffer lenght */ - cyc2x_writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16)); - cyc2x_writew(GEN_DEFPAR, pt_boot_cmd); + writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16)); + writew(GEN_DEFPAR, pt_boot_cmd); if (wait_cyc(addr) < 0) return -1; - - cyc2x_writew(0, pt_boot_cmd + sizeof(u16)); - cyc2x_writew(0x4000, pt_boot_cmd + 2 * sizeof(u16)); - cyc2x_writew(GEN_SET_SEG, pt_boot_cmd); - + writew(0, pt_boot_cmd + sizeof(u16)); + writew(0x4000, pt_boot_cmd + 2 * sizeof(u16)); + writew(GEN_SET_SEG, pt_boot_cmd); if (wait_cyc(addr) < 0) return -1; - for (i = 0 ; i < len ; i += CFM_LOAD_BUFSZ) if (buffer_load(addr, code + i, MIN(CFM_LOAD_BUFSZ, (len - i))) < 0) { printk(KERN_ERR "%s: Error !!\n", modname); return -1; } - return 0; } @@ -373,25 +336,22 @@ u32 i; /* boot buffer lenght */ - cyc2x_writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16)); - cyc2x_writew(GEN_DEFPAR, pt_boot_cmd); + writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16)); + writew(GEN_DEFPAR, pt_boot_cmd); if (wait_cyc(addr) < 0) return -1; - - cyc2x_writew(0x0000, pt_boot_cmd + sizeof(u16)); - cyc2x_writew(0xc400, pt_boot_cmd + 2 * sizeof(u16)); - cyc2x_writew(GEN_SET_SEG, pt_boot_cmd); + writew(0x0000, pt_boot_cmd + sizeof(u16)); + writew(0xc400, pt_boot_cmd + 2 * sizeof(u16)); + writew(GEN_SET_SEG, pt_boot_cmd); if (wait_cyc(addr) < 0) return -1; - for (i = 0 ; i < len ; i += CFM_LOAD_BUFSZ) if (buffer_load(addr, code + i,MIN(CFM_LOAD_BUFSZ,(len - i)))) { printk(KERN_ERR "%s: Error !!\n", modname); return -1; } - return 0; } @@ -411,7 +371,6 @@ /* Announce */ printk(KERN_INFO "%s: firmware signature=\"%s\"\n", modname, cfm->signature); - /* Verify firmware signature */ if (strcmp(cfm->signature, CFM_SIGNATURE)) { printk(KERN_ERR "%s:load_cyc2x: not Cyclom-2X firmware!\n", @@ -423,12 +382,11 @@ /* Verify firmware module format version */ if (cfm->version != CFM_VERSION) { - printk(KERN_ERR "%s:" __FUNCTION__ ": firmware format %u rejected! " - "Expecting %u.\n", - modname, cfm->version, CFM_VERSION); + printk(KERN_ERR "%s:" __FUNCTION__ + ": firmware format %u rejected! Expecting %u.\n", + modname, cfm->version, CFM_VERSION); return -EINVAL; } - /* Verify firmware module length and checksum */ cksum = checksum((u8*)&cfm->info, sizeof(cfm_info_t) + cfm->info.codesize); @@ -438,16 +396,14 @@ */ if (cksum != cfm->checksum) { printk(KERN_ERR "%s:" __FUNCTION__ ": firmware corrupted!\n", - modname); + modname); printk(KERN_ERR " cdsize = 0x%x (expected 0x%lx)\n", - len - sizeof(cfm_t) - 1, cfm->info.codesize); - printk(KERN_ERR " chksum = 0x%x (expected 0x%x)\n", - cksum, cfm->checksum); + len - sizeof(cfm_t) - 1, cfm->info.codesize); + printk(KERN_ERR " chksum = 0x%x (expected 0x%x)\n", cksum, + cfm->checksum); return -EINVAL; } - /* If everything is ok, set reset, data and code pointers */ - img_hdr = (cycx_header_t*)(((u8*)cfm) + sizeof(cfm_t) - 1); #ifdef FIRMWARE_DEBUG printk(KERN_INFO "%s:" __FUNCTION__ ": image sizes\n", modname); @@ -458,13 +414,11 @@ reset_image = ((u8 *)img_hdr) + sizeof(cycx_header_t); data_image = reset_image + img_hdr->reset_size; code_image = data_image + img_hdr->data_size; - - /*---- Start load ----*/ + /* Start load */ /* Announce */ printk(KERN_INFO "%s: loading firmware %s (ID=%u)...\n", modname, cfm->descr[0] ? cfm->descr : "unknown firmware", cfm->info.codeid); - for (i = 0 ; i < 5 ; i++) { /* Reset Cyclom hardware */ if (!reset_cyc2x(hw->dpmbase)) { @@ -472,50 +426,41 @@ modname); return -EINVAL; } - /* Load reset.bin */ cycx_reset_boot(hw->dpmbase, reset_image, img_hdr->reset_size); /* reset is waiting for boot */ - cyc2x_writew(GEN_POWER_ON, pt_cycld); + writew(GEN_POWER_ON, pt_cycld); delay_cycx(1); for (j = 0 ; j < 3 ; j++) - if (!cyc2x_readw(pt_cycld)) + if (!readw(pt_cycld)) goto reset_loaded; else delay_cycx(1); } - printk(KERN_ERR "%s: reset not started.\n", modname); return -EINVAL; - reset_loaded: /* Load data.bin */ if (cycx_data_boot(hw->dpmbase, data_image, img_hdr->data_size)) { printk(KERN_ERR "%s: cannot load data file.\n", modname); return -EINVAL; } - /* Load code.bin */ if (cycx_code_boot(hw->dpmbase, code_image, img_hdr->code_size)) { printk(KERN_ERR "%s: cannot load code file.\n", modname); return -EINVAL; } - /* Prepare boot-time configuration data */ cycx_bootcfg(hw); - /* kick-off CPU */ cycx_start(hw->dpmbase); - /* Arthur Ganzert's tip: wait a while after the firmware loading... seg abr 26 17:17:12 EST 1999 - acme */ delay_cycx(7); printk(KERN_INFO "%s: firmware loaded!\n", modname); - /* enable interrupts */ cycx_inten(hw); - return 0; } @@ -528,7 +473,7 @@ static void cycx_bootcfg(cycxhw_t *hw) { /* use fixed buffers */ - cyc2x_writeb(FIXED_BUFFERS, hw->dpmbase + CONF_OFFSET); + writeb(FIXED_BUFFERS, hw->dpmbase + CONF_OFFSET); } /* Detect Cyclom 2x adapter. @@ -540,7 +485,6 @@ static int detect_cyc2x(u32 addr) { reset_cyc2x(addr); - return memory_exists(addr); } @@ -554,18 +498,16 @@ for (; i <= optlist[0]; ++i) if (optlist[i] == optval) return i; - return 0; } /* Reset adapter's CPU. */ static int reset_cyc2x(u32 addr) { - cyc2x_writeb(0, addr + RST_ENABLE); + writeb(0, addr + RST_ENABLE); delay_cycx(2); - cyc2x_writeb(0, addr + RST_DISABLE); + writeb(0, addr + RST_DISABLE); delay_cycx(2); - return memory_exists(addr); } @@ -591,11 +533,7 @@ if (flag) crc ^= 0x1021; } - return crc; } - module_init(cycx_drv_init); module_exit(cycx_drv_cleanup); - -/* End */ Index: kernel-acme/drivers/scsi/wd7000.c diff -u kernel-acme/drivers/scsi/wd7000.c:1.1.1.2 kernel-acme/drivers/scsi/wd7000.c:1.1.1.2.6.1 --- kernel-acme/drivers/scsi/wd7000.c:1.1.1.2 Tue Nov 6 18:58:27 2001 +++ kernel-acme/drivers/scsi/wd7000.c Thu Dec 13 23:14:50 2001 @@ -1,4 +1,4 @@ -/* $Id: wd7000.c,v 1.1.1.2 2001/11/06 18:58:27 acme Exp $ +/* $Id: wd7000.c,v 1.1.1.2.6.1 2001/12/13 23:14:50 acme Exp $ * linux/drivers/scsi/wd7000.c * * Copyright (C) 1992 Thomas Wuensche @@ -166,6 +166,11 @@ #define ANY2SCSI_INLINE /* undef this to use old macros */ #undef WD7000_DEBUG /* general debug */ +#ifdef WD7000_DEBUG +#define dprintk printk +#else +#define dprintk +#endif #include "wd7000.h" #include @@ -557,7 +562,7 @@ } Icb; #ifdef MODULE -static char * wd7000 = NULL; +static char *wd7000; MODULE_PARM(wd7000, "s"); #endif @@ -568,23 +573,23 @@ * structure is not part of the Adapter structure. */ static Scb scbs[MAX_SCBS]; -static Scb *scbfree = NULL; /* free list */ +static Scb *scbfree; /* free list */ static int freescbs = MAX_SCBS; /* free list counter */ /* * END of data/declarations - code follows. */ -static void setup_error (char *mesg, int *ints) +static void __init setup_error(char *mesg, int *ints) { if (ints[0] == 3) - printk ("wd7000_setup: \"wd7000=%d,%d,0x%x\" -> %s\n", - ints[1], ints[2], ints[3], mesg); + printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x\" -> %s\n", + ints[1], ints[2], ints[3], mesg); else if (ints[0] == 4) - printk ("wd7000_setup: \"wd7000=%d,%d,0x%x,%d\" -> %s\n", - ints[1], ints[2], ints[3], ints[4], mesg); + printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x,%d\" -> %s\n", + ints[1], ints[2], ints[3], ints[4], mesg); else - printk ("wd7000_setup: \"wd7000=%d,%d,0x%x,%d,%d\" -> %s\n", - ints[1], ints[2], ints[3], ints[4], ints[5], mesg); + printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x,%d,%d\" -> %s\n", + ints[1], ints[2], ints[3], ints[4], ints[5], mesg); } @@ -604,21 +609,23 @@ */ static int __init wd7000_setup(char *str) { - static short wd7000_card_num = 0; + static short wd7000_card_num; /* .bss will zero this */ short i, j; int ints[6]; (void)get_options(str, ARRAY_SIZE(ints), ints); if (wd7000_card_num >= NUM_CONFIGS) { - printk("wd7000_setup: Too many \"wd7000=\" configurations in " - "command line!\n"); + printk(KERN_ERR __FUNCTION__ + ": Too many \"wd7000=\" configurations in " + "command line!\n"); return 0; } if ((ints[0] < 3) || (ints[0] > 5)) { - printk("wd7000_setup: Error in command line! " - "Usage: wd7000=,,IO>[,[,]]\n"); + printk(KERN_ERR __FUNCTION__ ": Error in command line! " + "Usage: wd7000=,,IO>[," + "[,]]\n"); } else { for (i = 0; i < NUM_IRQS; i++) if (ints[1] == wd7000_irq[i]) @@ -652,7 +659,8 @@ if (ints[0] > 3) { if ((ints[4] < 500) || (ints[4] > 31875)) { - setup_error("BUS_ON value is out of range (500 to 31875 nanoseconds)!", ints); + setup_error("BUS_ON value is out of range (500" + " to 31875 nanoseconds)!", ints); configs[wd7000_card_num].bus_on = BUS_ON; } else configs[wd7000_card_num].bus_on = ints[4] / 125; @@ -661,10 +669,12 @@ if (ints[0] > 4) { if ((ints[5] < 500) || (ints[5] > 31875)) { - setup_error("BUS_OFF value is out of range (500 to 31875 nanoseconds)!", ints); + setup_error("BUS_OFF value is out of range (500" + " to 31875 nanoseconds)!", ints); configs[wd7000_card_num].bus_off = BUS_OFF; } else - configs[wd7000_card_num].bus_off = ints[5] / 125; + configs[wd7000_card_num].bus_off = ints[5] / + 125; } else configs[wd7000_card_num].bus_off = BUS_OFF; @@ -672,25 +682,31 @@ for (i = 0; i < (wd7000_card_num - 1); i++) for (j = i + 1; j < wd7000_card_num; j++) if (configs[i].irq == configs[j].irq) { - setup_error("duplicated IRQ!", ints); + setup_error("duplicated IRQ!", + ints); return 0; - } else if (configs[i].dma == configs[j].dma) { - setup_error("duplicated DMA channel!", ints); + } + if (configs[i].dma == configs[j].dma) { + setup_error("duplicated DMA " + "channel!", ints); return 0; - } else if (configs[i].iobase == configs[j].iobase) { - setup_error ("duplicated I/O base address!", ints); + } + if (configs[i].iobase == + configs[j].iobase) { + setup_error("duplicated I/O " + "base address!", + ints); return 0; } } -#ifdef WD7000_DEBUG - printk ("wd7000_setup: IRQ=%d, DMA=%d, I/O=0x%x, BUS_ON=%dns, BUS_OFF=%dns\n", + dprintk(KERN_DEBUG "wd7000_setup: IRQ=%d, DMA=%d, I/O=0x%x, " + "BUS_ON=%dns, BUS_OFF=%dns\n", configs[wd7000_card_num].irq, configs[wd7000_card_num].dma, configs[wd7000_card_num].iobase, configs[wd7000_card_num].bus_on * 125, configs[wd7000_card_num].bus_off * 125); -#endif wd7000_card_num++; } @@ -811,7 +827,7 @@ return (1); } - printk ("wd7000 command_out: WAIT failed(%d)\n", len + 1); + printk(KERN_WARNING "wd7000 command_out: WAIT failed(%d)\n", len + 1); return (0); } @@ -929,9 +945,7 @@ Mailbox *ogmbs = host->mb.ogmb; int *next_ogmb = &(host->next_ogmb); -#ifdef WD7000_DEBUG - printk ("wd7000_mail_out: 0x%06lx", (long) scbptr); -#endif + dprintk("wd7000_mail_out: 0x%06lx", (long) scbptr); /* We first look for a free outgoing mailbox */ save_flags (flags); @@ -939,9 +953,7 @@ ogmb = *next_ogmb; for (i = 0; i < OGMB_CNT; i++) { if (ogmbs[ogmb].status == 0) { -#ifdef WD7000_DEBUG - printk (" using OGMB 0x%x", ogmb); -#endif + dprintk(" using OGMB 0x%x", ogmb); ogmbs[ogmb].status = 1; any2scsi ((unchar *) ogmbs[ogmb].scbptr, (int) scbptr); @@ -953,9 +965,7 @@ } restore_flags (flags); -#ifdef WD7000_DEBUG - printk (", scb is 0x%06lx", (long) scbptr); -#endif + dprintk(", scb is 0x%06lx", (long) scbptr); if (i >= OGMB_CNT) { /* @@ -966,9 +976,7 @@ * that marks OGMB's free, waiting even with interrupts off * should work, since they are freed very quickly in most cases. */ -#ifdef WD7000_DEBUG - printk (", no free OGMBs.\n"); -#endif + dprintk(", no free OGMBs.\n"); return (0); } @@ -977,9 +985,7 @@ start_ogmb = START_OGMB | ogmb; command_out (host, &start_ogmb, 1); -#ifdef WD7000_DEBUG - printk (", awaiting interrupt.\n"); -#endif + dprintk(", awaiting interrupt.\n"); return (1); } @@ -1026,7 +1032,7 @@ } #ifdef WD7000_DEBUG if (scsierr || hosterr) - printk ("\nSCSI command error: SCSI 0x%02x host 0x%04x return %d\n", + dprintk("\nSCSI command error: SCSI 0x%02x host 0x%04x return %d\n", scsierr, in_error, hosterr); #endif return (scsierr | (hosterr << 16)); @@ -1035,10 +1041,7 @@ static void wd7000_scsi_done (Scsi_Cmnd *SCpnt) { -#ifdef WD7000_DEBUG - printk ("wd7000_scsi_done: 0x%06lx\n", (long) SCpnt); -#endif - + dprintk("wd7000_scsi_done: 0x%06lx\n", (long)SCpnt); SCpnt->SCp.phase = 0; } @@ -1057,15 +1060,11 @@ host->int_counter++; -#ifdef WD7000_DEBUG - printk ("wd7000_intr_handle: irq = %d, host = 0x%06lx\n", irq, (long) host); -#endif + dprintk("wd7000_intr_handle: irq = %d, host = 0x%06lx\n", irq, (long) host); flag = inb (host->iobase + ASC_INTR_STAT); -#ifdef WD7000_DEBUG - printk ("wd7000_intr_handle: intr stat = 0x%02x\n", flag); -#endif + dprintk("wd7000_intr_handle: intr stat = 0x%02x\n", flag); if (!(inb (host->iobase + ASC_STAT) & INT_IM)) { /* NB: these are _very_ possible if IRQ 15 is being used, since @@ -1076,9 +1075,7 @@ * can sort these out. Otherwise, electrical noise and other such * problems would be indistinguishable from valid interrupts... */ -#ifdef WD7000_DEBUG - printk ("wd7000_intr_handle: phantom interrupt...\n"); -#endif + dprintk("wd7000_intr_handle: phantom interrupt...\n"); wd7000_intr_ack (host); return; } @@ -1086,9 +1083,7 @@ if (flag & MB_INTR) { /* The interrupt is for a mailbox */ if (!(flag & IMB_INTR)) { -#ifdef WD7000_DEBUG - printk ("wd7000_intr_handle: free outgoing mailbox\n"); -#endif + dprintk("wd7000_intr_handle: free outgoing mailbox\n"); /* * If sleep_on() and the "interrupt on free OGMB" command are * used in mail_out(), wake_up() should correspondingly be called @@ -1102,10 +1097,8 @@ icmb = flag & MB_MASK; icmb_status = icmbs[icmb].status; if (icmb_status & 0x80) { /* unsolicited - result in ICMB */ -#ifdef WD7000_DEBUG - printk ("wd7000_intr_handle: unsolicited interrupt 0x%02x\n", + dprintk("wd7000_intr_handle: unsolicited interrupt 0x%02x\n", icmb_status); -#endif wd7000_intr_ack (host); return; } @@ -1135,9 +1128,7 @@ wd7000_intr_ack (host); -#ifdef WD7000_DEBUG - printk ("wd7000_intr_handle: return from interrupt handler\n"); -#endif + dprintk("wd7000_intr_handle: return from interrupt handler\n"); } void do_wd7000_intr_handle (int irq, void *dev_id, struct pt_regs *regs) @@ -1179,9 +1170,7 @@ if (SCpnt->host->sg_tablesize == SG_NONE) { panic ("wd7000_queuecommand: scatter/gather not supported.\n"); } -#ifdef WD7000_DEBUG - printk ("Using scatter/gather with %d elements.\n", SCpnt->use_sg); -#endif + dprintk ("Using scatter/gather with %d elements.\n", SCpnt->use_sg); sgb = scb->sgb; scb->op = 1; @@ -1367,14 +1356,12 @@ save_flags (flags); cli (); -#ifdef WD7000_DEBUG - printk ("Buffer = <%.*s>, length = %d\n", length, buffer, length); -#endif + dprintk("Buffer = <%.*s>, length = %d\n", length, buffer, length); /* * Currently this is a no-op */ - printk ("Sorry, this function is currently out of order...\n"); + dprintk("Sorry, this function is currently out of order...\n"); restore_flags (flags); @@ -1521,9 +1508,7 @@ Adapter *host = NULL; struct Scsi_Host *sh; -#ifdef WD7000_DEBUG - printk ("wd7000_detect: started\n"); -#endif + dprintk("wd7000_detect: started\n"); #ifdef MODULE if (wd7000) @@ -1573,12 +1558,12 @@ * BIOS SIGNATURE has been found. */ #ifdef WD7000_DEBUG - printk ("wd7000_detect: pass %d\n", pass + 1); + dprintk("wd7000_detect: pass %d\n", pass + 1); if (biosaddr_ptr == NUM_ADDRS) - printk ("WD-7000 SST BIOS not detected...\n"); + dprintk("WD-7000 SST BIOS not detected...\n"); else - printk ("WD-7000 SST BIOS detected at 0x%lx: checking...\n", + dprintk("WD-7000 SST BIOS detected at 0x%lx: checking...\n", wd7000_biosaddr[biosaddr_ptr]); #endif @@ -1587,15 +1572,11 @@ iobase = configs[pass].iobase; -#ifdef WD7000_DEBUG - printk ("wd7000_detect: check IO 0x%x region...\n", iobase); -#endif + dprintk("wd7000_detect: check IO 0x%x region...\n", iobase); if (request_region (iobase, 4, "wd7000")) { -#ifdef WD7000_DEBUG - printk ("wd7000_detect: ASC reset (IO 0x%x) ...", iobase); -#endif + dprintk("wd7000_detect: ASC reset (IO 0x%x) ...", iobase); /* * ASC reset... */ @@ -1603,17 +1584,11 @@ delay (1); outb (0, iobase + ASC_CONTROL); - if (WAIT (iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) -#ifdef WD7000_DEBUG - { - printk ("failed!\n"); + if (WAIT (iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) { + dprintk("failed!\n"); goto err_release; - } - else - printk ("ok!\n"); -#else - goto err_release; -#endif + } else + dprintk("ok!\n"); if (inb (iobase + ASC_INTR_STAT) == 1) { /* @@ -1628,11 +1603,9 @@ goto err_release; host = (Adapter *) sh->hostdata; - -#ifdef WD7000_DEBUG - printk ("wd7000_detect: adapter allocated at 0x%x\n", (int) host); -#endif + dprintk("wd7000_detect: adapter allocated at 0x%x\n", + (int)host); memset (host, 0, sizeof (Adapter)); host->irq = configs[pass].irq; @@ -1643,11 +1616,9 @@ host->bus_off = configs[pass].bus_off; host->sh = wd7000_host[host->irq - IRQ_MIN] = sh; -#ifdef WD7000_DEBUG - printk ("wd7000_detect: Trying init WD-7000 card at IO " + dprintk("wd7000_detect: Trying init WD-7000 card at IO " "0x%x, IRQ %d, DMA %d...\n", host->iobase, host->irq, host->dma); -#endif if (!wd7000_init (host)) /* Initialization failed */ goto err_unregister; @@ -1675,13 +1646,10 @@ printk (" BUS_ON time: %dns, BUS_OFF time: %dns\n", host->bus_on * 125, host->bus_off * 125); } - } + } else + dprintk("wd7000_detect: IO 0x%x region already allocated!\n", + iobase); -#ifdef WD7000_DEBUG - else - printk ("wd7000_detect: IO 0x%x region already allocated!\n", iobase); -#endif - continue; err_unregister: @@ -1730,9 +1698,8 @@ */ int wd7000_biosparam (Disk *disk, kdev_t dev, int *ip) { -#ifdef WD7000_DEBUG - printk ("wd7000_biosparam: dev=%s, size=%d, ", kdevname (dev), disk->capacity); -#endif + dprintk("wd7000_biosparam: dev=%s, size=%d, ", kdevname(dev), + disk->capacity); /* * try default translation @@ -1766,14 +1733,13 @@ ip[2] = info[2]; if (info[0] == 255) - printk ("wd7000_biosparam: current partition table is using extended translation.\n"); + printk(KERN_INFO __FUNCTION__ ": current partition table is " + "using extended translation.\n"); } } -#ifdef WD7000_DEBUG - printk ("bios geometry: head=%d, sec=%d, cyl=%d\n", ip[0], ip[1], ip[2]); - printk ("WARNING: check, if the bios geometry is correct.\n"); -#endif + dprintk("bios geometry: head=%d, sec=%d, cyl=%d\n", ip[0], ip[1], ip[2]); + dprintk("WARNING: check, if the bios geometry is correct.\n"); return (0); } Index: kernel-acme/include/linux/af_netb.h diff -u /dev/null kernel-acme/include/linux/af_netb.h:1.1.12.1 --- /dev/null Sat Dec 22 02:21:00 2001 +++ kernel-acme/include/linux/af_netb.h Thu Nov 29 20:36:54 2001 @@ -0,0 +1,192 @@ +#ifndef _LINUX_AF_NETB_H +#define _LINUX_AF_NETB_H +/* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +/* General definitions */ +#define NETBEUI_MAX_DATALEN (64 * 1024) /* 64K-bytes max data buffer len */ +#define NETBEUI_MAX_NAMES 255 /* Maximum number of local names */ +#define NETBEUI_MAX_ADAPTERS 16 /* Maximum number of local adapters */ +#define NETBEUI_MAX_LINKS 256 /* Maximum number of links to others */ +#define NETBEUI_MAX_SESSIONS 255 /* Maximum number of sessions on a link */ + +#define SOCK_NAME SOCK_RAW /* Socket type for Name registration */ +#define NETBEUI_NAME_LEN 16 + +/* NetBEUI address type definitions */ +typedef enum { + NETBEUI_NAME_UNIQUE = 1, + NETBEUI_NAME_GROUP +} name_type_t; + +struct netbeui_addr { + char name[NETBEUI_NAME_LEN]; + unsigned char reserved; /* Safety region */ + name_type_t name_type; +}; + +/* Maximum permitted length of this structure is MAX_SOCK_ADDR defined in + * 'net/socket.c' */ +struct sockaddr_netbeui { + unsigned short snb_family; /* s.b. AF_NETBEUI */ + struct netbeui_addr snb_addr; +}; + +/* NetBEUI Socket Layer Default Values */ +#define NBSO_DFLT_STO_SEC 0 /* Seconds of 'Send Time Out' value */ +#define NBSO_DFLT_STO_MICSEC 0 /* Micro-Seconds of 'Send Time Out' value */ + +#define NBSO_DFLT_RTO_SEC 0 /* Seconds of 'Receive Time Out' value */ +#define NBSO_DFLT_RTO_MICSEC 0 /* Micro-Seconds of 'Receive Time Out' value */ + +/* NetBEUI ioctls */ +/* From 0x89E0 to 0x89EF are protocol private 'ioctl numbers' *\ + * For more information see SIOCDEVPRIVATE and SIOCPROTOPRIVATE definitions * +\* in 'include/linux/sockios.h' file */ + +/* NetBEUI specific I/O ConTroL calls (ioctl) */ +#define SIOCGSTATE (SIOCPROTOPRIVATE) /* Gets NetBEUI socket state */ +#define SIOCTRIMDATA (SIOCPROTOPRIVATE + 1) /* Trims last bytes of current + message */ +#define SIOCSENDZERO (SIOCPROTOPRIVATE + 2) /* Send a dummy session message with + zero size */ +#define SIOCRUWDGF (SIOCPROTOPRIVATE + 3) /* Removes an UnWanted DataGram + Frames */ +#define NBIOCGSTATUS (SIOCPROTOPRIVATE + 4) /* Gets NetBIOS STATUS of local or + remote node */ +#define NBIOCCONFIG (SIOCPROTOPRIVATE + 5) /* Configures NetBEUI during + running */ +/* NetBEUI 'SIOCGSTATE' ioctl() Constants */ +typedef enum { + NBSO_INIT = 0, + NBSO_LISTENING, + NBSO_RUNNING +} nbso_state_t; + +/* NetBEUI Configuration (via NBIOCCONFIG ioctl) */ +/* NetBEUI Configuration request constants */ +#define NETBEUI_UNBIND_FLAG_SAFE 0 /* Unbinds device only if no connection + exist on it */ +#define NETBEUI_UNBIND_FLAG_DROP 1 /* Drops connections that exist on device + and then unbinds it */ +#define NETBEUI_CFGCMD_NIF_UNBIND 0 +#define NETBEUI_CFGCMD_NIF_BIND 1 +#define NETBEUI_CFGCMD_DROP_SESS 2 +#define NETBEUI_CFGCMD_DROP_LINK 3 + +/* NetBEUI Configuration request data structure */ +struct netbeui_cfg { + unsigned short command; /* NETBEUI_CFGCMD_... */ + char nif_name[IFNAMSIZ]; + unsigned char reserved; /* Safety region, always must be zero */ + unsigned char flag; /* NETBEUI_UNBIND_FLAG_... */ + int ln_num; /* 0 <= ln_num < NETBEUI_MAX_LINKS */ + int sn_num; /* 0 < sn_num < NETBEUI_MAX_SESSIONS */ +}; + +/* NetBEUI setsockopt / getsockopt */ +/* + * NetBEUI specific option names for setsockopt() & getsockopt() + * + * Note: Remainder of option names defined in 'asm/socket.h' from 1 to 15 + */ +#define SO_URGENTACK 106 +#define SO_NBPARAM 107 + +/* + * NetBEUI configurable parameters use by SO_NBPARAM + * + * Note: Setting value of a parameter to zero means no change to the + * current value. + */ +struct netbeui_config { + __u8 inactivity_timeout; + __u8 transmit_timeout; + __u8 transmit_count; + __u8 resource_timeout; + __u8 data_ack_timeout; +}; + +/* Definition of default and maximum value of NetBIOS configurable parameters */ +#define NETBEUI_DFLT_LINK_INACT_TMOUT 30 /* Unit is second */ +#define NETBEUI_MAX_LINK_INACT_TMOUT 255 /* Unit is second */ +#define NETBEUI_DFLT_TX_TMOUT 1 /* Unit is 1/2 second */ +#define NETBEUI_MAX_TX_TMOUT 10 /* Unit is 1/2 second */ +#define NETBEUI_DFLT_TX_COUNT 6 +#define NETBEUI_MAX_TX_COUNT 10 +#define NETBEUI_DFLT_RSRC_TMOUT 1 /* Unit is 1/10 second */ +#define NETBEUI_MAX_RSRC_TMOUT 10 /* Unit is 1/10 second */ +#define NETBEUI_DFLT_DATA_ACK_TMOUT 1 /* Unit is 1/10 second */ +#define NETBEUI_MAX_DATA_ACK_TMOUT 10 /* Unit is 1/10 second */ + +/* NetBEUI STATUS Service */ +/* NetBEUI status service constants */ +#define NETBEUI_MIN_STATUS_BUFF_LEN 60 +#define NETBEUI_MAX_STATUS_BUFF_LEN (NETBEUI_MIN_STATUS_BUFF_LEN + \ + 18 * NETBEUI_MAX_NAMES) +/* NetBEUI STATUS request data structure */ +struct netbeui_status { + char called_name[NETBEUI_NAME_LEN]; + char reserved; /* Safety region, always must be zero */ + int buff_len; + char status_buff[0]; /* A dynamic length array for status information */ +}; + +/* Adapter types in status information */ +enum { + NETBEUI_3174_PEER = 0xFB, + NETBEUI_IBM_FDDI, + NETBEUI_ETHERNET, + NETBEUI_PC_NETWORK, + NETBEUI_TOKEN_RING +}; + +/* Name structure in status information */ +struct nb_status_names { + char name[NETBEUI_NAME_LEN]; + __u8 name_number; + __u8 name_status; +}; + +/* STATUS information structure */ +typedef struct { + __u8 adptr_addr[6]; + __u8 sftwr_release_no; + __u8 zero; + struct { + __u8 adptr_type; + __u8 sftwr_level; + } adptr_type_AND_sftwr_level; + __u16 duration; + __u16 no_rx_FRMR; /* NOT SUPPORTED YET */ + __u16 no_tx_FRMR; /* NOT SUPPORTED YET */ + __u16 no_rx_Iformat_LPDUs; /* NOT SUPPORTED YET */ + __u16 no_abrtd_transmissions; /* NOT SUPPORTED YET */ + __u32 no_succ_tx_packets; /* NOT SUPPORTED YET */ + __u32 no_succ_rx_packets; /* NOT SUPPORTED YET */ + __u16 no_tx_Iformat_LPDUs; /* NOT SUPPORTED YET */ + __u16 lost_data_OR_buff_fails; /* NOT SUPPORTED YET */ + __u16 no_DLC_T1_expired; /* NOT SUPPORTED YET */ + __u16 no_DLC_Ti_expired; /* NOT SUPPORTED YET */ + __u32 ext_status_inf_addr; /* NOT SUPPORTED YET */ + __u16 no_free_NCBs; /* NOT SUPPORTED YET */ + __u16 config_max_NCBs; /* NOT SUPPORTED YET */ + __u16 max_no_NCBs; /* NOT SUPPORTED YET */ + __u16 local_busy_OR_buff_fails; /* NOT SUPPORTED YET */ + __u16 max_dgram_packet_size; + __u16 no_pend_sess; /* NOT SUPPORTED YET */ + __u16 config_max_pend_sess; /* NOT SUPPORTED YET */ + __u16 max_no_pend_sess; + __u16 max_size_sess_data_packet; + __u16 no_names_in_local_name_tbl; + struct nb_status_names local_names[NETBEUI_MAX_NAMES]; +} nb_status_buffer_t; +#endif /* _LINUX_AF_NETB_H */ Index: kernel-acme/include/linux/atalk.h diff -u kernel-acme/include/linux/atalk.h:1.1.1.1 kernel-acme/include/linux/atalk.h:1.1.1.1.12.2 --- kernel-acme/include/linux/atalk.h:1.1.1.1 Tue Jun 26 17:34:04 2001 +++ kernel-acme/include/linux/atalk.h Mon Dec 17 15:04:50 2001 @@ -176,5 +176,7 @@ extern void aarp_cleanup_module(void); #endif /* MODULE */ +#define AT_SK(__sk) ((struct atalk_sock *)(__sk)->protinfo) + #endif /* __KERNEL__ */ #endif /* __LINUX_ATALK_H__ */ Index: kernel-acme/include/linux/atmdev.h diff -u kernel-acme/include/linux/atmdev.h:1.1.1.3 kernel-acme/include/linux/atmdev.h:1.1.1.3.4.2 --- kernel-acme/include/linux/atmdev.h:1.1.1.3 Fri Nov 23 22:43:30 2001 +++ kernel-acme/include/linux/atmdev.h Mon Dec 17 15:04:50 2001 @@ -33,7 +33,8 @@ #define ATM_PDU_OVHD 0 /* number of bytes to charge against buffer quota per PDU */ -#define ATM_SD(s) ((s)->sk->protinfo.af_atm) +#define ATM_SK(__sk) ((struct atm_vcc *)(__sk)->protinfo) +#define ATM_SD(s) (ATM_SK((s)->sk)) #define __AAL_STAT_ITEMS \ Index: kernel-acme/include/linux/brlock.h diff -u kernel-acme/include/linux/brlock.h:1.1.1.2 kernel-acme/include/linux/brlock.h:1.1.1.2.8.1 --- kernel-acme/include/linux/brlock.h:1.1.1.2 Wed Sep 26 22:05:08 2001 +++ kernel-acme/include/linux/brlock.h Thu Nov 29 20:36:54 2001 @@ -28,13 +28,15 @@ * load-locked/store-conditional cpus (ALPHA/MIPS/PPC) and * compare-and-swap cpus (Sparc64). So we control which * implementation to use with a __BRLOCK_USE_ATOMICS define. -DaveM + * + * Added BR_LLC_LOCK for use in net/core/ext8022.c -acme */ /* Register bigreader lock indices here. */ enum brlock_indices { BR_GLOBALIRQ_LOCK, BR_NETPROTO_LOCK, - + BR_LLC_LOCK, __BR_END }; Index: kernel-acme/include/linux/dextab.h diff -u /dev/null kernel-acme/include/linux/dextab.h:1.1.12.1 --- /dev/null Sat Dec 22 02:21:00 2001 +++ kernel-acme/include/linux/dextab.h Thu Nov 29 20:36:54 2001 @@ -0,0 +1,58 @@ +#ifndef __LINUX_DEXTAB_H +#define __LINUX_DEXTAB_H +/* + * dextab.h - Contains definition of dynamically expandable tables + * + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include + +/* Dynamically expandable table structure */ +struct dex_table { + void ** addr; + __u16 size; + __u16 reserved; + __u16 max_size; + __u16 count; + spinlock_t lock; +}; +typedef struct dex_table dextab_t; + +#define DEXTAB_NOFREE_ENTRY 0 +#define DEXTAB_FREE_ENTRY 1 + +#define dextab_add_entry(tbl, entry_size) \ + dextab_add_insert_entry(tbl, entry_size, NULL) +#define dextab_insert_entry(tbl, entry) dextab_add_insert_entry(tbl, 0, entry) +#define dextab_remove_index(tbl, entry_index) \ + dextab_remove_delete_index(tbl, entry_index, DEXTAB_FREE_ENTRY) +#define dextab_delete_index(tbl, entry_index) \ + dextab_remove_delete_index(tbl, entry_index, DEXTAB_NOFREE_ENTRY) +#define __dextab_delete_index(tbl, entry_index) \ + __dextab_remove_delete_index(tbl, entry_index, DEXTAB_NOFREE_ENTRY) +#define dextab_remove_entry(tbl, entry) \ + dextab_remove_delete_index(tbl, dextab_entry_index(tbl, entry), \ + DEXTAB_FREE_ENTRY) +#define dextab_delete_entry(tbl, entry) \ + dextab_remove_delete_index(tbl, dextab_entry_index(tbl, entry), \ + DEXTAB_NOFREE_ENTRY) +/* Dynamically expandable table interface */ +extern void dextab_init(dextab_t *tbl, int reserved, int max_size); +extern int dextab_add_insert_entry(dextab_t *tbl, int entry_size, void *entry); +extern void __dextab_remove_delete_index(dextab_t *tbl, int entry_index, + int flag); +extern void dextab_remove_delete_index(dextab_t *tbl, int entry_index, + int flag); +extern int dextab_entry_index(dextab_t *tbl, void *entry); +extern inline int __dextab_count_entries(dextab_t *tbl); +extern inline int dextab_count_entries(dextab_t *tbl); +extern void dextab_destruct(dextab_t *tbl); +#endif /* __LINUX_DEXTAB_H */ Index: kernel-acme/include/linux/if_ec.h diff -u kernel-acme/include/linux/if_ec.h:1.1.1.1 kernel-acme/include/linux/if_ec.h:1.1.1.1.12.2 --- kernel-acme/include/linux/if_ec.h:1.1.1.1 Tue Jun 26 17:34:04 2001 +++ kernel-acme/include/linux/if_ec.h Mon Dec 17 15:04:50 2001 @@ -55,6 +55,8 @@ unsigned char net; }; +#define EC_SK(__sk) ((struct econet_opt *)(__sk)->protinfo) + struct ec_device { unsigned char station, net; /* Econet protocol address */ Index: kernel-acme/include/linux/if_pppox.h diff -u kernel-acme/include/linux/if_pppox.h:1.1.1.2 kernel-acme/include/linux/if_pppox.h:1.1.1.2.10.2 --- kernel-acme/include/linux/if_pppox.h:1.1.1.2 Thu Aug 16 21:48:34 2001 +++ kernel-acme/include/linux/if_pppox.h Mon Dec 17 15:04:50 2001 @@ -113,6 +113,26 @@ } __attribute__ ((packed)); #ifdef __KERNEL__ +struct pppoe_opt { + struct net_device *dev; /* device associated with socket*/ + struct pppoe_addr pa; /* what this socket is bound to*/ + struct sockaddr_pppox relay; /* what socket data will be + relayed to (PPPoE relaying) */ +}; + +struct pppox_opt { + struct ppp_channel chan; + struct sock *sk; + struct pppox_opt *next; /* for hash table */ + union { + struct pppoe_opt pppoe; + } proto; +}; +#define pppoe_dev proto.pppoe.dev +#define pppoe_pa proto.pppoe.pa +#define pppoe_relay proto.pppoe.relay + +#define PPPOX_SK(__sk) ((struct pppox_opt *)(__sk)->protinfo) struct pppox_proto { int (*create)(struct socket *sock); Index: kernel-acme/include/linux/if_wanpipe.h diff -u kernel-acme/include/linux/if_wanpipe.h:1.1.1.1 kernel-acme/include/linux/if_wanpipe.h:1.1.1.1.12.2 --- kernel-acme/include/linux/if_wanpipe.h:1.1.1.1 Tue Jun 26 17:34:02 2001 +++ kernel-acme/include/linux/if_wanpipe.h Mon Dec 17 15:04:50 2001 @@ -123,6 +123,9 @@ unsigned char force; /* Used to force sock release */ atomic_t packet_sent; }; + +#define WP_SK(__sk) ((struct wanpipe_opt *)(__sk)->protinfo) + #endif #endif Index: kernel-acme/include/linux/ip.h diff -u kernel-acme/include/linux/ip.h:1.1.1.1 kernel-acme/include/linux/ip.h:1.1.1.1.12.3 --- kernel-acme/include/linux/ip.h:1.1.1.1 Tue Jun 26 17:33:59 2001 +++ kernel-acme/include/linux/ip.h Fri Dec 21 02:12:13 2001 @@ -111,6 +111,27 @@ }; #define optlength(opt) (sizeof(struct ip_options) + opt->optlen) + +struct inet_opt { + int ttl; /* TTL setting */ + int tos; /* TOS */ + unsigned cmsg_flags; + struct ip_options *opt; + unsigned char hdrincl; /* Include headers ? */ + __u8 mc_ttl; /* Multicasting TTL */ + __u8 mc_loop; /* Loopback */ + unsigned recverr : 1, + freebind : 1; + __u16 id; /* ID counter for DF pkts */ + __u8 pmtudisc; + int mc_index; /* Multicast device index */ + __u32 mc_addr; + struct ip_mc_socklist *mc_list; /* Group array */ +}; + +#include + +#define IP_SK(__sk) ((struct inet_opt *)(((struct sock *)(__sk)) + 1)) #endif struct iphdr { Index: kernel-acme/include/linux/ipv6.h diff -u kernel-acme/include/linux/ipv6.h:1.1.1.1 kernel-acme/include/linux/ipv6.h:1.1.1.1.12.4 --- kernel-acme/include/linux/ipv6.h:1.1.1.1 Tue Jun 26 17:34:02 2001 +++ kernel-acme/include/linux/ipv6.h Fri Dec 21 02:12:13 2001 @@ -101,6 +101,9 @@ }; #ifdef __KERNEL__ +#include /* struct sockaddr_in6 */ +#include +#include /* struct ipv6_mc_socklist */ /* This structure contains results of exthdrs parsing @@ -118,6 +121,62 @@ __u16 dst1; }; +struct ipv6_pinfo { + struct in6_addr saddr; + struct in6_addr rcv_saddr; + struct in6_addr daddr; + struct in6_addr *daddr_cache; + + __u32 flow_label; + __u32 frag_size; + int hop_limit; + int mcast_hops; + int mcast_oif; + + /* pktoption flags */ + union { + struct { + __u8 srcrt:2, + rxinfo:1, + rxhlim:1, + hopopts:1, + dstopts:1, + authhdr:1, + rxflow:1; + } bits; + __u8 all; + } rxopt; + + /* sockopt flags */ + __u8 mc_loop:1, + recverr:1, + sndflow:1, + pmtudisc:2; + + struct ipv6_mc_socklist *ipv6_mc_list; + struct ipv6_fl_socklist *ipv6_fl_list; + __u32 dst_cookie; + + struct ipv6_txoptions *opt; + struct sk_buff *pktoptions; +}; + +struct raw6_opt { + __u32 checksum; /* perform checksum */ + __u32 offset; /* checksum offset */ + + struct icmp6_filter filter; +}; + +/* in the old days both were in sk->tp_pinfo */ +#define IP6_PINFO(__sk) ((struct ipv6_pinfo *) \ + (((char *)((((struct sock *)(__sk)) + 1))) + \ + sizeof(struct inet_opt))) +#define RAW6_PINFO(__sk) ((struct raw6_opt *) \ + (((char *)((((struct sock *)(__sk)) + 1))) + \ + sizeof(struct inet_opt))) +#define IP6_SK_SIZE (sizeof(struct sock) + sizeof(struct inet_opt) + \ + sizeof(struct tcp_opt) + sizeof(struct ipv6_pinfo)) #endif #endif Index: kernel-acme/include/linux/llc.h diff -u /dev/null kernel-acme/include/linux/llc.h:1.1.8.3 --- /dev/null Sat Dec 22 02:21:01 2001 +++ kernel-acme/include/linux/llc.h Mon Dec 17 15:04:51 2001 @@ -0,0 +1,102 @@ +#ifndef __LINUX_LLC_H +#define __LINUX_LLC_H +/* + * IEEE 802.2 User Interface SAPs for Linux, data structures and indicators. + * + * Copyright (c) 2001 by Jay Schulist + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#define __LLC_SOCK_SIZE__ 28 /* sizeof(sockaddr_llc), word align. */ +struct sockaddr_llc { + sa_family_t sllc_family; /* AF_LLC */ + sa_family_t sllc_arphrd; /* ARPHRD_ETHER */ + unsigned char sllc_test; + unsigned char sllc_xid; + unsigned char sllc_ua; /* UA data, only for SOCK_STREAM. */ + unsigned char sllc_dsap; + unsigned char sllc_ssap; + unsigned char sllc_dmac[IFHWADDRLEN]; + unsigned char sllc_smac[IFHWADDRLEN]; + unsigned char sllc_mmac[IFHWADDRLEN]; + unsigned char __pad[__LLC_SOCK_SIZE__ - sizeof(sa_family_t) * 2 - + sizeof(unsigned char) * 5 - IFHWADDRLEN * 3]; +}; + +/* sockopt definitions. */ +enum llc_sockopts { + LLC_OPT_UNKNOWN = 0, + LLC_OPT_RETRY, /* max retrans attempts. */ + LLC_OPT_SIZE, /* max PDU size (octets). */ + LLC_OPT_ACK_TMR_EXP, /* ack expire time (secs). */ + LLC_OPT_P_TMR_EXP, /* pf cycle expire time (secs). */ + LLC_OPT_REJ_TMR_EXP, /* rej sent expire time (secs). */ + LLC_OPT_BUSY_TMR_EXP, /* busy state expire time (secs). */ + LLC_OPT_TX_WIN, /* tx window size. */ + LLC_OPT_RX_WIN, /* rx window size. */ + LLC_OPT_MAX +}; + +#define LLC_OPT_MAX_RETRY 100 +#define LLC_OPT_MAX_SIZE 4196 +#define LLC_OPT_MAX_WIN 127 +#define LLC_OPT_MAX_ACK_TMR_EXP 60 +#define LLC_OPT_MAX_P_TMR_EXP 60 +#define LLC_OPT_MAX_REJ_TMR_EXP 60 +#define LLC_OPT_MAX_BUSY_TMR_EXP 60 + +/* LLC SAP types. */ +#define LLC_SAP_NULL 0x00 /* NULL SAP. */ +#define LLC_SAP_LLC 0x02 /* LLC Sublayer Managment. */ +#define LLC_SAP_SNA 0x04 /* SNA Path Control. */ +#define LLC_SAP_PNM 0x0E /* Proway Network Managment. */ +#define LLC_SAP_IP 0x06 /* TCP/IP. */ +#define LLC_SAP_BSPAN 0x42 /* Bridge Spanning Tree Proto */ +#define LLC_SAP_MMS 0x4E /* Manufacturing Message Srv. */ +#define LLC_SAP_8208 0x7E /* ISO 8208 */ +#define LLC_SAP_3COM 0x80 /* 3COM. */ +#define LLC_SAP_PRO 0x8E /* Proway Active Station List */ +#define LLC_SAP_SNAP 0xAA /* SNAP. */ +#define LLC_SAP_BANYAN 0xBC /* Banyan. */ +#define LLC_SAP_IPX 0xE0 /* IPX/SPX. */ +#define LLC_SAP_NETBEUI 0xF0 /* NetBEUI. */ +#define LLC_SAP_LANMGR 0xF4 /* LanManager. */ +#define LLC_SAP_IMPL 0xF8 /* IMPL */ +#define LLC_SAP_DISC 0xFC /* Discovery */ +#define LLC_SAP_OSI 0xFE /* OSI Network Layers. */ +#define LLC_SAP_LAR 0xDC /* LAN Address Resolution */ +#define LLC_SAP_RM 0xD4 /* Resource Management */ +#define LLC_SAP_GLOBAL 0xFF /* Global SAP. */ + +#ifdef __KERNEL__ +#define LLC_SAP_DYN_START 0xC0 +#define LLC_SAP_DYN_STOP 0xDE +#define LLC_SAP_DYN_TRIES 4 + +struct sock; + +struct llc_ui_opt { + u16 link; /* network layer link number */ + struct llc_sap *sap; /* pointer to parent SAP */ + struct sock *core_sk; + struct net_device *dev; /* device to send to remote */ + struct sockaddr_llc addr; /* address sock is bound to */ +}; + +#define LLC_UI_SK(__sk) ((struct llc_ui_opt *)(__sk)->protinfo) +#define LLC_UI_SKB_CB(__skb) ((struct sockaddr_llc *)&((__skb)->cb[0])) + +#ifdef CONFIG_LLC_UI +extern int llc_ui_init(void); +extern void llc_ui_exit(void); +#else +#define llc_ui_init() +#define llc_ui_exit() +#endif +#endif /* __KERNEL__ */ +#endif /* __LINUX_LLC_H */ Index: kernel-acme/include/linux/netbeui.h diff -u kernel-acme/include/linux/netbeui.h:1.1.1.1 kernel-acme/include/linux/netbeui.h:1.1.1.1.12.3 --- kernel-acme/include/linux/netbeui.h:1.1.1.1 Tue Jun 26 17:34:01 2001 +++ kernel-acme/include/linux/netbeui.h Mon Dec 17 15:04:51 2001 @@ -1,16 +1,585 @@ #ifndef _LINUX_NETBEUI_H #define _LINUX_NETBEUI_H +/* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +/* NetBIOS frame commands - listed by functionality */ +#define NETBEUI_ADD_GROUP_NAME_QUERY 0x00 +#define NETBEUI_ADD_NAME_QUERY 0x01 +#define NETBEUI_ADD_NAME_RESPONSE 0x0D +#define NETBEUI_NAME_IN_CONFLICT 0x02 -#include +#define NETBEUI_NAME_QUERY 0x0A +#define NETBEUI_NAME_RECOGNIZED 0x0E +#define NETBEUI_SESSION_ALIVE 0x1F +#define NETBEUI_SESSION_CONFIRM 0x17 +#define NETBEUI_SESSION_END 0x18 +#define NETBEUI_SESSION_INITIALIZE 0x19 -#define NB_NAME_LEN 20 /* Set this properly from the full docs when - I get them */ - -struct sockaddr_netbeui -{ - sa_family snb_family; - char snb_name[NB_NAME_LEN]; - char snb_devhint[IFNAMSIZ]; +#define NETBEUI_DATA_ACK 0x14 +#define NETBEUI_DATA_FIRST_MIDDLE 0x15 +#define NETBEUI_DATAGRAM 0x08 +#define NETBEUI_DATAGRAM_BROADCAST 0x09 +#define NETBEUI_DATA_ONLY_LAST 0x16 +#define NETBEUI_NO_RECEIVE 0x1A +#define NETBEUI_RECEIVE_CONTINUE 0x1C +#define NETBEUI_RECEIVE_OUTSTANDING 0x1B + +#define NETBEUI_STATUS_QUERY 0x03 +#define NETBEUI_STATUS_RESPONSE 0x0F +#define NETBEUI_TERMINATE_TRACE 0x07 +#define NETBEUI_TERMINATE_TRACE2 0x13 + +#define NETBEUI_MAX_COMMAND_CODE 0x1F +#define NETBEUI_MIN_COMMAND_LEN 0x0B + +extern u8 nb_cmd_hdr_len[]; + +/* NetBIOS name service constants */ +typedef enum { + NETBEUI_NAME_INITIAL = 0, + NETBEUI_NAME_ADDWAIT, + NETBEUI_NAME_COLLIDED, + NETBEUI_NAME_ACQUIRED +} name_state_t; + +typedef enum { + NETBEUI_NAME_ADD_NAME = 0, + NETBEUI_NAME_RETRY_TIMEOUT, + NETBEUI_NAME_RESPONSE_TIMEOUT, + NETBEUI_NAME_ADD_NAME_RESPONSE1, + NETBEUI_NAME_ADD_NAME_RESPONSE2, + NETBEUI_NAME_ADD_NAME_QUERY, + NETBEUI_NAME_NAME_CONFLICT, + NETBEUI_NAME_REMOVE_NAME +} name_event_t; + +/* NetBIOS query service constants */ +#define NETBEUI_QUERY_MAX_CACHE_ENTRIES 50 +#define NETBEUI_QUERY_CACHE_LIVING_TIME (5 * 60 * HZ) + +typedef enum { + NETBEUI_QUERY_INITIAL = 0, + NETBEUI_QUERY_QRYWAIT, + NETBEUI_QUERY_FINDWAIT, + NETBEUI_QUERY_RECOGNIZED +} query_state_t; + +typedef enum { + NETBEUI_QUERY_NAME_QUERY = 0, + NETBEUI_QUERY_NAME_FIND, + NETBEUI_QUERY_RETRY_TIMEOUT, + NETBEUI_QUERY_RESPONSE_TIMEOUT, + NETBEUI_QUERY_NAME_RECOGNIZED, + NETBEUI_QUERY_END_QUERY +} query_event_t; + +#define NETBEUI_CALL_TT(data2) ((data2 & 0xFF00) >> 8) +#define NETBEUI_CALL_SS(data2) (data2 & 0x00FF) +#define NETBEUI_CALL_DATA2(tt,ss) (((tt << 8) & 0xFF00) | (ss & 0x00FF)) + +/* NetBIOS session service constants */ +typedef enum { + NETBEUI_SESS_INITIAL = 0, + NETBEUI_SESS_CALLWAIT, + NETBEUI_SESS_CONFWAIT, + NETBEUI_SESS_LISTENWAIT, + NETBEUI_SESS_INITWAIT, + NETBEUI_SESS_CONNECTED, + NETBEUI_SESS_DISCWAIT, + NETBEUI_SESS_CONTWAIT, + NETBEUI_SESS_STANDWAIT, + NETBEUI_SESS_ACKWAIT, + NETBEUI_SESS_RSRCWAIT, + NETBEUI_SESS_NORMAL +} session_state_t; + +typedef enum { + NETBEUI_SESS_CALL = 0, + NETBEUI_SESS_LISTEN, + NETBEUI_SESS_CONFIRM, + NETBEUI_SESS_REJ, + NETBEUI_SESS_CONNECT, + NETBEUI_SESS_TIMEOUT, + NETBEUI_SESS_ABORT, + NETBEUI_SESS_HANGUP, + NETBEUI_SESS_END, + NETBEUI_SESS_FIRST_MIDDLE_CONT, + NETBEUI_SESS_FIRST_MIDDLE, + NETBEUI_SESS_CONTINUE, + NETBEUI_SESS_NONBLOCK, + NETBEUI_SESS_PAUSE, + NETBEUI_SESS_PAUSE2, + NETBEUI_SESS_RESTART, + NETBEUI_SESS_ONLY_LAST_ACK, + NETBEUI_SESS_ONLY_LAST, + NETBEUI_SESS_DATA_ACKED, + NETBEUI_SESS_RESOURCE, + NETBEUI_SESS_CONN_RETRY, + NETBEUI_SESS_NORM_RETRY, + NETBEUI_SESS_ABORT_SEND, +} session_event_t; + +typedef enum { + NETBEUI_RECV_NORMAL= 0, + NETBEUI_RECV_NO_RECEIVE, + NETBEUI_RECV_RECEIVE_OUTSTANDING +} input_state_t; + +#define NETBEUI_VERSION_1xx 0 +#define NETBEUI_VERSION_2xx 1 + +#define NETBEUI_NACK_NONE 0 +#define NETBEUI_NACK_ABLE 1 + +#define NETBEUI_ORIGIN_CONNECTED 1 +#define NETBEUI_ORIGIN_NORMAL 2 + +#define NETBEUI_IS_ABLE_TO_HANDLE_NACK(hdr) (hdr->data1 & 0x80) +#define NETBIOS_VERSION(hdr) (hdr->data1 & 0x01) +#define NETBEUI_TR_FRAME_LF(hdr) (((hdr->data1) & 0x0E) >> 1) + +#define NETBEUI_RECEIVE_CONTINUE_REQUESTED(hdr) (hdr->data1 & 0x01) +#define NETBEUI_NACK_INDICATOR(hdr) (hdr->data1 & 0x02) +#define NETBEUI_ACK_WITH_DATA_ALLOWED(hdr) (hdr->data1 & 0x04) +#define NETBEUI_ACK_WITH_DATA_INCLUDED(hdr) (hdr->data1 & 0x08) + +#define NETBEUI_REQUEST_RECEIVE_CONTINUE(hdr) (hdr->data1 |= 0x01) +#define NETBEUI_INDICATE_NACK(hdr) (hdr->data1 |= 0x02) +#define NETBEUI_ALLOW_ACK_WITH_DATA(hdr) (hdr->data1 |= 0x04) +#define NETBEUI_INCLUDE_ACK_WITH_DATA(hdr) (hdr->data1 |= 0x08) + +#define NETBEUI_RESYNCH_INDICATOR(hdr) (hdr->data2) + +#define NETBEUI_ACK_FLAG 0x80000000 + +/* NetBIOS link manager constants */ +typedef enum { + NETBEUI_LINK_INITIAL = 0, + NETBEUI_LINK_CONNWAIT, + NETBEUI_LINK_UP +} link_state_t; + +typedef enum { + NETBEUI_LINK_CONN_INDICATE = 0, + NETBEUI_LINK_CONN_REQUEST, + NETBEUI_LINK_DUMMY_CONN, + NETBEUI_LINK_CONN_CONFIRM, + NETBEUI_LINK_CONN_REJ, + NETBEUI_LINK_RESET_INDICATE, + NETBEUI_LINK_SESSION_ALIVE, + NETBEUI_LINK_DISC_REQUEST, + NETBEUI_LINK_DISC_INDICATE +} link_event_t; + +/* NetBIOS constants */ +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) + +#define NB_SK(__sk) ((struct netbeui_opt *)(__sk)->protinfo) + +#define NETBIOS_FUNC_ADDR_4ETH "\x03\x00\x00\x00\x00\x01" +#define NETBIOS_FUNC_ADDR_4TR "\xC0\x00\x00\x00\x00\x80" + +#define NETBEUI_DELIMITER 0xEFFF + +#define NETBEUI_LLC_I_HEADLEN 4 /* 4 bytes for LLC header of I_frames */ +#define NETBEUI_ILEN 0x0E /* NetBEUI I_frame header length */ + +#define NETBEUI_LLC_UI_HEADLEN 3 /* 3 bytes for LLC header of UI_frames */ +#define NETBEUI_UILEN 0x2C /* NetBEUI UI_frame header length */ + +#define NETBEUI_MAC_B_HEADLEN MAX(sizeof(struct ethhdr), sizeof(struct trh_hdr)) + +/* NetBIOS status service constants */ +typedef enum { + NBS_STAT_INITIAL = 0, + NBS_STAT_RESPWAIT +} status_state_t; + +typedef enum { + NBE_STAT_STATUS_QUERY = 0, + NBE_STAT_RETRY_TIMEOUT, + NBE_STAT_RESPONSE_TIMEOUT, + NBE_STAT_STATUS_RESPONSE, + NBE_STAT_INCOMP_RESPONSE +} status_event_t; + +typedef enum { + NO_RESPONSE = 0, + INCOMPLETE_RESPONSE, + USER_BUFFER_OVERFLOW, + COMPLETED_RESPONSE +} status_rc_t; + +struct nb_adapters { + struct net_device *dev[NETBEUI_MAX_ADAPTERS]; + int count; + int autobind; + rwlock_t lock; +}; + +/* NetBIOS name data structure */ +struct nb_name { + struct nb_name * next; + atomic_t refcnt; + name_state_t volatile state; + s32 volatile status; + __u8 name[NETBEUI_NAME_LEN]; + __u8 reserved; + __u8 conflicted; + name_type_t type; + __u8 name_number; + __u32 identifier; + wait_queue_head_t waitq; + struct timer_list timer; + struct sk_buff * skb; + __u16 resp_correlator; + __u16 xmit_correlator; + __u8 retries; + __u8 responses; + __u8 remote_mac[6]; + struct net_device *dev; +}; +typedef struct nb_name name_t; + +/* NetBIOS Query Data Structure */ +struct nb_query { + struct nb_query *next; + query_state_t volatile state; + s32 volatile status; + name_t * calling_name; + __u8 called_name[NETBEUI_NAME_LEN]; + __u8 reserved; + __u8 lsn; + __u16 resp_correlator; + char *mac_buff; + struct net_device **dev_buff; + __u8 buff_len; + __u8 buff_ofs; + __u8 rsn; + __u8 remote_mac[6]; + struct net_device *dev; + __u16 xmit_correlator; + __u8 tr_lfb; /* for Token-Ring support */ + struct timer_list timer; + struct sk_buff *skb; + __u8 retries; + __u8 responses; + wait_queue_head_t waitq; +}; +typedef struct nb_query query_t; + +struct nb_session; +typedef struct nb_session session_t; + +typedef void (*abort_owner_cbt)(struct sock *sk, session_t *session); +typedef void (*session_ready_cbt)(struct sock *sk, session_t *session); + +/* NetBIOS Session Data Structure */ +struct nb_session { + struct nb_session * next; + struct nb_session * prev; + session_state_t volatile state; + s32 volatile status; + atomic_t refcnt; + int link; + struct sock * owner; + name_t * local_name; + name_type_t remote_name_type; + __u8 remote_name[NETBEUI_NAME_LEN]; + __u8 reserved; + __u8 lsn; + __u8 rsn; + __u8 version; + __u8 nack_indicator; + __u8 tr_frame_lf; + __u16 mtu; + __u16 llcmac_ihl; + __u8 urgent_ack; + __u8 users; + __u8 zapped; + struct sk_buff_head back_log; + abort_owner_cbt abort_owner_callback; + session_ready_cbt session_ready_callback; + wait_queue_head_t waitq; + struct timer_list timer; + struct sk_buff * skb; + struct net_device * dev; + __u8 remote_mac[6]; + __u16 xmit_correlator; + __u16 resp_correlator; + __u8 o_nonblock; + __u8 o_noack; + __u8 o_aborted; + __u8 o_no_receive; + __u8 o_receive_continue; + __u8 o_receive_outstanding; + __u8 o_rsrc_origin; + __u8 * o_buff; + __u16 o_buffsize; + __u16 o_size; + __u16 o_txed; + __u16 o_acked; + __u16 r_acked; + __u32 o_total; + __u32 o_ack_correlator; + __u16 i_rcvbuf; + __u16 i_aborted; + input_state_t i_state; + struct sk_buff_head i_skbq; + __u16 i_notacked; + __u16 i_size; + __u32 i_total; +}; + +/* NetBIOS-LLC link data structure */ +struct nb_link { + link_state_t volatile state; + s32 volatile status; + void *llc_handle; + __u32 link; + atomic_t refcnt; + __u8 remote_mac[6]; + struct net_device *dev; + struct sk_buff_head skbq; + __u8 llc_busy; + __u32 iactivity; + __u8 keep_alive; + struct timer_list timer; + dextab_t session_table; + wait_queue_head_t waitq; +}; +typedef struct nb_link link_t; + +/* NetBIOS dataGram data structure */ +struct name_dgrms { + char name[NETBEUI_NAME_LEN]; + struct sk_buff_head frameq; + struct sk_buff *curr_skb; + volatile unsigned char connected; + char *conn_name; + wait_queue_head_t *waitq; + struct name_dgrms **list; + struct name_dgrms *next; + struct name_dgrms *prev; +}; +typedef struct name_dgrms name_dgrms_t; + +/* NetBIOS socket supplement structures, present in struct sock's tp_pinfo */ +struct netbeui_opt { + name_t *name; + union { + struct { + session_t *session; + session_t *backlog; + volatile struct timeval sto; + volatile struct timeval rto; + } st; + struct { + struct sockaddr_netbeui conn_name; + name_dgrms_t *namep; + } dg; + } u; +}; + +/* NetBIOS status data structure */ +struct nb_status { + struct nb_status *next; + __u8 *called_name; + char *user_sbuff; + int sbuff_len; + status_rc_t resp_status; + volatile status_state_t state; + __u8 retries; + int len_rx_info; + __u8 no_rx_names; + __u8 overflowed; + __u16 resp_correlator; + __u8 unicast; + __u8 remote_mac[ETH_ALEN]; + struct sk_buff *tx_skb; + struct sk_buff *rx_skb; + volatile unsigned char locked; + struct timer_list timer; + wait_queue_head_t waitq; +}; +typedef struct nb_status status_t; + +/* NetBIOS datagram packet header */ +struct nb_dgram { + __u16 length; + __u16 delimiter; + __u8 command; + __u8 data1; + __u16 data2; + __u16 xmit_correlator; + __u16 resp_correlator; + __u8 dest_name[NETBEUI_NAME_LEN]; + __u8 source_name[NETBEUI_NAME_LEN]; +}; +typedef struct nb_dgram dgram_t; + +/* NetBIOS session packet header */ +struct nb_packet { + __u16 length; + __u16 delimiter; + __u8 command; + __u8 data1; + __u16 data2; + __u16 xmit_correlator; + __u16 resp_correlator; + __u8 dest_num; + __u8 source_num; }; +typedef struct nb_packet packet_t; + +/* NetBIOS Configuration Definitions */ +typedef struct netbeui_config config_t; + +extern config_t netbios_config; +extern struct nb_adapters netbeui_adapters; + +#define NETBEUI_INACTIVITY_TIMEOUT (netbios_config.inactivity_timeout * HZ) +#define NETBEUI_TRANSMIT_TIMEOUT (netbios_config.transmit_timeout * (HZ / 2)) +#define NETBEUI_TRANSMIT_COUNT (netbios_config.transmit_count) +#define NETBEUI_RESOURCE_TIMEOUT (netbios_config.resource_timeout * (HZ / 10)) +#define NETBEUI_DATA_ACK_TIMEOUT (netbios_config.data_ack_timeout * (HZ / 10)) + +/* Common functions interface */ +extern inline char *netbeui_funcaddr(struct net_device *dev); +extern unsigned char nbcm_apt_dev(struct net_device *dev); +extern inline int MAC_HEADLEN(struct net_device *dev); +extern inline int LLCMAC_I_HEADLEN(struct net_device *dev); +extern inline int LLCMAC_UI_HEADLEN(int mac_hlen); +extern inline int LLCMAC_UIB_HEADLEN(void); +extern inline int CALC_DG_SKBLEN(int mac_hlen, int user_datalen); + +/* LLC supplement interface */ +extern int nbll_attach_session(session_t *session, struct net_device *dev, + unsigned char *remote_mac); +extern int nbll_link_session(int link); +extern int nbll_isend(int link, struct sk_buff *skb); +extern int nbll_uisend(unsigned char *remote_maccaddr, struct sk_buff *skb); +extern void nbll_detach_session(int link, unsigned char session_no); +extern int nbll_drop_link(int link); +extern dextab_t *nbll_get_link_table(void); +extern link_t *nbll_get_link(int link); +extern inline void nbll_link_put(link_t *nb_link); +extern void nbll_test(void); + +/* Name service interface */ +extern unsigned char *netbeui_dev_name_number_1(struct net_device *dev); +extern int nbns_validate_name(char *name); +extern void nbns_init_name_number_1(struct net_device *adapters[]); +extern name_t *nbns_name_number_1(void); +extern int nbns_add_name(char *name, name_type_t type, name_t **out_name); +extern name_t *nbns_find_name(char *name); +extern inline void nbns_name_hold(name_t *nb_name); +extern inline void nbns_name_put(name_t *nb_name); +extern void nbns_del_name(name_t *name); +extern void nbns_del_identifier(unsigned long id); +extern void nbns_get_add_name_query(struct sk_buff *skb, + unsigned char *remote_mac, int type); +extern void nbns_get_add_name_response(struct sk_buff *skb, + unsigned char *remote_mac); +extern void nbns_get_name_conflict(struct sk_buff *skb); +extern dextab_t *nbns_get_name_table(void); +extern name_t *nbns_get_name_list(void); +extern int nbns_count_names(void); +extern void nbns_test(void); + +/* Query service interface */ +extern void nbqs_get_name_recognized(struct sk_buff *skb, + unsigned char *remote_mac); +extern int nbqs_query_name(char *called_name, name_t *calling_name, + unsigned char lsn, unsigned char *rsn, + unsigned char *lfb, unsigned short *xmit_correlator); +extern int nbqs_find_name(char *called_name, char *mac_buff, + struct net_device **dev_buff, int buff_len); +extern void nbqs_add_rnc(char *name, struct net_device *dev, + unsigned char *mac); +extern void nbqs_delete_rnc(char *name); +extern void nbqs_test(void); + +/* Session service interface */ +extern void nbss_get_name_query(struct sk_buff *skb, unsigned char *remote_mac); +extern void nbss_deliver_frame(session_t *session, struct sk_buff *skb); +extern int nbss_call(name_t *calling_name, char *called_name, + struct sock *owner, abort_owner_cbt itf_abort_owner, + session_t **session_ptr); +extern int nbss_listen(name_t *name, int backlog, struct sock *owner, + abort_owner_cbt itf_abort_owner, + session_ready_cbt itf_session_ready); +extern int nbss_listen_bh(name_t *nb_name, int backlog, struct sock *owner, + abort_owner_cbt itf_abort_owner, + session_ready_cbt itf_session_ready); +extern void __nbss_end_listen(name_t *name); +extern int nbss_send(session_t *session, unsigned char *buf, + unsigned short size, unsigned char nonblock, + unsigned char noack); +extern int nbss_send_zero(session_t *session, char *buff); +extern void nbss_abort_send(session_t *session); +extern int nbss_send_ready(session_t *session); +extern int nbss_receive(session_t *session, unsigned char *buf, + unsigned short size, unsigned char nonblock); +extern void nbss_abort_receive(session_t *session); +extern int nbss_receive_ready(session_t *session); +extern int nbss_trim_data(session_t *session); +extern void nbss_hangup(session_t *session); +extern void nbss_abort_session(session_t *session); +extern int nbss_drop_session(int link, int session_no); +extern dextab_t *nbss_get_session_table(int link); +extern void nbss_test(char *service_name); + +/* DataGram service interface */ +extern void nbdg_set_dgbc_mtu(void); +extern int nbdg_remove_unwanted_dgf(name_dgrms_t *namep, int len); +extern void nbdg_register_peername(name_dgrms_t *namep, char *remote_name); +extern void nbdg_deregister_peername(name_dgrms_t *namep); +extern int nbdg_add_name(char *local_name, wait_queue_head_t *wq, + name_dgrms_t **namep); +extern void nbdg_del_name(name_dgrms_t *namep); +extern int nbdg_receive_ready(name_dgrms_t *namep); +extern int nbdg_send(struct sock *sk, char *local_name, char *dest_name, + name_type_t dest_type, struct iovec *iov, int len, + int noblock); +extern int nbdg_receive(name_dgrms_t *namep, char *source_name, char *dest_name, + char *buff, int bufflen, int nonblock); +extern void nbdg_get_datagram(struct sk_buff *skb); +extern void nbdg_get_datagram_broadcast(struct sk_buff *skb); + +/* Socket Supplement Interface */ +extern int nbso_init(void); +extern int nbso_exit(void); + +/* Status service interface */ +void nbst_init_status(void); +int nbst_obtain_status(char *called_name, char *status_buff, int *buff_len); +void nbst_get_status_query(struct sk_buff *skb, unsigned char *remote_mac); +void nbst_get_status_response(struct sk_buff *skb, unsigned char *remote_mac); + +/* PROC entry interface */ +extern int netbeui_proc_init(void); +extern void netbeui_proc_clean(void); -#endif +/* Configuration system interface */ +extern int nbcs_setsockopt(struct socket *sock, int optname, void *optval, + int optlen); +extern int nbcs_getsockopt(struct socket *sock, int optname, void *optval, + int *optlen); +extern int nbcs_ioctl(unsigned int cmd, void *arg); +#endif /* _LINUX_NETBEUI_H */ Index: kernel-acme/include/linux/socket.h diff -u kernel-acme/include/linux/socket.h:1.1.1.2 kernel-acme/include/linux/socket.h:1.1.1.2.10.1 --- kernel-acme/include/linux/socket.h:1.1.1.2 Thu Aug 16 18:49:55 2001 +++ kernel-acme/include/linux/socket.h Thu Nov 29 20:36:54 2001 @@ -156,6 +156,7 @@ #define AF_IRDA 23 /* IRDA sockets */ #define AF_PPPOX 24 /* PPPoX sockets */ #define AF_WANPIPE 25 /* Wanpipe API Sockets */ +#define AF_LLC 26 /* Linux LLC */ #define AF_BLUETOOTH 31 /* Bluetooth sockets */ #define AF_MAX 32 /* For now.. */ @@ -187,6 +188,7 @@ #define PF_IRDA AF_IRDA #define PF_PPPOX AF_PPPOX #define PF_WANPIPE AF_WANPIPE +#define PF_LLC AF_LLC #define PF_BLUETOOTH AF_BLUETOOTH #define PF_MAX AF_MAX @@ -237,6 +239,8 @@ #define SOL_ATM 264 /* ATM layer (cell level) */ #define SOL_AAL 265 /* ATM Adaption Layer (packet level) */ #define SOL_IRDA 266 +#define SOL_NETBEUI 267 +#define SOL_LLC 268 /* IPX options */ #define IPX_TYPE 1 Index: kernel-acme/include/linux/tcp.h diff -u kernel-acme/include/linux/tcp.h:1.1.1.2 kernel-acme/include/linux/tcp.h:1.1.1.2.6.3 --- kernel-acme/include/linux/tcp.h:1.1.1.2 Tue Nov 6 21:35:11 2001 +++ kernel-acme/include/linux/tcp.h Fri Dec 21 02:12:13 2001 @@ -17,7 +17,7 @@ #ifndef _LINUX_TCP_H #define _LINUX_TCP_H -#include +#include #include struct tcphdr { @@ -185,4 +185,190 @@ __u32 tcpi_reordering; }; +/* This defines a selective acknowledgement block. */ +struct tcp_sack_block { + __u32 start_seq; + __u32 end_seq; +}; + +struct tcp_opt { + int tcp_header_len; /* Bytes of tcp header to send */ + +/* + * Header prediction flags + * 0x5?10 << 16 + snd_wnd in net byte order + */ + __u32 pred_flags; + +/* + * RFC793 variables by their proper names. This means you can + * read the code and the spec side by side (and laugh ...) + * See RFC793 and RFC1122. The RFC writes these in capitals. + */ + __u32 rcv_nxt; /* What we want to receive next */ + __u32 snd_nxt; /* Next sequence we send */ + + __u32 snd_una; /* First byte we want an ack for */ + __u32 snd_sml; /* Last byte of the most recently transmitted small packet */ + __u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */ + __u32 lsndtime; /* timestamp of last sent data packet (for restart window) */ + + /* Delayed ACK control data */ + struct { + __u8 pending; /* ACK is pending */ + __u8 quick; /* Scheduled number of quick acks */ + __u8 pingpong; /* The session is interactive */ + __u8 blocked; /* Delayed ACK was blocked by socket lock*/ + __u32 ato; /* Predicted tick of soft clock */ + unsigned long timeout; /* Currently scheduled timeout */ + __u32 lrcvtime; /* timestamp of last received data packet*/ + __u16 last_seg_size; /* Size of last incoming segment */ + __u16 rcv_mss; /* MSS used for delayed ACK decisions */ + } ack; + + /* Data for direct copy to user */ + struct { + struct sk_buff_head prequeue; + int memory; + struct task_struct *task; + struct iovec *iov; + int len; + } ucopy; + + __u32 snd_wl1; /* Sequence for window update */ + __u32 snd_wnd; /* The window we expect to receive */ + __u32 max_window; /* Maximal window ever seen from peer */ + __u32 pmtu_cookie; /* Last pmtu seen by socket */ + __u16 mss_cache; /* Cached effective mss, not including SACKS */ + __u16 mss_clamp; /* Maximal mss, negotiated at connection setup */ + __u16 ext_header_len; /* Network protocol overhead (IP/IPv6 options) */ + __u8 ca_state; /* State of fast-retransmit machine */ + __u8 retransmits; /* Number of unrecovered RTO timeouts. */ + + __u8 reordering; /* Packet reordering metric. */ + __u8 queue_shrunk; /* Write queue has been shrunk recently.*/ + __u8 defer_accept; /* User waits for some data after accept() */ + +/* RTT measurement */ + __u8 backoff; /* backoff */ + __u32 srtt; /* smothed round trip time << 3 */ + __u32 mdev; /* medium deviation */ + __u32 mdev_max; /* maximal mdev for the last rtt period */ + __u32 rttvar; /* smoothed mdev_max */ + __u32 rtt_seq; /* sequence number to update rttvar */ + __u32 rto; /* retransmit timeout */ + + __u32 packets_out; /* Packets which are "in flight" */ + __u32 left_out; /* Packets which leaved network */ + __u32 retrans_out; /* Retransmitted packets out */ + + +/* + * Slow start and congestion control (see also Nagle, and Karn & Partridge) + */ + __u32 snd_ssthresh; /* Slow start size threshold */ + __u32 snd_cwnd; /* Sending congestion window */ + __u16 snd_cwnd_cnt; /* Linear increase counter */ + __u16 snd_cwnd_clamp; /* Do not allow snd_cwnd to grow above this */ + __u32 snd_cwnd_used; + __u32 snd_cwnd_stamp; + + /* Two commonly used timers in both sender and receiver paths. */ + unsigned long timeout; + struct timer_list retransmit_timer; /* Resend (no ack) */ + struct timer_list delack_timer; /* Ack delay */ + + struct sk_buff_head out_of_order_queue; /* Out of order segments go here */ + + struct tcp_func *af_specific; /* Operations which are AF_INET{4,6} specific */ + struct sk_buff *send_head; /* Front of stuff to transmit */ + struct page *sndmsg_page; /* Cached page for sendmsg */ + u32 sndmsg_off; /* Cached offset for sendmsg */ + + __u32 rcv_wnd; /* Current receiver window */ + __u32 rcv_wup; /* rcv_nxt on last window update sent */ + __u32 write_seq; /* Tail(+1) of data held in tcp send buffer */ + __u32 pushed_seq; /* Last pushed seq, required to talk to windows */ + __u32 copied_seq; /* Head of yet unread data */ +/* + * Options received (usually on last packet, some only on SYN packets). + */ + char tstamp_ok, /* TIMESTAMP seen on SYN packet */ + wscale_ok, /* Wscale seen on SYN packet */ + sack_ok; /* SACK seen on SYN packet */ + char saw_tstamp; /* Saw TIMESTAMP on last packet */ + __u8 snd_wscale; /* Window scaling received from sender */ + __u8 rcv_wscale; /* Window scaling to send to receiver */ + __u8 nonagle; /* Disable Nagle algorithm? */ + __u8 keepalive_probes; /* num of allowed keep alive probes */ + +/* PAWS/RTTM data */ + __u32 rcv_tsval; /* Time stamp value */ + __u32 rcv_tsecr; /* Time stamp echo reply */ + __u32 ts_recent; /* Time stamp to echo next */ + long ts_recent_stamp;/* Time we stored ts_recent (for aging) */ + +/* SACKs data */ + __u16 user_mss; /* mss requested by user in ioctl */ + __u8 dsack; /* D-SACK is scheduled */ + __u8 eff_sacks; /* Size of SACK array to send with next packet */ + struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */ + struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/ + + __u32 window_clamp; /* Maximal window to advertise */ + __u32 rcv_ssthresh; /* Current window clamp */ + __u8 probes_out; /* unanswered 0 window probes */ + __u8 num_sacks; /* Number of SACK blocks */ + __u16 advmss; /* Advertised MSS */ + + __u8 syn_retries; /* num of allowed syn retries */ + __u8 ecn_flags; /* ECN status bits. */ + __u16 prior_ssthresh; /* ssthresh saved at recovery start */ + __u32 lost_out; /* Lost packets */ + __u32 sacked_out; /* SACK'd packets */ + __u32 fackets_out; /* FACK'd packets */ + __u32 high_seq; /* snd_nxt at onset of congestion */ + + __u32 retrans_stamp; /* Timestamp of the last retransmit, + * also used in SYN-SENT to remember stamp of + * the first SYN. */ + __u32 undo_marker; /* tracking retrans started here. */ + int undo_retrans; /* number of undoable retransmissions. */ + __u32 urg_seq; /* Seq of received urgent pointer */ + __u16 urg_data; /* Saved octet of OOB data and control flags */ + __u8 pending; /* Scheduled timer event */ + __u8 urg_mode; /* In urgent mode */ + __u32 snd_up; /* Urgent pointer */ + + /* The syn_wait_lock is necessary only to avoid tcp_get_info having + * to grab the main lock sock while browsing the listening hash + * (otherwise it's deadlock prone). + * This lock is acquired in read mode only from tcp_get_info() and + * it's acquired in write mode _only_ from code that is actively + * changing the syn_wait_queue. All readers that are holding + * the master sock lock don't need to grab this lock in read mode + * too as the syn_wait_queue writes are always protected from + * the main sock lock. + */ + rwlock_t syn_wait_lock; + struct tcp_listen_opt *listen_opt; + + /* FIFO of established children */ + struct open_request *accept_queue; + struct open_request *accept_queue_tail; + + int write_pending; /* A write to socket waits to start. */ + + unsigned int keepalive_time; /* time before keep alive takes place */ + unsigned int keepalive_intvl; /* time interval between keep alive probes */ + int linger2; + + unsigned long last_synq_overflow; +}; + +#define TCP_PINFO(__sk) ((struct tcp_opt *) \ + (((char *)((((struct sock *)(__sk)) + 1))) + \ + sizeof(struct inet_opt))) +#define TCP_SK_SIZE (sizeof(struct sock) + sizeof(struct inet_opt) + \ + sizeof(struct tcp_opt)) #endif /* _LINUX_TCP_H */ Index: kernel-acme/include/linux/trdevice.h diff -u kernel-acme/include/linux/trdevice.h:1.1.1.1 kernel-acme/include/linux/trdevice.h:1.1.1.1.12.1 --- kernel-acme/include/linux/trdevice.h:1.1.1.1 Tue Jun 26 17:34:03 2001 +++ kernel-acme/include/linux/trdevice.h Thu Nov 29 20:36:54 2001 @@ -31,6 +31,9 @@ extern int tr_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len); +extern void tr_source_route(struct sk_buff *skb, + struct trh_hdr *trh, + struct net_device *dev); extern int tr_rebuild_header(struct sk_buff *skb); extern unsigned short tr_type_trans(struct sk_buff *skb, struct net_device *dev); extern struct net_device *init_trdev(struct net_device *dev, int sizeof_priv); Index: kernel-acme/include/net/af_unix.h diff -u kernel-acme/include/net/af_unix.h:1.1.1.1 kernel-acme/include/net/af_unix.h:1.1.1.1.12.2 --- kernel-acme/include/net/af_unix.h:1.1.1.1 Tue Jun 26 17:33:58 2001 +++ kernel-acme/include/net/af_unix.h Fri Dec 21 02:12:13 2001 @@ -34,9 +34,27 @@ #define UNIXCB(skb) (*(struct unix_skb_parms*)&((skb)->cb)) #define UNIXCREDS(skb) (&UNIXCB((skb)).creds) -#define unix_state_rlock(s) read_lock(&(s)->protinfo.af_unix.lock) -#define unix_state_runlock(s) read_unlock(&(s)->protinfo.af_unix.lock) -#define unix_state_wlock(s) write_lock(&(s)->protinfo.af_unix.lock) -#define unix_state_wunlock(s) write_unlock(&(s)->protinfo.af_unix.lock) +#define unix_state_rlock(s) read_lock(&UNIX_SK(s)->lock) +#define unix_state_runlock(s) read_unlock(&UNIX_SK(s)->lock) +#define unix_state_wlock(s) write_lock(&UNIX_SK(s)->lock) +#define unix_state_wunlock(s) write_unlock(&UNIX_SK(s)->lock) +#ifdef __KERNEL__ +/* The AF_UNIX specific socket options */ +struct unix_opt { + struct unix_address *addr; + struct dentry *dentry; + struct vfsmount *mnt; + struct semaphore readsem; + struct sock *other; + struct sock **list; + struct sock *gc_tree; + atomic_t inflight; + rwlock_t lock; + wait_queue_head_t peer_wait; +}; + +#define UNIX_SK(__sk) ((struct unix_opt *)(((struct sock *)(__sk)) + 1)) +#define UNIX_SK_SIZE (sizeof(struct sock) + sizeof(struct unix_opt)) +#endif #endif Index: kernel-acme/include/net/ax25.h diff -u kernel-acme/include/net/ax25.h:1.1.1.1 kernel-acme/include/net/ax25.h:1.1.1.1.12.2 --- kernel-acme/include/net/ax25.h:1.1.1.1 Tue Jun 26 17:33:57 2001 +++ kernel-acme/include/net/ax25.h Mon Dec 17 15:04:51 2001 @@ -194,6 +194,8 @@ struct sock *sk; /* Backlink to socket */ } ax25_cb; +#define AX25_SK(__sk) ((ax25_cb *)(__sk)->protinfo) + /* af_ax25.c */ extern ax25_cb *volatile ax25_list; extern void ax25_free_cb(ax25_cb *); Index: kernel-acme/include/net/checksum.h diff -u kernel-acme/include/net/checksum.h:1.1.1.1 kernel-acme/include/net/checksum.h:1.1.1.1.12.1 --- kernel-acme/include/net/checksum.h:1.1.1.1 Tue Jun 26 17:33:58 2001 +++ kernel-acme/include/net/checksum.h Mon Dec 17 03:11:12 2001 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include Index: kernel-acme/include/net/datalink.h diff -u kernel-acme/include/net/datalink.h:1.1.1.1 kernel-acme/include/net/datalink.h:1.1.1.1.12.1 --- kernel-acme/include/net/datalink.h:1.1.1.1 Tue Jun 26 17:33:58 2001 +++ kernel-acme/include/net/datalink.h Thu Nov 29 20:36:54 2001 @@ -2,15 +2,24 @@ #define _NET_INET_DATALINK_H_ struct datalink_proto { - unsigned short type_len; - unsigned char type[8]; - const char *string_name; - unsigned short header_length; - int (*rcvfunc)(struct sk_buff *, struct net_device *, - struct packet_type *); - void (*datalink_header)(struct datalink_proto *, struct sk_buff *, - unsigned char *); - struct datalink_proto *next; + unsigned short type_len; + unsigned char type[8]; + const char *string_name; + + union { + struct llc_pinfo *llc; + } ll_pinfo; + + struct llc_sc_info *llc_sc; + struct sock *sock; + + unsigned short header_length; + + int (*rcvfunc)(struct sk_buff *, struct net_device *, + struct packet_type *); + void (*datalink_header)(struct datalink_proto *, struct sk_buff *, + unsigned char *); + struct datalink_proto *next; }; #endif Index: kernel-acme/include/net/dn.h diff -u kernel-acme/include/net/dn.h:1.1.1.2 kernel-acme/include/net/dn.h:1.1.1.2.4.2 --- kernel-acme/include/net/dn.h:1.1.1.2 Fri Nov 23 22:34:42 2001 +++ kernel-acme/include/net/dn.h Mon Dec 17 15:04:51 2001 @@ -9,8 +9,6 @@ #define dn_ntohs(x) le16_to_cpu((unsigned short)(x)) #define dn_htons(x) cpu_to_le16((unsigned short)(x)) -#define DN_SK(sk) (&sk->protinfo.dn) - struct dn_scp /* Session Control Port */ { unsigned char state; @@ -134,6 +132,8 @@ void (*delack_fxn)(struct sock *sk); }; + +#define DN_SK(__sk) ((struct dn_scp *)(__sk)->protinfo) /* * src,dst : Source and Destination DECnet addresses Index: kernel-acme/include/net/dn_nsp.h diff -u kernel-acme/include/net/dn_nsp.h:1.1.1.1 kernel-acme/include/net/dn_nsp.h:1.1.1.1.12.1 --- kernel-acme/include/net/dn_nsp.h:1.1.1.1 Tue Jun 26 17:33:58 2001 +++ kernel-acme/include/net/dn_nsp.h Mon Dec 17 15:04:51 2001 @@ -150,7 +150,7 @@ * numbers used in NSP. Similar in operation to the functions * of the same name in TCP. */ -static __inline__ int before(unsigned short seq1, unsigned short seq2) +static __inline__ int dn_before(unsigned short seq1, unsigned short seq2) { seq1 &= 0x0fff; seq2 &= 0x0fff; @@ -159,7 +159,7 @@ } -static __inline__ int after(unsigned short seq1, unsigned short seq2) +static __inline__ int dn_after(unsigned short seq1, unsigned short seq2) { seq1 &= 0x0fff; seq2 &= 0x0fff; @@ -167,14 +167,14 @@ return (int)((seq2 - seq1) & 0x0fff) > 2048; } -static __inline__ int equal(unsigned short seq1, unsigned short seq2) +static __inline__ int dn_equal(unsigned short seq1, unsigned short seq2) { return ((seq1 ^ seq2) & 0x0fff) == 0; } -static __inline__ int before_or_equal(unsigned short seq1, unsigned short seq2) +static __inline__ int dn_before_or_equal(unsigned short seq1, unsigned short seq2) { - return (before(seq1, seq2) || equal(seq1, seq2)); + return (dn_before(seq1, seq2) || dn_equal(seq1, seq2)); } static __inline__ void seq_add(unsigned short *seq, unsigned short off) @@ -185,7 +185,7 @@ static __inline__ int seq_next(unsigned short seq1, unsigned short seq2) { - return equal(seq1 + 1, seq2); + return dn_equal(seq1 + 1, seq2); } /* Index: kernel-acme/include/net/dn_route.h diff -u kernel-acme/include/net/dn_route.h:1.1.1.1 kernel-acme/include/net/dn_route.h:1.1.1.1.12.1 --- kernel-acme/include/net/dn_route.h:1.1.1.1 Tue Jun 26 17:33:58 2001 +++ kernel-acme/include/net/dn_route.h Tue Dec 11 00:26:44 2001 @@ -113,7 +113,7 @@ static inline void dn_nsp_send(struct sk_buff *skb) { struct sock *sk = skb->sk; - struct dn_scp *scp = &sk->protinfo.dn; + struct dn_scp *scp = DN_SK(sk); struct dst_entry *dst; skb->h.raw = skb->data; Index: kernel-acme/include/net/icmp.h diff -u kernel-acme/include/net/icmp.h:1.1.1.1 kernel-acme/include/net/icmp.h:1.1.1.1.12.3 --- kernel-acme/include/net/icmp.h:1.1.1.1 Tue Jun 26 17:33:57 2001 +++ kernel-acme/include/net/icmp.h Sat Dec 22 02:14:58 2001 @@ -43,4 +43,13 @@ /* Move into dst.h ? */ extern int xrlim_allow(struct dst_entry *dst, int timeout); +struct raw_opt { + struct icmp_filter filter; +}; + +#define RAW4_PINFO(__sk) ((struct raw_opt *) \ + (((char *)((((struct sock *)(__sk)) + 1))) + \ + sizeof(struct inet_opt))) +#define RAW4_SK_SIZE (sizeof(struct sock) + sizeof(struct inet_opt) +\ + sizeof(struct raw_opt)) #endif /* _ICMP_H */ Index: kernel-acme/include/net/inet_ecn.h diff -u kernel-acme/include/net/inet_ecn.h:1.1.1.2 kernel-acme/include/net/inet_ecn.h:1.1.1.2.6.2 --- kernel-acme/include/net/inet_ecn.h:1.1.1.2 Tue Nov 6 21:35:05 2001 +++ kernel-acme/include/net/inet_ecn.h Mon Dec 17 03:11:12 2001 @@ -24,15 +24,15 @@ return outer; } -#define INET_ECN_xmit(sk) do { (sk)->protinfo.af_inet.tos |= 2; } while (0) -#define INET_ECN_dontxmit(sk) do { (sk)->protinfo.af_inet.tos &= ~3; } while (0) +#define INET_ECN_xmit(sk) do { IP_SK(sk)->tos |= 2; } while (0) +#define INET_ECN_dontxmit(sk) do { IP_SK(sk)->tos &= ~3; } while (0) #define IP6_ECN_flow_init(label) do { \ (label) &= ~htonl(3<<20); \ } while (0) #define IP6_ECN_flow_xmit(sk, label) do { \ - if (INET_ECN_is_capable((sk)->protinfo.af_inet.tos)) \ + if (INET_ECN_is_capable(IP_SK(sk)->tos)) \ (label) |= __constant_htons(2 << 4); \ } while (0) Index: kernel-acme/include/net/ip.h diff -u kernel-acme/include/net/ip.h:1.1.1.1 kernel-acme/include/net/ip.h:1.1.1.1.12.1 --- kernel-acme/include/net/ip.h:1.1.1.1 Tue Jun 26 17:33:57 2001 +++ kernel-acme/include/net/ip.h Thu Dec 13 23:14:52 2001 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -181,8 +182,8 @@ static inline int ip_dont_fragment(struct sock *sk, struct dst_entry *dst) { - return (sk->protinfo.af_inet.pmtudisc == IP_PMTUDISC_DO || - (sk->protinfo.af_inet.pmtudisc == IP_PMTUDISC_WANT && + return (IP_SK(sk)->pmtudisc == IP_PMTUDISC_DO || + (IP_SK(sk)->pmtudisc == IP_PMTUDISC_WANT && !(dst->mxlock&(1<id = ((sk && sk->daddr) ? htons(sk->protinfo.af_inet.id++) : 0); + iph->id = ((sk && sk->daddr) ? htons(IP_SK(sk)->id++) : 0); } else __ip_select_ident(iph, dst); } Index: kernel-acme/include/net/ip6_route.h diff -u kernel-acme/include/net/ip6_route.h:1.1.1.1 kernel-acme/include/net/ip6_route.h:1.1.1.1.12.1 --- kernel-acme/include/net/ip6_route.h:1.1.1.1 Tue Jun 26 17:33:57 2001 +++ kernel-acme/include/net/ip6_route.h Thu Dec 13 23:14:52 2001 @@ -11,6 +11,8 @@ #include #include +#include +#include struct pol_chain { int type; @@ -97,7 +99,7 @@ static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, struct in6_addr *daddr) { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); struct rt6_info *rt = (struct rt6_info *) dst; write_lock(&sk->dst_lock); Index: kernel-acme/include/net/ipx.h diff -u kernel-acme/include/net/ipx.h:1.1.1.1 kernel-acme/include/net/ipx.h:1.1.1.1.12.4 --- kernel-acme/include/net/ipx.h:1.1.1.1 Tue Jun 26 17:33:57 2001 +++ kernel-acme/include/net/ipx.h Mon Dec 17 15:04:51 2001 @@ -86,6 +86,22 @@ int index; } last_hop; }; + +struct ipx_opt { + ipx_address dest_addr; + ipx_interface *intrfc; + unsigned short port; +#ifdef CONFIG_IPX_INTERN + unsigned char node[IPX_NODE_LEN]; +#endif + unsigned short type; + /* To handle special ncp connection-handling sockets for mars_nwe, + * the connection number must be stored in the socket. */ + unsigned short ipx_ncp_conn; +}; + +#define IPX_SK(__sk) ((struct ipx_opt *)(__sk)->protinfo) +#define IPX_SKB_CB(__skb) ((struct ipx_cb *)&((__skb)->cb[0])) #endif #define IPX_MIN_EPHEMERAL_SOCKET 0x4000 #define IPX_MAX_EPHEMERAL_SOCKET 0x7fff Index: kernel-acme/include/net/llc_actn.h diff -u /dev/null kernel-acme/include/net/llc_actn.h:1.1.12.1 --- /dev/null Sat Dec 22 02:21:02 2001 +++ kernel-acme/include/net/llc_actn.h Thu Nov 29 20:36:54 2001 @@ -0,0 +1,48 @@ +#ifndef LLC_ACTN_H +#define LLC_ACTN_H +/* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +/* Station component state transition actions */ +#define LLC_STATION_AC_START_ACK_TMR 1 +#define LLC_STATION_AC_SET_RETRY_CNT_0 2 +#define LLC_STATION_AC_INC_RETRY_CNT_BY_1 3 +#define LLC_STATION_AC_SET_XID_R_CNT_0 4 +#define LLC_STATION_AC_INC_XID_R_CNT_BY_1 5 +#define LLC_STATION_AC_SEND_NULL_DSAP_XID_C 6 +#define LLC_STATION_AC_SEND_XID_R 7 +#define LLC_STATION_AC_SEND_TEST_R 8 +#define LLC_STATION_AC_REPORT_STATUS 9 + +/* All station state event action functions look like this */ +typedef int (*llc_station_action_t)(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_station_ac_start_ack_timer(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_station_ac_set_retry_cnt_0(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_station_ac_inc_retry_cnt_by_1(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_station_ac_set_xid_r_cnt_0(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_station_ac_inc_xid_r_cnt_by_1(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_station_ac_send_null_dsap_xid_c(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_station_ac_send_xid_r(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_station_ac_send_test_r(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_station_ac_report_status(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_station_ac_report_status(struct llc_station *station, + struct llc_station_state_ev *ev); +#endif /* LLC_ACTN_H */ Index: kernel-acme/include/net/llc_c_ac.h diff -u /dev/null kernel-acme/include/net/llc_c_ac.h:1.1.12.1 --- /dev/null Sat Dec 22 02:21:02 2001 +++ kernel-acme/include/net/llc_c_ac.h Thu Nov 29 20:36:54 2001 @@ -0,0 +1,254 @@ +#ifndef LLC_C_AC_H +#define LLC_C_AC_H +/* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +/* Connection component state transition actions */ +/* + * Connection state transition actions + * (Fb = F bit; Pb = P bit; Xb = X bit) + */ +#define LLC_CONN_AC_CLR_REMOTE_BUSY 1 +#define LLC_CONN_AC_CONN_IND 2 +#define LLC_CONN_AC_CONN_CONFIRM 3 +#define LLC_CONN_AC_DATA_IND 4 +#define LLC_CONN_AC_DISC_IND 5 +#define LLC_CONN_AC_RESET_IND 6 +#define LLC_CONN_AC_RESET_CONFIRM 7 +#define LLC_CONN_AC_REPORT_STATUS 8 +#define LLC_CONN_AC_CLR_REMOTE_BUSY_IF_Fb_EQ_1 9 +#define LLC_CONN_AC_STOP_REJ_TMR_IF_DATA_FLAG_EQ_2 10 +#define LLC_CONN_AC_SEND_DISC_CMD_Pb_SET_X 11 +#define LLC_CONN_AC_SEND_DM_RSP_Fb_SET_Pb 12 +#define LLC_CONN_AC_SEND_DM_RSP_Fb_SET_1 13 +#define LLC_CONN_AC_SEND_DM_RSP_Fb_SET_F_FLAG 14 +#define LLC_CONN_AC_SEND_FRMR_RSP_Fb_SET_X 15 +#define LLC_CONN_AC_RESEND_FRMR_RSP_Fb_SET_0 16 +#define LLC_CONN_AC_RESEND_FRMR_RSP_Fb_SET_Pb 17 +#define LLC_CONN_AC_SEND_I_CMD_Pb_SET_1 18 +#define LLC_CONN_AC_RESEND_I_CMD_Pb_SET_1 19 +#define LLC_CONN_AC_RESEND_I_CMD_Pb_SET_1_OR_SEND_RR 20 +#define LLC_CONN_AC_SEND_I_XXX_Xb_SET_0 21 +#define LLC_CONN_AC_RESEND_I_XXX_Xb_SET_0 22 +#define LLC_CONN_AC_RESEND_I_XXX_Xb_SET_0_OR_SEND_RR 23 +#define LLC_CONN_AC_RESEND_I_RSP_Fb_SET_1 24 +#define LLC_CONN_AC_SEND_REJ_CMD_Pb_SET_1 25 +#define LLC_CONN_AC_SEND_REJ_RSP_Fb_SET_1 26 +#define LLC_CONN_AC_SEND_REJ_XXX_Xb_SET_0 27 +#define LLC_CONN_AC_SEND_RNR_CMD_Pb_SET_1 28 +#define LLC_CONN_AC_SEND_RNR_RSP_Fb_SET_1 29 +#define LLC_CONN_AC_SEND_RNR_XXX_Xb_SET_0 30 +#define LLC_CONN_AC_SET_REMOTE_BUSY 31 +#define LLC_CONN_AC_OPTIONAL_SEND_RNR_XXX_Xb_SET_0 32 +#define LLC_CONN_AC_SEND_RR_CMD_Pb_SET_1 33 +#define LLC_CONN_AC_SEND_ACK_CMD_Pb_SET_1 34 +#define LLC_CONN_AC_SEND_RR_RSP_Fb_SET_1 35 +#define LLC_CONN_AC_SEND_ACK_RSP_Fb_SET_1 36 +#define LLC_CONN_AC_SEND_RR_XXX_Xb_SET_0 37 +#define LLC_CONN_AC_SEND_ACK_XXX_Xb_SET_0 38 +#define LLC_CONN_AC_SEND_SABME_CMD_Pb_SET_X 39 +#define LLC_CONN_AC_SEND_UA_RSP_Fb_SET_Pb 40 +#define LLC_CONN_AC_SEND_UA_RSP_Fb_SET_F_FLAG 41 +#define LLC_CONN_AC_S_FLAG_SET_0 42 +#define LLC_CONN_AC_S_FLAG_SET_1 43 +#define LLC_CONN_AC_START_P_TMR 44 +#define LLC_CONN_AC_START_ACK_TMR 45 +#define LLC_CONN_AC_START_REJ_TMR 46 +#define LLC_CONN_AC_START_ACK_TMR_IF_NOT_RUNNING 47 +#define LLC_CONN_AC_STOP_ACK_TMR 48 +#define LLC_CONN_AC_STOP_P_TMR 49 +#define LLC_CONN_AC_STOP_REJ_TMR 50 +#define LLC_CONN_AC_STOP_ALL_TMRS 51 +#define LLC_CONN_AC_STOP_OTHER_TMRS 52 +#define LLC_CONN_AC_UPDATE_Nr_RECEIVED 53 +#define LLC_CONN_AC_UPDATE_P_FLAG 54 +#define LLC_CONN_AC_DATA_FLAG_SET_2 55 +#define LLC_CONN_AC_DATA_FLAG_SET_0 56 +#define LLC_CONN_AC_DATA_FLAG_SET_1 57 +#define LLC_CONN_AC_DATA_FLAG_SET_1_IF_DATA_FLAG_EQ_0 58 +#define LLC_CONN_AC_P_FLAG_SET_0 59 +#define LLC_CONN_AC_P_FLAG_SET_P 60 +#define LLC_CONN_AC_REMOTE_BUSY_SET_0 61 +#define LLC_CONN_AC_RETRY_CNT_SET_0 62 +#define LLC_CONN_AC_RETRY_CNT_INC_BY_1 63 +#define LLC_CONN_AC_Vr_SET_0 64 +#define LLC_CONN_AC_Vr_INC_BY_1 65 +#define LLC_CONN_AC_Vs_SET_0 66 +#define LLC_CONN_AC_Vs_SET_Nr 67 +#define LLC_CONN_AC_F_FLAG_SET_P 68 +#define LLC_CONN_AC_STOP_SENDACK_TMR 70 +#define LLC_CONN_AC_START_SENDACK_TMR_IF_NOT_RUNNING 71 + +typedef int (*llc_conn_action_t)(struct sock *sk, struct llc_conn_state_ev *ev); + +extern int llc_conn_ac_clear_remote_busy(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_conn_ind(struct sock *sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ac_conn_confirm(struct sock* sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ac_data_ind(struct sock* sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ac_disc_ind(struct sock* sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ac_rst_ind(struct sock* sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ac_rst_confirm(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_report_status(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_disc_cmd_p_set_x(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_dm_rsp_f_set_p(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_dm_rsp_f_set_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_dm_rsp_f_set_f_flag(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_i_cmd_p_set_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_i_cmd_p_set_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_resend_i_cmd_p_set_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_resend_i_cmd_p_set_1_or_send_rr(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_i_xxx_x_set_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_resend_i_xxx_x_set_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_resend_i_rsp_f_set_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_rej_cmd_p_set_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_rej_rsp_f_set_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_rej_xxx_x_set_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_remote_busy(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_rr_cmd_p_set_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_ack_cmd_p_set_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_rr_rsp_f_set_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_ack_rsp_f_set_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_rr_xxx_x_set_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_ack_xxx_x_set_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_ua_rsp_f_set_f_flag(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_ua_rsp_f_set_p(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_s_flag_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_s_flag_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_start_p_timer(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_start_ack_timer(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_start_rej_timer(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_start_ack_tmr_if_not_running(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_stop_ack_timer(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_stop_p_timer(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_stop_rej_timer(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_stop_all_timers(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_stop_other_timers(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_upd_nr_received(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_inc_tx_win_size(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_dec_tx_win_size(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_upd_p_flag(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_data_flag_2(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_data_flag_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_data_flag_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_data_flag_1_if_data_flag_eq_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_p_flag_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_p_flag_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_remote_busy_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_retry_cnt_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_cause_flag_0(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_cause_flag_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_inc_retry_cnt_by_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_vr_0(struct sock* sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ac_inc_vr_by_1(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_vs_0(struct sock* sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_vs_nr(struct sock* sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ac_rst_vs(struct sock* sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ac_upd_vs(struct sock* sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ac_set_f_flag_p(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_disc(struct sock* sk, struct llc_conn_state_ev *ev); +extern int llc_conn_reset(struct sock* sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ac_disc_confirm(struct sock* sk, struct llc_conn_state_ev *ev); +extern u8 llc_circular_between(u8 a, u8 b, u8 c); +extern int llc_conn_ac_send_ack_if_needed(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_inc_npta_value(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_adjust_npta_by_rr(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_adjust_npta_by_rnr(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_rst_sendack_flag(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_i_rsp_as_ack(struct sock* sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ac_send_i_as_ack(struct sock* sk, + struct llc_conn_state_ev *ev); +#endif /* LLC_C_AC_H */ Index: kernel-acme/include/net/llc_c_ev.h diff -u /dev/null kernel-acme/include/net/llc_c_ev.h:1.1.12.1 --- /dev/null Sat Dec 22 02:21:02 2001 +++ kernel-acme/include/net/llc_c_ev.h Thu Nov 29 20:36:54 2001 @@ -0,0 +1,323 @@ +#ifndef LLC_C_EV_H +#define LLC_C_EV_H +/* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +/* Connection component state transition event qualifiers */ +/* Types of events (possible values in 'ev->type') */ +#define LLC_CONN_EV_TYPE_SIMPLE 1 +#define LLC_CONN_EV_TYPE_CONDITION 2 +#define LLC_CONN_EV_TYPE_PRIM 3 +#define LLC_CONN_EV_TYPE_PDU 4 /* command/response PDU */ +#define LLC_CONN_EV_TYPE_ACK_TMR 5 +#define LLC_CONN_EV_TYPE_P_TMR 6 +#define LLC_CONN_EV_TYPE_REJ_TMR 7 +#define LLC_CONN_EV_TYPE_BUSY_TMR 8 +#define LLC_CONN_EV_TYPE_RPT_STATUS 9 +#define LLC_CONN_EV_TYPE_SENDACK_TMR 10 + +#define NBR_CONN_EV 5 +/* Connection events which cause state transitions when fully qualified */ + +#define LLC_CONN_EV_CONN_REQ 1 +#define LLC_CONN_EV_CONN_RESP 2 +#define LLC_CONN_EV_DATA_REQ 3 +#define LLC_CONN_EV_DISC_REQ 4 +#define LLC_CONN_EV_RESET_REQ 5 +#define LLC_CONN_EV_RESET_RESP 6 +#define LLC_CONN_EV_LOCAL_BUSY_DETECTED 7 +#define LLC_CONN_EV_LOCAL_BUSY_CLEARED 8 +#define LLC_CONN_EV_RX_BAD_PDU 9 +#define LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X 10 +#define LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X 11 +#define LLC_CONN_EV_RX_FRMR_RSP_Fbit_SET_X 12 +#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_X 13 +#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_X_UNEXPD_Ns 14 +#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_X_INVAL_Ns 15 +#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_X 16 +#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_X_UNEXPD_Ns 17 +#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_X_INVAL_Ns 18 +#define LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_X 19 +#define LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_X 20 +#define LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_X 21 +#define LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_X 22 +#define LLC_CONN_EV_RX_RR_CMD_Pbit_SET_X 23 +#define LLC_CONN_EV_RX_RR_RSP_Fbit_SET_X 24 +#define LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X 25 +#define LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X 26 +#define LLC_CONN_EV_RX_XXX_CMD_Pbit_SET_X 27 +#define LLC_CONN_EV_RX_XXX_RSP_Fbit_SET_X 28 +#define LLC_CONN_EV_RX_XXX_YYY 29 +#define LLC_CONN_EV_RX_ZZZ_CMD_Pbit_SET_X_INVAL_Nr 30 +#define LLC_CONN_EV_RX_ZZZ_RSP_Fbit_SET_X_INVAL_Nr 31 +#define LLC_CONN_EV_P_TMR_EXP 32 +#define LLC_CONN_EV_ACK_TMR_EXP 33 +#define LLC_CONN_EV_REJ_TMR_EXP 34 +#define LLC_CONN_EV_BUSY_TMR_EXP 35 +#define LLC_CONN_EV_RX_XXX_CMD_Pbit_SET_1 36 +#define LLC_CONN_EV_RX_XXX_CMD_Pbit_SET_0 37 +#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns 38 +#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns 39 +#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_1_UNEXPD_Ns 40 +#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns 41 +#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 42 +#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 43 +#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 44 +#define LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 45 +#define LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 46 +#define LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 47 +#define LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 48 +#define LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 49 +#define LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 50 +#define LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 51 +#define LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 52 +#define LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 53 +#define LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 54 +#define LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 55 +#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_1 56 +#define LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_1 57 +#define LLC_CONN_EV_RX_XXX_RSP_Fbit_SET_1 58 +#define LLC_CONN_EV_TX_BUFF_FULL 59 + +#define LLC_CONN_EV_INIT_P_F_CYCLE 100 +/* + * Connection event qualifiers; for some events a certain combination of + * these qualifiers must be TRUE before event recognized valid for state; + * these constants act as indexes into the Event Qualifier function + * table + */ +#define LLC_CONN_EV_QFY_DATA_FLAG_EQ_1 1 +#define LLC_CONN_EV_QFY_DATA_FLAG_EQ_0 2 +#define LLC_CONN_EV_QFY_DATA_FLAG_EQ_2 3 +#define LLC_CONN_EV_QFY_P_FLAG_EQ_1 4 +#define LLC_CONN_EV_QFY_P_FLAG_EQ_0 5 +#define LLC_CONN_EV_QFY_P_FLAG_EQ_Fbit 6 +#define LLC_CONN_EV_QFY_REMOTE_BUSY_EQ_0 7 +#define LLC_CONN_EV_QFY_RETRY_CNT_LT_N2 8 +#define LLC_CONN_EV_QFY_RETRY_CNT_GTE_N2 9 +#define LLC_CONN_EV_QFY_S_FLAG_EQ_1 10 +#define LLC_CONN_EV_QFY_S_FLAG_EQ_0 11 +#define LLC_CONN_EV_QFY_INIT_P_F_CYCLE 12 + +/* Event data interface; what is sent in an event package */ +/* Event LLC_CONN_EV_TYPE_SIMPLE interface */ +struct llc_conn_ev_simple_if { + u8 ev; +}; + +/* Event LLC_CONN_EV_TYPE_PRIM interface */ +struct llc_conn_ev_prim_if { + u8 prim; /* connect, disconnect, reset, ... */ + u8 type; /* request, indicate, response, conf */ + struct llc_prim_if_block *data; +}; + +/* Event LLC_CONN_EV_TYPE_PDU interface */ +struct llc_conn_ev_pdu_if { + u8 ev; + u8 reason; + struct sk_buff *skb; +}; + +/* Event interface for timer-generated events */ +struct llc_conn_ev_tmr_if { + struct sock *sk; + u32 component_handle; + void *timer_specific; +}; + +struct llc_conn_ev_rpt_sts_if { + u8 status; +}; + +union llc_conn_ev_if { + struct llc_conn_ev_simple_if a; /* 'a' for simple, easy ... */ + struct llc_conn_ev_prim_if prim; + struct llc_conn_ev_pdu_if pdu; + struct llc_conn_ev_tmr_if tmr; + struct llc_conn_ev_rpt_sts_if rsts; /* report status */ +}; + +struct llc_conn_state_ev { + u8 type; + u8 status; + u8 flag; + struct llc_prim_if_block *ind_prim; + struct llc_prim_if_block *cfm_prim; + union llc_conn_ev_if data; +}; + +typedef int (*llc_conn_ev_t)(struct sock *sk, struct llc_conn_state_ev *ev); +typedef int (*llc_conn_ev_qfyr_t)(struct sock *sk, + struct llc_conn_state_ev *ev); + +extern int llc_conn_ev_conn_req(struct sock *sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ev_conn_resp(struct sock *sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ev_data_req(struct sock *sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ev_disc_req(struct sock *sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rst_req(struct sock *sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rst_resp(struct sock *sk, struct llc_conn_state_ev *ev); +extern int llc_conn_ev_local_busy_detected(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_local_busy_cleared(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_bad_pdu(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_xxx_yyy(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_p_tmr_exp(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_ack_tmr_exp(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rej_tmr_exp(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_busy_tmr_exp(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_any_tmr_exp(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_sendack_tmr_exp(struct sock *sk, + struct llc_conn_state_ev *ev); +/* NOT_USED functions and their variations */ +extern int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_xxx_cmd_pbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_rx_any_frame(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_tx_buffer_full(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_init_p_f_cycle(struct sock *sk, + struct llc_conn_state_ev *ev); + +/* Available connection action qualifiers */ +extern int llc_conn_ev_qlfy_data_flag_eq_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_data_flag_eq_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_data_flag_eq_2(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_p_flag_eq_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_last_frame_eq_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_last_frame_eq_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_p_flag_eq_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_p_flag_eq_f(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_remote_busy_eq_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_remote_busy_eq_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_retry_cnt_lt_n2(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_retry_cnt_gte_n2(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_s_flag_eq_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_s_flag_eq_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_cause_flag_eq_1(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_cause_flag_eq_0(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_init_p_f_cycle(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_set_status_conn(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_set_status_disc(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_set_status_failed(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_set_status_impossible(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_set_status_remote_busy(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_set_status_received(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_set_status_refuse(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_set_status_conflict(struct sock *sk, + struct llc_conn_state_ev *ev); +extern int llc_conn_ev_qlfy_set_status_rst_done(struct sock *sk, + struct llc_conn_state_ev *ev); +#endif /* LLC_C_EV_H */ Index: kernel-acme/include/net/llc_c_st.h diff -u /dev/null kernel-acme/include/net/llc_c_st.h:1.1.12.2 --- /dev/null Sat Dec 22 02:21:02 2001 +++ kernel-acme/include/net/llc_c_st.h Sat Dec 1 00:45:51 2001 @@ -0,0 +1,48 @@ +#ifndef LLC_C_ST_H +#define LLC_C_ST_H +/* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +/* Connection component state management */ +/* connection states */ +#define LLC_CONN_OUT_OF_SVC 0 /* prior to allocation */ + +#define LLC_CONN_STATE_ADM 1 /* disc, initial state */ +#define LLC_CONN_STATE_SETUP 2 /* disconnected state */ +#define LLC_CONN_STATE_NORMAL 3 /* connected state */ +#define LLC_CONN_STATE_BUSY 4 /* connected state */ +#define LLC_CONN_STATE_REJ 5 /* connected state */ +#define LLC_CONN_STATE_AWAIT 6 /* connected state */ +#define LLC_CONN_STATE_AWAIT_BUSY 7 /* connected state */ +#define LLC_CONN_STATE_AWAIT_REJ 8 /* connected state */ +#define LLC_CONN_STATE_D_CONN 9 /* disconnected state */ +#define LLC_CONN_STATE_RESET 10 /* disconnected state */ +#define LLC_CONN_STATE_ERROR 11 /* disconnected state */ +#define LLC_CONN_STATE_TEMP 12 /* disconnected state */ + +#define NBR_CONN_STATES 12 /* size of state table */ +#define NO_STATE_CHANGE 100 + +/* Connection state table structure */ +struct llc_conn_state_trans { + llc_conn_ev_t ev; + u8 next_state; + llc_conn_ev_qfyr_t *ev_qualifiers; + llc_conn_action_t *ev_actions; +}; + +struct llc_conn_state { + u8 current_state; + struct llc_conn_state_trans **transitions; +}; + +extern struct llc_conn_state llc_conn_state_table[]; +#endif /* LLC_C_ST_H */ Index: kernel-acme/include/net/llc_conn.h diff -u /dev/null kernel-acme/include/net/llc_conn.h:1.1.12.6 --- /dev/null Sat Dec 22 02:21:02 2001 +++ kernel-acme/include/net/llc_conn.h Mon Dec 17 15:04:51 2001 @@ -0,0 +1,155 @@ +#ifndef LLC_CONN_H +#define LLC_CONN_H +/* + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include + +#undef DEBUG_LLC_CONN_ALLOC + +struct llc_timer { + struct timer_list timer; + u8 running; /* timer is running or no */ + u16 expire; /* timer expire time */ +}; + +struct llc_opt { + struct list_head node; /* entry in sap->sk_list.list */ + struct sock *sk; /* sock that has this llc_opt */ + void *handler; /* for upper layers usage */ + u8 state; /* state of connection */ + struct llc_sap *sap; /* pointer to parent SAP */ + struct llc_addr laddr; /* lsap/mac pair */ + struct llc_addr daddr; /* dsap/mac pair */ + struct net_device *dev; /* device to send to remote */ + u8 retry_count; /* number of retries */ + u8 ack_must_be_send; + u8 first_pdu_Ns; + u8 npta; + struct llc_timer ack_timer; + struct llc_timer pf_cycle_timer; + struct llc_timer rej_sent_timer; + struct llc_timer busy_state_timer; /* ind busy clr at remote LLC */ + u8 vS; /* seq# next in-seq I-PDU tx'd*/ + u8 vR; /* seq# next in-seq I-PDU rx'd*/ + u32 n2; /* max nbr re-tx's for timeout*/ + u32 n1; /* max nbr octets in I PDU */ + u8 k; /* tx window size; max = 127 */ + u8 rw; /* rx window size; max = 127 */ + u8 p_flag; /* state flags */ + u8 f_flag; + u8 s_flag; + u8 data_flag; + u8 remote_busy_flag; + u8 cause_flag; + struct sk_buff_head pdu_unack_q; /* PUDs sent/waiting ack */ + u16 link; /* network layer link number */ + u8 X; /* a temporary variable */ + u8 ack_pf; /* this flag indicates what is + the P-bit of acknowledge */ + u8 failed_data_req; /* recognize that already exist a + failed llc_data_req_handler + (tx_buffer_full or unacceptable + state */ + u8 dec_step; + u8 inc_cntr; + u8 dec_cntr; + u8 connect_step; + u8 last_nr; /* NR of last pdu recieved */ + u32 rx_pdu_hdr; /* used for saving header of last pdu + received and caused sending FRMR. + Used for resending FRMR */ +#ifdef DEBUG_LLC_CONN_ALLOC + char *f_alloc, /* function that allocated this connection */ + *f_free; /* function that freed this connection */ + int l_alloc, /* line that allocated this connection */ + l_free; /* line that freed this connection */ +#endif +}; + +#define LLC_SK(__sk) ((struct llc_opt *)(__sk)->protinfo) + +struct llc_conn_state_ev; + +extern struct sock *__llc_sock_alloc(void); +extern void __llc_sock_free(struct sock *sk, u8 free); + +#ifdef DEBUG_LLC_CONN_ALLOC +#define dump_stack() printk(KERN_INFO "call trace: %p, %p, %p\n", \ + __builtin_return_address(0), \ + __builtin_return_address(1), \ + __builtin_return_address(2)); +#define llc_sock_alloc() ({ \ + struct sock *__sk = __llc_sock_alloc(); \ + if (__sk) { \ + LLC_SK(__sk)->f_alloc = __FUNCTION__; \ + LLC_SK(__sk)->l_alloc = __LINE__; \ + } \ + __sk;}) +#define __llc_sock_assert(__sk) \ + if (LLC_SK(__sk)->f_free) { \ + printk(KERN_ERR \ + "%p conn (alloc'd @ %s(%d)) " \ + "already freed @ %s(%d) " \ + "being used again @ %s(%d)\n", \ + LLC_SK(__sk), \ + LLC_SK(__sk)->f_alloc, LLC_SK(__sk)->l_alloc, \ + LLC_SK(__sk)->f_free, LLC_SK(__sk)->l_free, \ + __FUNCTION__, __LINE__); \ + dump_stack(); +#define llc_sock_free(__sk) \ +{ \ + __llc_sock_assert(__sk) \ + } else { \ + __llc_sock_free(__sk, 0); \ + LLC_SK(__sk)->f_free = __FUNCTION__; \ + LLC_SK(__sk)->l_free = __LINE__; \ + } \ +} +#define llc_sock_assert(__sk) \ +{ \ + __llc_sock_assert(__sk); \ + return; } \ +} +#define llc_sock_assert_ret(__sk, __ret) \ +{ \ + __llc_sock_assert(__sk); \ + return __ret; } \ +} +#else /* DEBUG_LLC_CONN_ALLOC */ +#define llc_sock_alloc() __llc_sock_alloc() +#define llc_sock_free(__sk) __llc_sock_free(__sk, 1) +#define llc_sock_assert(__sk) +#define llc_sock_assert_ret(__sk) +#endif /* DEBUG_LLC_CONN_ALLOC */ + +extern void llc_sock_reset(struct sock *sk); +extern int llc_sock_init(struct sock *sk); + +/* Access to a connection */ +extern struct llc_conn_state_ev *llc_conn_alloc_ev(struct sock *sk); +extern int llc_conn_send_ev(struct sock *sk, struct llc_conn_state_ev *ev); +extern void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb); +extern void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb, + struct llc_conn_state_ev *ev); +extern void llc_conn_free_ev(struct llc_conn_state_ev *ev); +extern void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, + u8 first_p_bit); +extern void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, + u8 first_f_bit); +extern int llc_conn_remove_acked_pdus(struct sock *conn, u8 nr, + u16 *how_many_unacked); +extern struct sock *llc_find_sock(struct llc_sap *sap, struct llc_addr *daddr, + struct llc_addr *laddr); +extern u8 llc_data_accept_state(u8 state); +extern void llc_build_offset_table(void); +#endif /* LLC_CONN_H */ Index: kernel-acme/include/net/llc_evnt.h diff -u /dev/null kernel-acme/include/net/llc_evnt.h:1.1.12.1 --- /dev/null Sat Dec 22 02:21:03 2001 +++ kernel-acme/include/net/llc_evnt.h Thu Nov 29 20:36:54 2001 @@ -0,0 +1,93 @@ +#ifndef LLC_EVNT_H +#define LLC_EVNT_H +/* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +/* Station component state transition events */ +/* Types of events (possible values in 'ev->type') */ +#define LLC_STATION_EV_TYPE_SIMPLE 1 +#define LLC_STATION_EV_TYPE_CONDITION 2 +#define LLC_STATION_EV_TYPE_PRIM 3 +#define LLC_STATION_EV_TYPE_PDU 4 /* command/response PDU */ +#define LLC_STATION_EV_TYPE_ACK_TMR 5 +#define LLC_STATION_EV_TYPE_RPT_STATUS 6 + +/* Events */ +#define LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK 1 +#define LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK 2 +#define LLC_STATION_EV_ACK_TMR_EXP_LT_RETRY_CNT_MAX_RETRY 3 +#define LLC_STATION_EV_ACK_TMR_EXP_EQ_RETRY_CNT_MAX_RETRY 4 +#define LLC_STATION_EV_RX_NULL_DSAP_XID_C 5 +#define LLC_STATION_EV_RX_NULL_DSAP_0_XID_R_XID_R_CNT_EQ 6 +#define LLC_STATION_EV_RX_NULL_DSAP_1_XID_R_XID_R_CNT_EQ 7 +#define LLC_STATION_EV_RX_NULL_DSAP_TEST_C 8 +#define LLC_STATION_EV_DISABLE_REQ 9 + +/* Interfaces for various types of supported events */ +struct llc_stat_ev_simple_if { + u8 ev; +}; + +struct llc_stat_ev_prim_if { + u8 prim; /* connect, disconnect, reset, ... */ + u8 type; /* request, indicate, response, confirm */ +}; + +struct llc_stat_ev_pdu_if { + u8 reason; + struct sk_buff *skb; +}; + +struct llc_stat_ev_tmr_if { + void *timer_specific; +}; + +struct llc_stat_ev_rpt_sts_if { + u8 status; +}; + +union llc_stat_ev_if { + struct llc_stat_ev_simple_if a; /* 'a' for simple, easy ... */ + struct llc_stat_ev_prim_if prim; + struct llc_stat_ev_pdu_if pdu; + struct llc_stat_ev_tmr_if tmr; + struct llc_stat_ev_rpt_sts_if rsts; /* report status */ +}; + +struct llc_station_state_ev { + u8 type; + union llc_stat_ev_if data; + struct list_head node; /* node in station->ev_q.list */ +}; + +typedef int (*llc_station_ev_t)(struct llc_station *station, + struct llc_station_state_ev *ev); + +extern int llc_stat_ev_enable_with_dup_addr_check(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_stat_ev_enable_without_dup_addr_check(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry(struct llc_station * + station, + struct llc_station_state_ev *ev); +extern int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station, + struct llc_station_state_ev *ev); +extern int llc_stat_ev_disable_req(struct llc_station *station, + struct llc_station_state_ev *ev); +#endif /* LLC_EVNT_H */ Index: kernel-acme/include/net/llc_if.h diff -u /dev/null kernel-acme/include/net/llc_if.h:1.1.12.2 --- /dev/null Sat Dec 22 02:21:03 2001 +++ kernel-acme/include/net/llc_if.h Tue Dec 11 00:26:44 2001 @@ -0,0 +1,155 @@ +#ifndef LLC_IF_H +#define LLC_IF_H +/* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +/* Defines LLC interface to network layer */ +/* Available primitives */ +#include + +#define LLC_DATAUNIT_PRIM 0 +#define LLC_CONN_PRIM 1 +#define LLC_DATA_PRIM 2 +#define LLC_DISC_PRIM 3 +#define LLC_RESET_PRIM 4 +#define LLC_FLOWCONTROL_PRIM 5 +#define LLC_DISABLE_PRIM 6 +#define LLC_XID_PRIM 7 +#define LLC_TEST_PRIM 8 +#define LLC_SAP_ACTIVATION 9 +#define LLC_SAP_DEACTIVATION 10 + +#define LLC_NBR_PRIMITIVES 11 + +#define LLC_IND 1 +#define LLC_CONFIRM 2 + +/* Primitive type */ +#define LLC_PRIM_TYPE_REQ 1 +#define LLC_PRIM_TYPE_IND 2 +#define LLC_PRIM_TYPE_RESP 3 +#define LLC_PRIM_TYPE_CONFIRM 4 + +/* Reset reasons, remote entity or local LLC */ +#define LLC_RESET_REASON_REMOTE 1 +#define LLC_RESET_REASON_LOCAL 2 + +/* Disconnect reasons */ +#define LLC_DISC_REASON_RX_DM_RSP_PDU 0 +#define LLC_DISC_REASON_RX_DISC_CMD_PDU 1 +#define LLC_DISC_REASON_ACK_TMR_EXP 2 + +/* Confirm reasons */ +#define LLC_STATUS_CONN 0 /* connect confirm & reset confirm */ +#define LLC_STATUS_DISC 1 /* connect confirm & reset confirm */ +#define LLC_STATUS_FAILED 2 /* connect confirm & reset confirm */ +#define LLC_STATUS_IMPOSSIBLE 3 /* connect confirm */ +#define LLC_STATUS_RECEIVED 4 /* data conn */ +#define LLC_STATUS_REMOTE_BUSY 5 /* data conn */ +#define LLC_STATUS_REFUSE 6 /* data conn */ +#define LLC_STATUS_CONFLICT 7 /* disconnect conn */ +#define LLC_STATUS_RESET_DONE 8 /* */ + +/* Structures and types */ +/* SAP/MAC Address pair */ +struct llc_addr { + u8 lsap; + u8 mac[IFHWADDRLEN]; +}; + +/* Primitive-specific data */ +struct llc_prim_conn { + struct llc_addr saddr; /* used by request only */ + struct llc_addr daddr; /* used by request only */ + u8 status; /* reason for failure */ + u8 pri; /* service_class */ + struct net_device *dev; + struct sock *sk; /* returned from REQUEST */ + void *handler; /* upper layer use, + stored in llc_opt->handler */ + u16 link; + struct sk_buff *skb; /* received SABME */ +}; + +struct llc_prim_disc { + struct sock *sk; + u16 link; + u8 reason; /* not used by request */ +}; + +struct llc_prim_reset { + struct sock *sk; + u16 link; + u8 reason; /* used only by indicate */ +}; + +struct llc_prim_flow_ctrl { + struct sock *sk; + u16 link; + u32 amount; +}; + +struct llc_prim_data { + struct sock *sk; + u16 link; + u8 pri; + struct sk_buff *skb; /* pointer to frame */ + u8 status; /* reason */ +}; + + /* Sending data in conection-less mode */ +struct llc_prim_unit_data { + struct llc_addr saddr; + struct llc_addr daddr; + u8 pri; + struct sk_buff *skb; /* pointer to frame */ + u8 lfb; /* largest frame bit (TR) */ +}; + +struct llc_prim_xid { + struct llc_addr saddr; + struct llc_addr daddr; + u8 pri; + struct sk_buff *skb; +}; + +struct llc_prim_test { + struct llc_addr saddr; + struct llc_addr daddr; + u8 pri; + struct sk_buff *skb; /* pointer to frame */ +}; + +union llc_u_prim_data { + struct llc_prim_conn conn; + struct llc_prim_disc disc; + struct llc_prim_reset res; + struct llc_prim_flow_ctrl fc; + struct llc_prim_data data; /* data */ + struct llc_prim_unit_data udata; /* unit data */ + struct llc_prim_xid xid; + struct llc_prim_test test; +}; + +struct llc_sap; + +/* Information block passed with all called primitives */ +struct llc_prim_if_block { + struct llc_sap *sap; + u8 prim; + union llc_u_prim_data *data; +}; +typedef int (*llc_prim_call_t)(struct llc_prim_if_block *prim_if); + +extern struct llc_sap *llc_sap_open(llc_prim_call_t network_indicate, + llc_prim_call_t network_confirm, u8 lsap); +extern void llc_sap_close(struct llc_sap *sap); +#endif /* LLC_IF_H */ Index: kernel-acme/include/net/llc_mac.h diff -u /dev/null kernel-acme/include/net/llc_mac.h:1.1.12.2 --- /dev/null Sat Dec 22 02:21:03 2001 +++ kernel-acme/include/net/llc_mac.h Tue Dec 11 00:26:44 2001 @@ -0,0 +1,23 @@ +#ifndef LLC_MAC_H +#define LLC_MAC_H +/* + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +/* Defines MAC-layer interface to LLC layer */ +extern int mac_send_pdu(struct sk_buff *skb); +extern int mac_indicate(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt); +extern struct net_device *mac_dev_peer(struct net_device *current_dev, + int type, u8 *mac); +extern int llc_pdu_router(struct llc_sap *sap, struct sock *sk, + struct sk_buff *skb, u8 type); +extern u16 lan_hdrs_init(struct sk_buff *skb, u8 *sa, u8 *da); +#endif /* LLC_MAC_H */ Index: kernel-acme/include/net/llc_main.h diff -u /dev/null kernel-acme/include/net/llc_main.h:1.1.12.1 --- /dev/null Sat Dec 22 02:21:03 2001 +++ kernel-acme/include/net/llc_main.h Thu Nov 29 20:36:54 2001 @@ -0,0 +1,68 @@ +#ifndef LLC_MAIN_H +#define LLC_MAIN_H +/* + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#define LLC_EVENT 1 +#define LLC_PACKET 2 +#define LLC_TYPE_1 1 +#define LLC_TYPE_2 2 +#define LLC_P_TIME 2 +#define LLC_ACK_TIME 3 +#define LLC_REJ_TIME 3 +#define LLC_BUSY_TIME 3 +#define LLC_SENDACK_TIME 50 +#define LLC_DEST_INVALID 0 /* Invalid LLC PDU type */ +#define LLC_DEST_SAP 1 /* Type 1 goes here */ +#define LLC_DEST_CONN 2 /* Type 2 goes here */ + +/* LLC Layer global default parameters */ + +#define LLC_GLOBAL_DEFAULT_MAX_NBR_SAPS 4 +#define LLC_GLOBAL_DEFAULT_MAX_NBR_CONNS 64 + +extern struct llc_prim_if_block llc_ind_prim, llc_cfm_prim; + +/* LLC station component (SAP and connection resource manager) */ +/* Station component; one per adapter */ +struct llc_station { + u8 state; /* state of station */ + u8 xid_r_count; /* XID response PDU counter */ + struct timer_list ack_timer; + u8 ack_tmr_running; /* 1 or 0 */ + u8 retry_count; + u8 maximum_retry; + u8 mac_sa[6]; /* MAC source address */ + struct { + spinlock_t lock; + struct list_head list; + } sap_list; /* list of related SAPs */ + struct { + spinlock_t lock; + struct list_head list; + } ev_q; /* events entering state mach. */ + struct sk_buff_head mac_pdu_q; /* PDUs ready to send to MAC */ +}; +struct llc_station_state_ev; + +extern struct llc_sap *llc_sap_alloc(void); +extern void llc_sap_save(struct llc_sap *sap); +extern void llc_free_sap(struct llc_sap *sap); +extern struct llc_sap *llc_sap_find(u8 lsap); +extern struct llc_station *llc_station_get(void); +extern struct llc_station_state_ev * + llc_station_alloc_ev(struct llc_station *station); +extern void llc_station_send_ev(struct llc_station *station, + struct llc_station_state_ev *ev); +extern void llc_station_send_pdu(struct llc_station *station, + struct sk_buff *skb); +extern struct sk_buff *llc_alloc_frame(void); +#endif /* LLC_MAIN_H */ Index: kernel-acme/include/net/llc_pdu.h diff -u /dev/null kernel-acme/include/net/llc_pdu.h:1.1.12.1 --- /dev/null Sat Dec 22 02:21:03 2001 +++ kernel-acme/include/net/llc_pdu.h Thu Nov 29 20:36:54 2001 @@ -0,0 +1,255 @@ +#ifndef LLC_PDU_H +#define LLC_PDU_H +/* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +/* LLC PDU structure */ +/* Lengths of frame formats */ +#define LLC_PDU_LEN_I 4 /* header and 2 control bytes */ +#define LLC_PDU_LEN_S 4 +#define LLC_PDU_LEN_U 3 /* header and 1 control byte */ +/* Known SAP addresses */ +#define LLC_GLOBAL_SAP 0xFF +#define LLC_NULL_SAP 0x00 /* not network-layer visible */ +#define LLC_MGMT_INDIV 0x02 /* station LLC mgmt indiv addr */ +#define LLC_MGMT_GRP 0x03 /* station LLC mgmt group addr */ +#define LLC_RDE_SAP 0xA6 /* route ... */ + +/* SAP field bit masks */ +#define LLC_ISO_RESERVED_SAP 0x02 +#define LLC_SAP_GROUP_DSAP 0x01 +#define LLC_SAP_RESP_SSAP 0x01 + +/* Group/individual DSAP indicator is DSAP field */ +#define LLC_PDU_GROUP_DSAP_MASK 0x01 +#define LLC_PDU_IS_GROUP_DSAP(pdu) \ + ((pdu->dsap & LLC_PDU_GROUP_DSAP_MASK) ? 0 : 1) +#define LLC_PDU_IS_INDIV_DSAP(pdu) \ + (!(pdu->dsap & LLC_PDU_GROUP_DSAP_MASK) ? 0 : 1) + +/* Command/response PDU indicator in SSAP field */ +#define LLC_PDU_CMD_RSP_MASK 0x01 +#define LLC_PDU_CMD 0 +#define LLC_PDU_RSP 1 +#define LLC_PDU_IS_CMD(pdu) ((pdu->ssap & LLC_PDU_RSP) ? 1 : 0) +#define LLC_PDU_IS_RSP(pdu) ((pdu->ssap & LLC_PDU_RSP) ? 0 : 1) + +/* Get PDU type from 2 lowest-order bits of control field first byte */ +#define LLC_PDU_TYPE_I_MASK 0x01 /* 16-bit control field */ +#define LLC_PDU_TYPE_S_MASK 0x03 +#define LLC_PDU_TYPE_U_MASK 0x03 /* 8-bit control field */ +#define LLC_PDU_TYPE_MASK 0x03 + +#define LLC_PDU_TYPE_I 0 /* first bit */ +#define LLC_PDU_TYPE_S 1 /* first two bits */ +#define LLC_PDU_TYPE_U 3 /* first two bits */ + +#define LLC_PDU_TYPE_IS_I(pdu) \ + ((!(pdu->ctrl_1 & LLC_PDU_TYPE_I_MASK)) ? 0 : 1) + +#define LLC_PDU_TYPE_IS_U(pdu) \ + (((pdu->ctrl_1 & LLC_PDU_TYPE_U_MASK) == LLC_PDU_TYPE_U) ? 0 : 1) + +#define LLC_PDU_TYPE_IS_S(pdu) \ + (((pdu->ctrl_1 & LLC_PDU_TYPE_S_MASK) == LLC_PDU_TYPE_S) ? 0 : 1) + +/* U-format PDU control field masks */ +#define LLC_U_PF_BIT_MASK 0x10 /* P/F bit mask */ +#define LLC_U_PF_IS_1(pdu) ((pdu->ctrl_1 & LLC_U_PF_BIT_MASK) ? 0 : 1) +#define LLC_U_PF_IS_0(pdu) ((!(pdu->ctrl_1 & LLC_U_PF_BIT_MASK)) ? 0 : 1) + +#define LLC_U_PDU_CMD_MASK 0xEC /* cmd/rsp mask */ +#define LLC_U_PDU_CMD(pdu) (pdu->ctrl_1 & LLC_U_PDU_CMD_MASK) +#define LLC_U_PDU_RSP(pdu) (pdu->ctrl_1 & LLC_U_PDU_CMD_MASK) + +#define LLC_1_PDU_CMD_UI 0x00 /* Type 1 cmds/rsps */ +#define LLC_1_PDU_CMD_XID 0xAC +#define LLC_1_PDU_CMD_TEST 0xE0 + +#define LLC_2_PDU_CMD_SABME 0x6C /* Type 2 cmds/rsps */ +#define LLC_2_PDU_CMD_DISC 0x40 +#define LLC_2_PDU_RSP_UA 0x60 +#define LLC_2_PDU_RSP_DM 0x0C +#define LLC_2_PDU_RSP_FRMR 0x84 + +/* Type 1 operations */ + +/* XID information field bit masks */ + +/* LLC format identifier (byte 1) */ +#define LLC_XID_FMT_ID 0x81 /* first byte must be this */ + +/* LLC types/classes identifier (byte 2) */ +#define LLC_XID_CLASS_ZEROS_MASK 0xE0 /* these must be zeros */ +#define LLC_XID_CLASS_MASK 0x1F /* AND with byte to get below */ + +#define LLC_XID_NULL_CLASS_1 0x01 /* if NULL LSAP...use these */ +#define LLC_XID_NULL_CLASS_2 0x03 +#define LLC_XID_NULL_CLASS_3 0x05 +#define LLC_XID_NULL_CLASS_4 0x07 + +#define LLC_XID_NNULL_TYPE_1 0x01 /* if non-NULL LSAP...use these */ +#define LLC_XID_NNULL_TYPE_2 0x02 +#define LLC_XID_NNULL_TYPE_3 0x04 +#define LLC_XID_NNULL_TYPE_1_2 0x03 +#define LLC_XID_NNULL_TYPE_1_3 0x05 +#define LLC_XID_NNULL_TYPE_2_3 0x06 +#define LLC_XID_NNULL_ALL 0x07 + +/* Sender Receive Window (byte 3) */ +#define LLC_XID_RW_MASK 0xFE /* AND with value to get below */ + +#define LLC_XID_MIN_RW 0x02 /* lowest-order bit always zero */ + +/* Type 2 operations */ + +#define LLC_2_SEQ_NBR_MODULO ((u8) 128) + +/* I-PDU masks ('ctrl' is I-PDU control word) */ +#define LLC_I_GET_NS(pdu) (u8)((pdu->ctrl_1 & 0xFE) >> 1) +#define LLC_I_GET_NR(pdu) (u8)((pdu->ctrl_2 & 0xFE) >> 1) + +#define LLC_I_PF_BIT_MASK 0x01 + +#define LLC_I_PF_IS_0(pdu) ((!(pdu->ctrl_2 & LLC_I_PF_BIT_MASK)) ? 0 : 1) +#define LLC_I_PF_IS_1(pdu) ((pdu->ctrl_2 & LLC_I_PF_BIT_MASK) ? 0 : 1) + +/* S-PDU supervisory commands and responses */ + +#define LLC_S_PDU_CMD_MASK 0x0C +#define LLC_S_PDU_CMD(pdu) (pdu->ctrl_1 & LLC_S_PDU_CMD_MASK) +#define LLC_S_PDU_RSP(pdu) (pdu->ctrl_1 & LLC_S_PDU_CMD_MASK) + +#define LLC_2_PDU_CMD_RR 0x00 /* rx ready cmd */ +#define LLC_2_PDU_RSP_RR 0x00 /* rx ready rsp */ +#define LLC_2_PDU_CMD_REJ 0x08 /* reject PDU cmd */ +#define LLC_2_PDU_RSP_REJ 0x08 /* reject PDU rsp */ +#define LLC_2_PDU_CMD_RNR 0x04 /* rx not ready cmd */ +#define LLC_2_PDU_RSP_RNR 0x04 /* rx not ready rsp */ + +#define LLC_S_PF_BIT_MASK 0x01 +#define LLC_S_PF_IS_0(pdu) ((!(pdu->ctrl_2 & LLC_S_PF_BIT_MASK)) ? 0 : 1) +#define LLC_S_PF_IS_1(pdu) ((pdu->ctrl_2 & LLC_S_PF_BIT_MASK) ? 0 : 1) + +#define PDU_SUPV_GET_Nr(pdu) ((pdu->ctrl_2 & 0xFE) >> 1) +#define PDU_GET_NEXT_Vr(sn) (++sn & ~LLC_2_SEQ_NBR_MODULO) + +/* FRMR information field macros */ + +#define FRMR_INFO_LENGTH 5 /* 5 bytes of information */ + +/* + * info is pointer to FRMR info field structure; 'rej_ctrl' is byte pointer + * (if U-PDU) or word pointer to rejected PDU control field + */ +#define FRMR_INFO_SET_REJ_CNTRL(info,rej_ctrl) \ + info->rej_pdu_ctrl = ((*((u8 *) rej_ctrl) & \ + LLC_PDU_TYPE_U) != LLC_PDU_TYPE_U ? \ + (u16)*((u16 *) rej_ctrl) : \ + (((u16) *((u8 *) rej_ctrl)) & 0x00FF)) + +/* + * Info is pointer to FRMR info field structure; 'vs' is a byte containing + * send state variable value in low-order 7 bits (insure the lowest-order + * bit remains zero (0)) + */ +#define FRMR_INFO_SET_Vs(info,vs) (info->curr_ssv = (((u8) vs) << 1)) +#define FRMR_INFO_SET_Vr(info,vr) (info->curr_rsv = (((u8) vr) << 1)) + +/* + * Info is pointer to FRMR info field structure; 'cr' is a byte containing + * the C/R bit value in the low-order bit + */ +#define FRMR_INFO_SET_C_R_BIT(info, cr) (info->curr_rsv |= (((u8) cr) & 0x01)) + +/* + * In the remaining five macros, 'info' is pointer to FRMR info field + * structure; 'ind' is a byte containing the bit value to set in the + * lowest-order bit) + */ +#define FRMR_INFO_SET_INVALID_PDU_CTRL_IND(info, ind) \ + (info->ind_bits = ((info->ind_bits & 0xFE) | (((u8) ind) & 0x01))) + +#define FRMR_INFO_SET_INVALID_PDU_INFO_IND(info, ind) \ + (info->ind_bits = ( (info->ind_bits & 0xFD) | (((u8) ind) & 0x02))) + +#define FRMR_INFO_SET_PDU_INFO_2LONG_IND(info, ind) \ + (info->ind_bits = ( (info->ind_bits & 0xFB) | (((u8) ind) & 0x04))) + +#define FRMR_INFO_SET_PDU_INVALID_Nr_IND(info, ind) \ + (info->ind_bits = ( (info->ind_bits & 0xF7) | (((u8) ind) & 0x08))) + +#define FRMR_INFO_SET_PDU_INVALID_Ns_IND(info, ind) \ + (info->ind_bits = ( (info->ind_bits & 0xEF) | (((u8) ind) & 0x10))) + +/* Sequence-numbered PDU format (4 bytes in length) */ +typedef struct llc_pdu_sn { + u8 dsap; + u8 ssap; + u8 ctrl_1; + u8 ctrl_2; +} llc_pdu_sn_t; + +/* Un-numbered PDU format (3 bytes in length) */ +typedef struct llc_pdu_un { + u8 dsap; + u8 ssap; + u8 ctrl_1; +} llc_pdu_un_t; + +/* LLC Type 1 XID command/response information fields format */ +typedef struct llc_xid_info { + u8 fmt_id; /* always 0x18 for LLC */ + u8 type; /* different if NULL/non-NULL LSAP */ + u8 rw; /* sender receive window */ +} llc_xid_info_t; + +/* LLC Type 2 FRMR response information field format */ +typedef struct llc_frmr_info { + u16 rej_pdu_ctrl; /* bits 1-8 if U-PDU */ + u8 curr_ssv; /* current send state variable val */ + u8 curr_rsv; /* current receive state variable */ + u8 ind_bits; /* indicator bits set with macro */ +} llc_frmr_info_t; + +extern void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 type); +extern void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value); +extern int llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit); +extern int llc_pdu_decode_cr_bit(struct sk_buff *skb, u8 *cr_bit); +extern int llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa); +extern int llc_pdu_decode_da(struct sk_buff *skb, u8 *ds); +extern int llc_pdu_decode_dsap(struct sk_buff *skb, u8 *dsap); +extern int llc_pdu_decode_ssap(struct sk_buff *skb, u8 *ssap); +extern int llc_decode_pdu_type(struct sk_buff *skb, u8 *destination); +extern void llc_pdu_header_init(struct sk_buff *skb, u8 pdu_type, u8 ssap, + u8 dsap, u8 cr); +extern int llc_pdu_init_as_ui_cmd(struct sk_buff *skb); +extern int llc_pdu_init_as_xid_cmd(struct sk_buff *skb, u8 svcs_supported, + u8 rx_window); +extern int llc_pdu_init_as_test_cmd(struct sk_buff *skb); +extern int llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit); +extern int llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr); +extern int llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr); +extern int llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr); +extern int llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr); +extern int llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit); +extern int llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit); +extern int llc_pdu_init_as_xid_rsp(struct sk_buff *skb, u8 svcs_supported, + u8 rx_window); +extern int llc_pdu_init_as_test_rsp(struct sk_buff *skb, + struct sk_buff *ev_skb); +extern int llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, llc_pdu_sn_t *prev_pdu, + u8 f_bit, u8 vs, u8 vr, u8 vzyxw); +extern int llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr); +extern int llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr); +extern int llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr); +extern int llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit); +#endif /* LLC_PDU_H */ Index: kernel-acme/include/net/llc_s_ac.h diff -u /dev/null kernel-acme/include/net/llc_s_ac.h:1.1.12.1 --- /dev/null Sat Dec 22 02:21:03 2001 +++ kernel-acme/include/net/llc_s_ac.h Thu Nov 29 20:36:54 2001 @@ -0,0 +1,47 @@ +#ifndef LLC_S_AC_H +#define LLC_S_AC_H +/* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +/* SAP component actions */ +#define SAP_ACT_UNITDATA_IND 1 +#define SAP_ACT_SEND_UI 2 +#define SAP_ACT_SEND_XID_C 3 +#define SAP_ACT_SEND_XID_R 4 +#define SAP_ACT_SEND_TEST_C 5 +#define SAP_ACT_SEND_TEST_R 6 +#define SAP_ACT_REPORT_STATUS 7 +#define SAP_ACT_XID_IND 8 +#define SAP_ACT_TEST_IND 9 + +/* All action functions must look like this */ +typedef int (*llc_sap_action_t)(struct llc_sap *sap, + struct llc_sap_state_ev *ev); + +extern int llc_sap_action_unitdata_ind(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_action_send_ui(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_action_send_xid_c(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_action_send_xid_r(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_action_send_test_c(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_action_send_test_r(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_action_report_status(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_action_xid_ind(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_action_test_ind(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +#endif /* LLC_S_AC_H */ Index: kernel-acme/include/net/llc_s_ev.h diff -u /dev/null kernel-acme/include/net/llc_s_ev.h:1.1.12.1 --- /dev/null Sat Dec 22 02:21:03 2001 +++ kernel-acme/include/net/llc_s_ev.h Thu Nov 29 20:36:54 2001 @@ -0,0 +1,101 @@ +#ifndef LLC_S_EV_H +#define LLC_S_EV_H +/* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +/* Defines SAP component events */ +/* Types of events (possible values in 'ev->type') */ +#define LLC_SAP_EV_TYPE_SIMPLE 1 +#define LLC_SAP_EV_TYPE_CONDITION 2 +#define LLC_SAP_EV_TYPE_PRIM 3 +#define LLC_SAP_EV_TYPE_PDU 4 /* command/response PDU */ +#define LLC_SAP_EV_TYPE_ACK_TMR 5 +#define LLC_SAP_EV_TYPE_RPT_STATUS 6 + +#define LLC_SAP_EV_ACTIVATION_REQ 1 +#define LLC_SAP_EV_RX_UI 2 +#define LLC_SAP_EV_UNITDATA_REQ 3 +#define LLC_SAP_EV_XID_REQ 4 +#define LLC_SAP_EV_RX_XID_C 5 +#define LLC_SAP_EV_RX_XID_R 6 +#define LLC_SAP_EV_TEST_REQ 7 +#define LLC_SAP_EV_RX_TEST_C 8 +#define LLC_SAP_EV_RX_TEST_R 9 +#define LLC_SAP_EV_DEACTIVATION_REQ 10 + +/* Interfaces for various types of supported events */ +struct llc_sap_ev_simple_if { + u8 ev; +}; + +struct llc_prim_if_block; + +struct llc_sap_ev_prim_if { + u8 prim; /* connect, disconnect, reset, ... */ + u8 type; /* request, indicate, response, conf */ + struct llc_prim_if_block *data; +}; + +struct llc_sap_ev_pdu_if { + u8 ev; + u8 reason; + struct sk_buff *skb; +}; + +struct llc_sap_ev_tmr_if { + void *timer_specific; +}; + +struct llc_sap_ev_rpt_sts_if { + u8 status; +}; + +union llc_sap_ev_if { + struct llc_sap_ev_simple_if a; /* 'a' for simple, easy ... */ + struct llc_sap_ev_prim_if prim; + struct llc_sap_ev_pdu_if pdu; + struct llc_sap_ev_tmr_if tmr; + struct llc_sap_ev_rpt_sts_if rsts; /* report status */ +}; + +struct llc_prim_if_block; + +struct llc_sap_state_ev { + u8 type; + u8 ind_cfm_flag; + struct llc_prim_if_block *prim; + union llc_sap_ev_if data; +}; + +struct llc_sap; + +typedef int (*llc_sap_ev_t)(struct llc_sap *sap, struct llc_sap_state_ev *ev); + +extern int llc_sap_ev_activation_req(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_ev_rx_ui(struct llc_sap *sap, struct llc_sap_state_ev *ev); +extern int llc_sap_ev_unitdata_req(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_ev_xid_req(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_ev_rx_xid_c(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_ev_rx_xid_r(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_ev_test_req(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_ev_rx_test_c(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_ev_rx_test_r(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +extern int llc_sap_ev_deactivation_req(struct llc_sap *sap, + struct llc_sap_state_ev *ev); +#endif /* LLC_S_EV_H */ Index: kernel-acme/include/net/llc_s_st.h diff -u /dev/null kernel-acme/include/net/llc_s_st.h:1.1.12.1 --- /dev/null Sat Dec 22 02:21:03 2001 +++ kernel-acme/include/net/llc_s_st.h Thu Nov 29 20:36:54 2001 @@ -0,0 +1,34 @@ +#ifndef LLC_S_ST_H +#define LLC_S_ST_H +/* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +/* Defines SAP component states */ + +#define LLC_SAP_STATE_INACTIVE 1 +#define LLC_SAP_STATE_ACTIVE 2 +#define LLC_NBR_SAP_STATES 2 /* size of state table */ +/* structures and types */ +/* SAP state table structure */ +struct llc_sap_state_trans { + llc_sap_ev_t ev; + u8 next_state; + llc_sap_action_t *ev_actions; +}; + +struct llc_sap_state { + u8 curr_state; + struct llc_sap_state_trans **transitions; +}; + +/* only access to SAP state table */ +extern struct llc_sap_state llc_sap_state_table[LLC_NBR_SAP_STATES]; +#endif /* LLC_S_ST_H */ Index: kernel-acme/include/net/llc_sap.h diff -u /dev/null kernel-acme/include/net/llc_sap.h:1.1.12.2 --- /dev/null Sat Dec 22 02:21:03 2001 +++ kernel-acme/include/net/llc_sap.h Tue Dec 11 00:26:44 2001 @@ -0,0 +1,42 @@ +#ifndef LLC_SAP_H +#define LLC_SAP_H +/* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +/* Defines the SAP component */ +struct llc_sap { + u8 state; + struct llc_station *parent_station; + u8 p_bit; /* only lowest-order bit used */ + u8 f_bit; /* only lowest-order bit used */ + llc_prim_call_t req; /* provided by LLC layer */ + llc_prim_call_t resp; /* provided by LLC layer */ + llc_prim_call_t ind; /* provided by network layer */ + llc_prim_call_t conf; /* provided by network layer */ + struct llc_addr laddr; /* SAP value in this 'lsap' */ + struct list_head node; /* entry in station sap_list */ + struct { + spinlock_t lock; + struct list_head list; + } sk_list; /* LLC sockets this one manages */ + struct sk_buff_head mac_pdu_q; /* PDUs ready to send to MAC */ +}; +struct llc_sap_state_ev; + +extern void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk); +extern void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk); +extern void llc_sap_send_ev(struct llc_sap *sap, struct llc_sap_state_ev *ev); +extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb, + struct llc_sap_state_ev *ev); +extern void llc_sap_send_pdu(struct llc_sap *sap, struct sk_buff *skb); +extern struct llc_sap_state_ev *llc_sap_alloc_ev(struct llc_sap *sap); +#endif /* LLC_SAP_H */ Index: kernel-acme/include/net/llc_stat.h diff -u /dev/null kernel-acme/include/net/llc_stat.h:1.1.12.1 --- /dev/null Sat Dec 22 02:21:03 2001 +++ kernel-acme/include/net/llc_stat.h Thu Nov 29 20:36:54 2001 @@ -0,0 +1,35 @@ +#ifndef LLC_STAT_H +#define LLC_STAT_H +/* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +/* Station component state table */ +/* Station component states */ +#define LLC_STATION_STATE_DOWN 1 /* initial state */ +#define LLC_STATION_STATE_DUP_ADDR_CHK 2 +#define LLC_STATION_STATE_UP 3 + +#define LLC_NBR_STATION_STATES 3 /* size of state table */ + +/* Station component state table structure */ +struct llc_station_state_trans { + llc_station_ev_t ev; + u8 next_state; + llc_station_action_t *ev_actions; +}; + +struct llc_station_state { + u8 curr_state; + struct llc_station_state_trans **transitions; +}; + +extern struct llc_station_state llc_station_state_table[LLC_NBR_STATION_STATES]; +#endif /* LLC_STAT_H */ Index: kernel-acme/include/net/netrom.h diff -u kernel-acme/include/net/netrom.h:1.1.1.1 kernel-acme/include/net/netrom.h:1.1.1.1.12.2 --- kernel-acme/include/net/netrom.h:1.1.1.1 Tue Jun 26 17:33:58 2001 +++ kernel-acme/include/net/netrom.h Mon Dec 17 15:04:51 2001 @@ -74,6 +74,8 @@ struct sock *sk; /* Backlink to socket */ } nr_cb; +#define NR_SK(__sk) ((nr_cb *)(__sk)->protinfo) + struct nr_neigh { struct nr_neigh *next; ax25_address callsign; Index: kernel-acme/include/net/p8022.h diff -u kernel-acme/include/net/p8022.h:1.1.1.1 kernel-acme/include/net/p8022.h:1.1.1.1.12.1 --- kernel-acme/include/net/p8022.h:1.1.1.1 Tue Jun 26 17:33:57 2001 +++ kernel-acme/include/net/p8022.h Thu Nov 29 20:36:54 2001 @@ -1,7 +1,9 @@ #ifndef _NET_P8022_H #define _NET_P8022_H - -extern struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *)); +extern struct datalink_proto *register_8022_client(unsigned char type, + int (*rcvfunc) + (struct sk_buff *, + struct net_device *, + struct packet_type *)); extern void unregister_8022_client(unsigned char type); - #endif Index: kernel-acme/include/net/rose.h diff -u kernel-acme/include/net/rose.h:1.1.1.1 kernel-acme/include/net/rose.h:1.1.1.1.12.2 --- kernel-acme/include/net/rose.h:1.1.1.1 Tue Jun 26 17:33:58 2001 +++ kernel-acme/include/net/rose.h Mon Dec 17 15:04:51 2001 @@ -138,6 +138,8 @@ struct sock *sk; /* Backlink to socket */ } rose_cb; +#define ROSE_SK(__sk) ((rose_cb *)(__sk)->protinfo) + /* af_rose.c */ extern ax25_address rose_callsign; extern int sysctl_rose_restart_request_timeout; Index: kernel-acme/include/net/route.h diff -u kernel-acme/include/net/route.h:1.1.1.5 kernel-acme/include/net/route.h:1.1.1.5.6.1 --- kernel-acme/include/net/route.h:1.1.1.5 Tue Nov 6 21:35:04 2001 +++ kernel-acme/include/net/route.h Thu Dec 13 23:14:52 2001 @@ -42,7 +42,7 @@ /* RTO_CONN is not used (being alias for 0), but preserved not to break * some modules referring to it. */ -#define RT_CONN_FLAGS(sk) (RT_TOS(sk->protinfo.af_inet.tos) | sk->localroute) +#define RT_CONN_FLAGS(sk) (RT_TOS(IP_SK(sk)->tos) | sk->localroute) struct rt_key { Index: kernel-acme/include/net/sock.h diff -u kernel-acme/include/net/sock.h:1.1.1.4 kernel-acme/include/net/sock.h:1.1.1.4.6.9 --- kernel-acme/include/net/sock.h:1.1.1.4 Tue Nov 6 21:35:05 2001 +++ kernel-acme/include/net/sock.h Fri Dec 21 02:12:13 2001 @@ -24,6 +24,11 @@ * Alan Cox : Eliminate low level recv/recvfrom * David S. Miller : New socket lookup architecture. * Steve Whitehouse: Default routines for sock_ops + * Arnaldo C. Melo : removed net_pinfo, tp_pinfo and made + * protinfo be just a void pointer, as the + * protocol specific parts were moved to + * respective headers and ipv4/v6, etc now + * use private slabcaches for its socks * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -36,69 +41,10 @@ #include #include #include -#include /* struct sockaddr_in */ -#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) -#include /* struct sockaddr_in6 */ -#include /* dest_cache, inet6_options */ -#include -#include /* struct ipv6_mc_socklist */ -#endif - -#if defined(CONFIG_INET) || defined (CONFIG_INET_MODULE) -#include -#endif -#include /* struct tcphdr */ - #include #include /* struct sk_buff */ -#include /* struct inet_protocol */ -#if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE) -#include -#endif -#if defined(CONFIG_WAN_ROUTER) || defined(CONFIG_WAN_ROUTER_MODULE) -#include -#endif - -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) -#include -#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) -#include -#endif -#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) -#include -#endif -#endif - -#if defined(CONFIG_PPPOE) || defined(CONFIG_PPPOE_MODULE) -#include -#include /* struct ppp_channel */ -#endif - -#if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE) -#if defined(CONFIG_SPX) || defined(CONFIG_SPX_MODULE) -#include -#else -#include -#endif /* CONFIG_SPX */ -#endif /* CONFIG_IPX */ -#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) -#include -#endif - -#if defined(CONFIG_DECNET) || defined(CONFIG_DECNET_MODULE) -#include -#endif - -#if defined(CONFIG_IRDA) || defined(CONFIG_IRDA_MODULE) -#include -#endif - -#if defined(CONFIG_ATM) || defined(CONFIG_ATM_MODULE) -struct atm_vcc; -#endif - #ifdef CONFIG_FILTER #include #endif @@ -106,362 +52,12 @@ #include #include - -/* The AF_UNIX specific socket options */ -struct unix_opt { - struct unix_address *addr; - struct dentry * dentry; - struct vfsmount * mnt; - struct semaphore readsem; - struct sock * other; - struct sock ** list; - struct sock * gc_tree; - atomic_t inflight; - rwlock_t lock; - wait_queue_head_t peer_wait; -}; - - -/* Once the IPX ncpd patches are in these are going into protinfo. */ -#if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE) -struct ipx_opt { - ipx_address dest_addr; - ipx_interface *intrfc; - unsigned short port; -#ifdef CONFIG_IPX_INTERN - unsigned char node[IPX_NODE_LEN]; -#endif - unsigned short type; -/* - * To handle special ncp connection-handling sockets for mars_nwe, - * the connection number must be stored in the socket. - */ - unsigned short ipx_ncp_conn; -}; -#endif - -#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) -struct ipv6_pinfo { - struct in6_addr saddr; - struct in6_addr rcv_saddr; - struct in6_addr daddr; - struct in6_addr *daddr_cache; - - __u32 flow_label; - __u32 frag_size; - int hop_limit; - int mcast_hops; - int mcast_oif; - - /* pktoption flags */ - union { - struct { - __u8 srcrt:2, - rxinfo:1, - rxhlim:1, - hopopts:1, - dstopts:1, - authhdr:1, - rxflow:1; - } bits; - __u8 all; - } rxopt; - - /* sockopt flags */ - __u8 mc_loop:1, - recverr:1, - sndflow:1, - pmtudisc:2; - - struct ipv6_mc_socklist *ipv6_mc_list; - struct ipv6_fl_socklist *ipv6_fl_list; - __u32 dst_cookie; - - struct ipv6_txoptions *opt; - struct sk_buff *pktoptions; -}; - -struct raw6_opt { - __u32 checksum; /* perform checksum */ - __u32 offset; /* checksum offset */ - - struct icmp6_filter filter; -}; - -#endif /* IPV6 */ - -#if defined(CONFIG_INET) || defined(CONFIG_INET_MODULE) -struct raw_opt { - struct icmp_filter filter; -}; -#endif - -#if defined(CONFIG_INET) || defined (CONFIG_INET_MODULE) -struct inet_opt -{ - int ttl; /* TTL setting */ - int tos; /* TOS */ - unsigned cmsg_flags; - struct ip_options *opt; - unsigned char hdrincl; /* Include headers ? */ - __u8 mc_ttl; /* Multicasting TTL */ - __u8 mc_loop; /* Loopback */ - unsigned recverr : 1, - freebind : 1; - __u16 id; /* ID counter for DF pkts */ - __u8 pmtudisc; - int mc_index; /* Multicast device index */ - __u32 mc_addr; - struct ip_mc_socklist *mc_list; /* Group array */ -}; -#endif - -#if defined(CONFIG_PPPOE) || defined (CONFIG_PPPOE_MODULE) -struct pppoe_opt -{ - struct net_device *dev; /* device associated with socket*/ - struct pppoe_addr pa; /* what this socket is bound to*/ - struct sockaddr_pppox relay; /* what socket data will be - relayed to (PPPoE relaying) */ -}; - -struct pppox_opt -{ - struct ppp_channel chan; - struct sock *sk; - struct pppox_opt *next; /* for hash table */ - union { - struct pppoe_opt pppoe; - } proto; -}; -#define pppoe_dev proto.pppoe.dev -#define pppoe_pa proto.pppoe.pa -#define pppoe_relay proto.pppoe.relay -#endif - -/* This defines a selective acknowledgement block. */ -struct tcp_sack_block { - __u32 start_seq; - __u32 end_seq; -}; - -struct tcp_opt { - int tcp_header_len; /* Bytes of tcp header to send */ - -/* - * Header prediction flags - * 0x5?10 << 16 + snd_wnd in net byte order - */ - __u32 pred_flags; - -/* - * RFC793 variables by their proper names. This means you can - * read the code and the spec side by side (and laugh ...) - * See RFC793 and RFC1122. The RFC writes these in capitals. - */ - __u32 rcv_nxt; /* What we want to receive next */ - __u32 snd_nxt; /* Next sequence we send */ - - __u32 snd_una; /* First byte we want an ack for */ - __u32 snd_sml; /* Last byte of the most recently transmitted small packet */ - __u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */ - __u32 lsndtime; /* timestamp of last sent data packet (for restart window) */ - - /* Delayed ACK control data */ - struct { - __u8 pending; /* ACK is pending */ - __u8 quick; /* Scheduled number of quick acks */ - __u8 pingpong; /* The session is interactive */ - __u8 blocked; /* Delayed ACK was blocked by socket lock*/ - __u32 ato; /* Predicted tick of soft clock */ - unsigned long timeout; /* Currently scheduled timeout */ - __u32 lrcvtime; /* timestamp of last received data packet*/ - __u16 last_seg_size; /* Size of last incoming segment */ - __u16 rcv_mss; /* MSS used for delayed ACK decisions */ - } ack; - - /* Data for direct copy to user */ - struct { - struct sk_buff_head prequeue; - int memory; - struct task_struct *task; - struct iovec *iov; - int len; - } ucopy; - - __u32 snd_wl1; /* Sequence for window update */ - __u32 snd_wnd; /* The window we expect to receive */ - __u32 max_window; /* Maximal window ever seen from peer */ - __u32 pmtu_cookie; /* Last pmtu seen by socket */ - __u16 mss_cache; /* Cached effective mss, not including SACKS */ - __u16 mss_clamp; /* Maximal mss, negotiated at connection setup */ - __u16 ext_header_len; /* Network protocol overhead (IP/IPv6 options) */ - __u8 ca_state; /* State of fast-retransmit machine */ - __u8 retransmits; /* Number of unrecovered RTO timeouts. */ - - __u8 reordering; /* Packet reordering metric. */ - __u8 queue_shrunk; /* Write queue has been shrunk recently.*/ - __u8 defer_accept; /* User waits for some data after accept() */ - -/* RTT measurement */ - __u8 backoff; /* backoff */ - __u32 srtt; /* smothed round trip time << 3 */ - __u32 mdev; /* medium deviation */ - __u32 mdev_max; /* maximal mdev for the last rtt period */ - __u32 rttvar; /* smoothed mdev_max */ - __u32 rtt_seq; /* sequence number to update rttvar */ - __u32 rto; /* retransmit timeout */ - - __u32 packets_out; /* Packets which are "in flight" */ - __u32 left_out; /* Packets which leaved network */ - __u32 retrans_out; /* Retransmitted packets out */ - - /* - * Slow start and congestion control (see also Nagle, and Karn & Partridge) - */ - __u32 snd_ssthresh; /* Slow start size threshold */ - __u32 snd_cwnd; /* Sending congestion window */ - __u16 snd_cwnd_cnt; /* Linear increase counter */ - __u16 snd_cwnd_clamp; /* Do not allow snd_cwnd to grow above this */ - __u32 snd_cwnd_used; - __u32 snd_cwnd_stamp; - - /* Two commonly used timers in both sender and receiver paths. */ - unsigned long timeout; - struct timer_list retransmit_timer; /* Resend (no ack) */ - struct timer_list delack_timer; /* Ack delay */ - - struct sk_buff_head out_of_order_queue; /* Out of order segments go here */ - - struct tcp_func *af_specific; /* Operations which are AF_INET{4,6} specific */ - struct sk_buff *send_head; /* Front of stuff to transmit */ - struct page *sndmsg_page; /* Cached page for sendmsg */ - u32 sndmsg_off; /* Cached offset for sendmsg */ - - __u32 rcv_wnd; /* Current receiver window */ - __u32 rcv_wup; /* rcv_nxt on last window update sent */ - __u32 write_seq; /* Tail(+1) of data held in tcp send buffer */ - __u32 pushed_seq; /* Last pushed seq, required to talk to windows */ - __u32 copied_seq; /* Head of yet unread data */ -/* - * Options received (usually on last packet, some only on SYN packets). - */ - char tstamp_ok, /* TIMESTAMP seen on SYN packet */ - wscale_ok, /* Wscale seen on SYN packet */ - sack_ok; /* SACK seen on SYN packet */ - char saw_tstamp; /* Saw TIMESTAMP on last packet */ - __u8 snd_wscale; /* Window scaling received from sender */ - __u8 rcv_wscale; /* Window scaling to send to receiver */ - __u8 nonagle; /* Disable Nagle algorithm? */ - __u8 keepalive_probes; /* num of allowed keep alive probes */ - -/* PAWS/RTTM data */ - __u32 rcv_tsval; /* Time stamp value */ - __u32 rcv_tsecr; /* Time stamp echo reply */ - __u32 ts_recent; /* Time stamp to echo next */ - long ts_recent_stamp;/* Time we stored ts_recent (for aging) */ - -/* SACKs data */ - __u16 user_mss; /* mss requested by user in ioctl */ - __u8 dsack; /* D-SACK is scheduled */ - __u8 eff_sacks; /* Size of SACK array to send with next packet */ - struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */ - struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/ - - __u32 window_clamp; /* Maximal window to advertise */ - __u32 rcv_ssthresh; /* Current window clamp */ - __u8 probes_out; /* unanswered 0 window probes */ - __u8 num_sacks; /* Number of SACK blocks */ - __u16 advmss; /* Advertised MSS */ - - __u8 syn_retries; /* num of allowed syn retries */ - __u8 ecn_flags; /* ECN status bits. */ - __u16 prior_ssthresh; /* ssthresh saved at recovery start */ - __u32 lost_out; /* Lost packets */ - __u32 sacked_out; /* SACK'd packets */ - __u32 fackets_out; /* FACK'd packets */ - __u32 high_seq; /* snd_nxt at onset of congestion */ - - __u32 retrans_stamp; /* Timestamp of the last retransmit, - * also used in SYN-SENT to remember stamp of - * the first SYN. */ - __u32 undo_marker; /* tracking retrans started here. */ - int undo_retrans; /* number of undoable retransmissions. */ - __u32 urg_seq; /* Seq of received urgent pointer */ - __u16 urg_data; /* Saved octet of OOB data and control flags */ - __u8 pending; /* Scheduled timer event */ - __u8 urg_mode; /* In urgent mode */ - __u32 snd_up; /* Urgent pointer */ - - /* The syn_wait_lock is necessary only to avoid tcp_get_info having - * to grab the main lock sock while browsing the listening hash - * (otherwise it's deadlock prone). - * This lock is acquired in read mode only from tcp_get_info() and - * it's acquired in write mode _only_ from code that is actively - * changing the syn_wait_queue. All readers that are holding - * the master sock lock don't need to grab this lock in read mode - * too as the syn_wait_queue writes are always protected from - * the main sock lock. - */ - rwlock_t syn_wait_lock; - struct tcp_listen_opt *listen_opt; - - /* FIFO of established children */ - struct open_request *accept_queue; - struct open_request *accept_queue_tail; - - int write_pending; /* A write to socket waits to start. */ - - unsigned int keepalive_time; /* time before keep alive takes place */ - unsigned int keepalive_intvl; /* time interval between keep alive probes */ - int linger2; - - unsigned long last_synq_overflow; -}; - - -/* * This structure really needs to be cleaned up. * Most of it is for TCP, and not used by any of * the other protocols. */ -/* - * The idea is to start moving to a newer struct gradualy - * - * IMHO the newer struct should have the following format: - * - * struct sock { - * sockmem [mem, proto, callbacks] - * - * union or struct { - * ax25; - * } ll_pinfo; - * - * union { - * ipv4; - * ipv6; - * ipx; - * netrom; - * rose; - * x25; - * } net_pinfo; - * - * union { - * tcp; - * udp; - * spx; - * netrom; - * } tp_pinfo; - * - * } - * - * The idea failed because IPv6 transition asssumes dual IP/IPv6 sockets. - * So, net_pinfo is IPv6 are really, and protinfo unifies all another - * private areas. - */ - /* Define this to get the sk->debug debugging facility. */ #define SOCK_DEBUGGING #ifdef SOCK_DEBUGGING @@ -567,26 +163,6 @@ struct proto *prot; -#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) - union { - struct ipv6_pinfo af_inet6; - } net_pinfo; -#endif - - union { - struct tcp_opt af_tcp; -#if defined(CONFIG_INET) || defined (CONFIG_INET_MODULE) - struct raw_opt tp_raw4; -#endif -#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) - struct raw6_opt tp_raw; -#endif /* CONFIG_IPV6 */ -#if defined(CONFIG_SPX) || defined (CONFIG_SPX_MODULE) - struct spx_opt af_spx; -#endif /* CONFIG_SPX */ - - } tp_pinfo; - int err, err_soft; /* Soft holds errors that don't cause failure but are the cause of a persistent failure not just @@ -608,58 +184,15 @@ #endif /* CONFIG_FILTER */ /* This is where all the private (optional) areas that don't - * overlap will eventually live. + * overlap will eventually live. We should have a way to say: hey, + * this protocol has a private slabcache where this instance was + * allocated from, so it doesn't uses protinfo, so we can use a + * unnamed union here to reuse protinfo pointer, that is not used + * for protocols with a private sock slabcache, maybe a flag word? + * for now lets just add the slab pointer ;) */ - union { - void *destruct_hook; - struct unix_opt af_unix; -#if defined(CONFIG_INET) || defined (CONFIG_INET_MODULE) - struct inet_opt af_inet; -#endif -#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) - struct atalk_sock af_at; -#endif -#if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE) - struct ipx_opt af_ipx; -#endif -#if defined (CONFIG_DECNET) || defined(CONFIG_DECNET_MODULE) - struct dn_scp dn; -#endif -#if defined (CONFIG_PACKET) || defined(CONFIG_PACKET_MODULE) - struct packet_opt *af_packet; -#endif -#if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE) - x25_cb *x25; -#endif -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) - ax25_cb *ax25; -#endif -#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) - nr_cb *nr; -#endif -#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) - rose_cb *rose; -#endif -#if defined(CONFIG_PPPOE) || defined(CONFIG_PPPOE_MODULE) - struct pppox_opt *pppox; -#endif -#ifdef CONFIG_NETLINK - struct netlink_opt *af_netlink; -#endif -#if defined(CONFIG_ECONET) || defined(CONFIG_ECONET_MODULE) - struct econet_opt *af_econet; -#endif -#if defined(CONFIG_ATM) || defined(CONFIG_ATM_MODULE) - struct atm_vcc *af_atm; -#endif -#if defined(CONFIG_IRDA) || defined(CONFIG_IRDA_MODULE) - struct irda_sock *irda; -#endif -#if defined(CONFIG_WAN_ROUTER) || defined(CONFIG_WAN_ROUTER_MODULE) - struct wanpipe_opt *af_wanpipe; -#endif - } protinfo; - + void *protinfo; + kmem_cache_t *slab; /* This part is used for the timeout functions. */ struct timer_list timer; /* This is the sock cleanup timer. */ @@ -805,7 +338,8 @@ #define bh_lock_sock(__sk) spin_lock(&((__sk)->lock.slock)) #define bh_unlock_sock(__sk) spin_unlock(&((__sk)->lock.slock)) -extern struct sock * sk_alloc(int family, int priority, int zero_it); +extern struct sock * sk_alloc(int family, int priority, int zero_it, + kmem_cache_t *slab); extern void sk_free(struct sock *sk); extern struct sk_buff *sock_wmalloc(struct sock *sk, Index: kernel-acme/include/net/spx.h diff -u kernel-acme/include/net/spx.h:1.1.1.1 kernel-acme/include/net/spx.h:1.1.1.1.12.1 --- kernel-acme/include/net/spx.h:1.1.1.1 Tue Jun 26 17:33:57 2001 +++ kernel-acme/include/net/spx.h Mon Dec 17 03:55:25 2001 @@ -48,6 +48,8 @@ struct sk_buff_head retransmit_queue; }; +#define SPX_PINFO(__sk) ((struct spx_opt *)(((struct sock *)(__sk)) + 1)) + /* Packet connectino control defines */ #define CCTL_SPXII_XHD 0x01 /* SPX2 extended header */ #define CCTL_SPX_UNKNOWN 0x02 /* Unknown (unused ??) */ Index: kernel-acme/include/net/tcp.h diff -u kernel-acme/include/net/tcp.h:1.1.1.4 kernel-acme/include/net/tcp.h:1.1.1.4.6.3 --- kernel-acme/include/net/tcp.h:1.1.1.4 Tue Nov 6 19:00:14 2001 +++ kernel-acme/include/net/tcp.h Fri Dec 21 02:12:13 2001 @@ -29,6 +29,9 @@ #include #include #include +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +#include +#endif /* This is for all connections with a full identity, no wildcards. * New scheme, half the table is for TIME_WAIT, the other half is @@ -134,6 +137,9 @@ #define tcp_lhash_wait (tcp_hashinfo.__tcp_lhash_wait) #define tcp_portalloc_lock (tcp_hashinfo.__tcp_portalloc_lock) +/* SLAB cache for TCP socks */ +extern kmem_cache_t *tcp_sk_cachep; + extern kmem_cache_t *tcp_bucket_cachep; extern struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head, unsigned short snum); @@ -245,8 +251,8 @@ #define TCP_IPV6_MATCH(__sk, __saddr, __daddr, __ports, __dif) \ (((*((__u32 *)&((__sk)->dport)))== (__ports)) && \ ((__sk)->family == AF_INET6) && \ - !ipv6_addr_cmp(&(__sk)->net_pinfo.af_inet6.daddr, (__saddr)) && \ - !ipv6_addr_cmp(&(__sk)->net_pinfo.af_inet6.rcv_saddr, (__daddr)) && \ + !ipv6_addr_cmp(&IP6_PINFO(__sk)->daddr, (__saddr)) && \ + !ipv6_addr_cmp(&IP6_PINFO(__sk)->rcv_saddr, (__daddr)) && \ (!((__sk)->bound_dev_if) || ((__sk)->bound_dev_if == (__dif)))) /* These can have wildcards, don't try too hard. */ @@ -824,7 +830,7 @@ static inline void tcp_clear_xmit_timer(struct sock *sk, int what) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); switch (what) { case TCP_TIME_RETRANS: @@ -859,7 +865,7 @@ */ static inline void tcp_reset_xmit_timer(struct sock *sk, int what, unsigned long when) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); if (when > TCP_RTO_MAX) { #ifdef TCP_DEBUG @@ -895,7 +901,7 @@ static __inline__ unsigned int tcp_current_mss(struct sock *sk) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); struct dst_entry *dst = __sk_dst_get(sk); int mss_now = tp->mss_cache; @@ -918,7 +924,7 @@ static inline void tcp_initialize_rcv_mss(struct sock *sk) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); unsigned int hint = min(tp->advmss, tp->mss_cache); hint = min(hint, tp->rcv_wnd/2); @@ -1321,7 +1327,7 @@ */ static __inline__ int tcp_prequeue(struct sock *sk, struct sk_buff *skb) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); if (tp->ucopy.task) { __skb_queue_tail(&tp->ucopy.prequeue, skb); @@ -1572,7 +1578,7 @@ static inline void tcp_acceptq_queue(struct sock *sk, struct open_request *req, struct sock *child) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); req->sk = child; tcp_acceptq_added(sk); @@ -1598,7 +1604,7 @@ static inline void tcp_synq_removed(struct sock *sk, struct open_request *req) { - struct tcp_listen_opt *lopt = sk->tp_pinfo.af_tcp.listen_opt; + struct tcp_listen_opt *lopt = TCP_PINFO(sk)->listen_opt; if (--lopt->qlen == 0) tcp_delete_keepalive_timer(sk); @@ -1608,7 +1614,7 @@ static inline void tcp_synq_added(struct sock *sk) { - struct tcp_listen_opt *lopt = sk->tp_pinfo.af_tcp.listen_opt; + struct tcp_listen_opt *lopt = TCP_PINFO(sk)->listen_opt; if (lopt->qlen++ == 0) tcp_reset_keepalive_timer(sk, TCP_TIMEOUT_INIT); @@ -1617,17 +1623,17 @@ static inline int tcp_synq_len(struct sock *sk) { - return sk->tp_pinfo.af_tcp.listen_opt->qlen; + return TCP_PINFO(sk)->listen_opt->qlen; } static inline int tcp_synq_young(struct sock *sk) { - return sk->tp_pinfo.af_tcp.listen_opt->qlen_young; + return TCP_PINFO(sk)->listen_opt->qlen_young; } static inline int tcp_synq_is_full(struct sock *sk) { - return tcp_synq_len(sk)>>sk->tp_pinfo.af_tcp.listen_opt->max_qlen_log; + return tcp_synq_len(sk) >> TCP_PINFO(sk)->listen_opt->max_qlen_log; } static inline void tcp_synq_unlink(struct tcp_opt *tp, struct open_request *req, @@ -1641,7 +1647,7 @@ static inline void tcp_synq_drop(struct sock *sk, struct open_request *req, struct open_request **prev) { - tcp_synq_unlink(&sk->tp_pinfo.af_tcp, req, prev); + tcp_synq_unlink(TCP_PINFO(sk), req, prev); tcp_synq_removed(sk, req); tcp_openreq_free(req); } @@ -1667,7 +1673,7 @@ static inline void tcp_free_skb(struct sock *sk, struct sk_buff *skb) { - sk->tp_pinfo.af_tcp.queue_shrunk = 1; + TCP_PINFO(sk)->queue_shrunk = 1; sk->wmem_queued -= skb->truesize; sk->forward_alloc += skb->truesize; __kfree_skb(skb); Index: kernel-acme/include/net/udp.h diff -u kernel-acme/include/net/udp.h:1.1.1.1 kernel-acme/include/net/udp.h:1.1.1.1.12.1 --- kernel-acme/include/net/udp.h:1.1.1.1 Tue Jun 26 17:33:57 2001 +++ kernel-acme/include/net/udp.h Fri Dec 21 13:19:21 2001 @@ -74,4 +74,6 @@ #define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field) #define UDP_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_statistics, field) +#define UDP_SK_SIZE (sizeof(struct sock) + sizeof(struct inet_opt)) + #endif /* _UDP_H */ Index: kernel-acme/include/net/x25.h diff -u kernel-acme/include/net/x25.h:1.1.1.1 kernel-acme/include/net/x25.h:1.1.1.1.12.2 --- kernel-acme/include/net/x25.h:1.1.1.1 Tue Jun 26 17:33:57 2001 +++ kernel-acme/include/net/x25.h Mon Dec 17 15:04:51 2001 @@ -139,6 +139,8 @@ unsigned long vc_facil_mask; /* inc_call facilities mask */ } x25_cb; +#define X25_SK(__sk) ((x25_cb *)(__sk)->protinfo) + /* af_x25.c */ extern int sysctl_x25_restart_request_timeout; extern int sysctl_x25_call_request_timeout; Index: kernel-acme/include/net/irda/irda.h diff -u kernel-acme/include/net/irda/irda.h:1.1.1.2 kernel-acme/include/net/irda/irda.h:1.1.1.2.4.2 --- kernel-acme/include/net/irda/irda.h:1.1.1.2 Fri Nov 23 22:35:42 2001 +++ kernel-acme/include/net/irda/irda.h Mon Dec 17 15:04:51 2001 @@ -168,6 +168,8 @@ LOCAL_FLOW rx_flow; }; +#define IRDA_SK(__sk) ((struct irda_sock *)(__sk)->protinfo) + /* * This type is used by the protocols that transmit 16 bits words in * little endian format. A little endian machine stores MSB of word in Index: kernel-acme/net/Config.in diff -u kernel-acme/net/Config.in:1.1.1.2 kernel-acme/net/Config.in:1.1.1.2.6.1 --- kernel-acme/net/Config.in:1.1.1.2 Tue Nov 6 21:30:30 2001 +++ kernel-acme/net/Config.in Thu Nov 29 20:36:54 2001 @@ -65,11 +65,12 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25 tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB - bool '802.2 LLC (EXPERIMENTAL)' CONFIG_LLC + tristate 'ANSI/IEEE 802.2 Data link layer protocol' CONFIG_LLC + if [ "$CONFIG_LLC" != "n" ]; then + bool ' ANSI/IEEE 802.2 Data link layer User Interface SAPs' CONFIG_LLC_UI + tristate 'The NETBEUI protocol' CONFIG_NETBEUI + fi bool 'Frame Diverter (EXPERIMENTAL)' CONFIG_NET_DIVERT -# if [ "$CONFIG_LLC" = "y" ]; then -# bool ' Netbeui (EXPERIMENTAL)' CONFIG_NETBEUI -# fi if [ "$CONFIG_INET" = "y" ]; then tristate 'Acorn Econet/AUN protocols (EXPERIMENTAL)' CONFIG_ECONET fi Index: kernel-acme/net/Makefile diff -u kernel-acme/net/Makefile:1.1.1.3 kernel-acme/net/Makefile:1.1.1.3.6.1 --- kernel-acme/net/Makefile:1.1.1.3 Tue Nov 6 21:30:30 2001 +++ kernel-acme/net/Makefile Thu Nov 29 20:36:54 2001 @@ -7,7 +7,7 @@ O_TARGET := network.o -mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched +mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched llc netbeui export-objs := netsyms.o subdir-y := core ethernet @@ -46,7 +46,8 @@ subdir-$(CONFIG_DECNET) += decnet subdir-$(CONFIG_ECONET) += econet subdir-$(CONFIG_VLAN_8021Q) += 8021q - +subdir-$(CONFIG_LLC) += llc +subdir-$(CONFIG_NETBEUI) += netbeui obj-y := socket.o $(join $(subdir-y), $(patsubst %,/%.o,$(notdir $(subdir-y)))) ifeq ($(CONFIG_NET),y) Index: kernel-acme/net/netsyms.c diff -u kernel-acme/net/netsyms.c:1.1.1.6 kernel-acme/net/netsyms.c:1.1.1.6.6.1 --- kernel-acme/net/netsyms.c:1.1.1.6 Tue Nov 6 21:30:30 2001 +++ kernel-acme/net/netsyms.c Thu Nov 29 20:36:54 2001 @@ -459,6 +459,7 @@ #endif /* CONFIG_INET */ #ifdef CONFIG_TR +EXPORT_SYMBOL(tr_source_route); EXPORT_SYMBOL(tr_type_trans); #endif @@ -477,6 +478,7 @@ EXPORT_SYMBOL(__dev_get_by_index); EXPORT_SYMBOL(dev_get_by_name); EXPORT_SYMBOL(__dev_get_by_name); +EXPORT_SYMBOL(dev_getbyhwaddr); EXPORT_SYMBOL(netdev_finish_unregister); EXPORT_SYMBOL(netdev_set_master); EXPORT_SYMBOL(eth_type_trans); Index: kernel-acme/net/socket.c diff -u kernel-acme/net/socket.c:1.1.1.6 kernel-acme/net/socket.c:1.1.1.6.6.2 --- kernel-acme/net/socket.c:1.1.1.6 Tue Nov 6 20:13:36 2001 +++ kernel-acme/net/socket.c Fri Dec 21 02:12:13 2001 @@ -133,7 +133,7 @@ * The protocol list. Each protocol is registered in here. */ -static struct net_proto_family *net_families[NPROTO]; +struct net_proto_family *net_families[NPROTO]; #ifdef CONFIG_SMP static atomic_t net_family_lockct = ATOMIC_INIT(0); Index: kernel-acme/net/802/p8022.c diff -u kernel-acme/net/802/p8022.c:1.1.1.1 kernel-acme/net/802/p8022.c:1.1.1.1.12.1 --- kernel-acme/net/802/p8022.c:1.1.1.1 Tue Jun 26 17:28:54 2001 +++ kernel-acme/net/802/p8022.c Thu Nov 29 20:36:54 2001 @@ -11,11 +11,10 @@ * matches. The control byte is ignored and handling of such items * is up to the routine passed the frame. * - * Unlike the 802.3 datalink we have a list of 802.2 entries as there - * are multiple protocols to demux. The list is currently short (3 or - * 4 entries at most). The current demux assumes this. + * Unlike the 802.3 datalink we have a list of 802.2 entries as + * there are multiple protocols to demux. The list is currently + * short (3 or 4 entries at most). The current demux assumes this. */ - #include #include #include @@ -25,8 +24,13 @@ #include #include -static struct datalink_proto *p8022_list = NULL; +extern void llc_register_sap(unsigned char sap, + int (*rcvfunc)(struct sk_buff *, + struct net_device *, + struct packet_type *)); +extern void llc_unregister_sap(unsigned char sap); +static struct datalink_proto *p8022_list; /* * We don't handle the loopback SAP stuff, the extended * 802.2 command set, multicast SAP identifiers and non UI @@ -34,91 +38,68 @@ * IP and Appletalk phase 2. See the llc_* routines for * support libraries if your protocol needs these. */ - static struct datalink_proto *find_8022_client(unsigned char type) { - struct datalink_proto *proto; - - for (proto = p8022_list; - ((proto != NULL) && (*(proto->type) != type)); - proto = proto->next) - ; + struct datalink_proto *proto = p8022_list; + while (proto && *(proto->type) != type) + proto = proto->next; return proto; } -int p8022_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) +int p8022_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt) { - struct datalink_proto *proto; + struct datalink_proto *proto; + int rc = 0; proto = find_8022_client(*(skb->h.raw)); - if (proto != NULL) - { - skb->h.raw += 3; - skb->nh.raw += 3; - skb_pull(skb,3); - return proto->rcvfunc(skb, dev, pt); + if (!proto) { + skb->sk = NULL; + kfree_skb(skb); + goto out; } - - skb->sk = NULL; - kfree_skb(skb); - return 0; + skb->h.raw += 3; + skb->nh.raw += 3; + skb_pull(skb, 3); + rc = proto->rcvfunc(skb, dev, pt); +out: return rc; } static void p8022_datalink_header(struct datalink_proto *dl, - struct sk_buff *skb, unsigned char *dest_node) + struct sk_buff *skb, unsigned char *dest_node) { - struct net_device *dev = skb->dev; - unsigned char *rawp; + struct net_device *dev = skb->dev; + unsigned char *rawp = skb_push(skb, 3); - rawp = skb_push(skb,3); *rawp++ = dl->type[0]; *rawp++ = dl->type[0]; - *rawp = 0x03; /* UI */ + *rawp = 0x03; /* UI */ dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len); } - -static struct packet_type p8022_packet_type = -{ - 0, /* MUTTER ntohs(ETH_P_8022),*/ - NULL, /* All devices */ - p8022_rcv, - NULL, - NULL, -}; - -EXPORT_SYMBOL(register_8022_client); -EXPORT_SYMBOL(unregister_8022_client); - -static int __init p8022_init(void) -{ - p8022_packet_type.type=htons(ETH_P_802_2); - dev_add_pack(&p8022_packet_type); - return 0; -} -module_init(p8022_init); - -struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *)) -{ - struct datalink_proto *proto; - - if (find_8022_client(type) != NULL) - return NULL; - - proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC); - if (proto != NULL) { - proto->type[0] = type; - proto->type_len = 1; - proto->rcvfunc = rcvfunc; - proto->header_length = 3; - proto->datalink_header = p8022_datalink_header; - proto->string_name = "802.2"; - proto->next = p8022_list; - p8022_list = proto; +struct datalink_proto *register_8022_client(unsigned char type, + int (*rcvfunc)(struct sk_buff *, + struct net_device *, + struct packet_type *)) +{ + struct datalink_proto *proto = NULL; + + if (find_8022_client(type)) + goto out; + proto = kmalloc(sizeof(*proto), GFP_ATOMIC); + if (proto) { + proto->type[0] = type; + proto->type_len = 1; + proto->rcvfunc = rcvfunc; + proto->header_length = 3; + proto->datalink_header = p8022_datalink_header; + proto->string_name = "802.2"; + proto->next = p8022_list; + p8022_list = proto; + llc_register_sap(type, p8022_rcv); } - - return proto; +out: return proto; } void unregister_8022_client(unsigned char type) @@ -128,17 +109,18 @@ save_flags(flags); cli(); - - while ((tmp = *clients) != NULL) - { + while (*clients) { + tmp = *clients; if (tmp->type[0] == type) { *clients = tmp->next; kfree(tmp); + llc_unregister_sap(type); break; - } else { - clients = &tmp->next; } + clients = &tmp->next; } - restore_flags(flags); } + +EXPORT_SYMBOL(register_8022_client); +EXPORT_SYMBOL(unregister_8022_client); Index: kernel-acme/net/802/tr.c diff -u kernel-acme/net/802/tr.c:1.1.1.1 kernel-acme/net/802/tr.c:1.1.1.1.12.1 --- kernel-acme/net/802/tr.c:1.1.1.1 Tue Jun 26 17:28:54 2001 +++ kernel-acme/net/802/tr.c Thu Nov 29 20:36:55 2001 @@ -36,7 +36,8 @@ #include #include -static void tr_source_route(struct sk_buff *skb, struct trh_hdr *trh, struct net_device *dev); +void tr_source_route(struct sk_buff *skb, struct trh_hdr *trh, + struct net_device *dev); static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev); static void rif_check_expire(unsigned long dummy); @@ -65,7 +66,7 @@ * up a lot. */ -rif_cache rif_table[RIF_TABLE_SIZE]={ NULL, }; +rif_cache rif_table[RIF_TABLE_SIZE]; static spinlock_t rif_lock = SPIN_LOCK_UNLOCKED; @@ -230,7 +231,8 @@ * We try to do source routing... */ -static void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct net_device *dev) +void tr_source_route(struct sk_buff *skb, struct trh_hdr *trh, + struct net_device *dev) { int i, slack; unsigned int hash; Index: kernel-acme/net/appletalk/ddp.c diff -u kernel-acme/net/appletalk/ddp.c:1.1.1.3 kernel-acme/net/appletalk/ddp.c:1.1.1.3.8.3 --- kernel-acme/net/appletalk/ddp.c:1.1.1.3 Wed Sep 26 22:00:31 2001 +++ kernel-acme/net/appletalk/ddp.c Fri Dec 21 02:12:13 2001 @@ -152,16 +152,18 @@ spin_lock_bh(&atalk_sockets_lock); for (s = atalk_sockets; s; s = s->next) { - if (to->sat_port != s->protinfo.af_at.src_port) + struct atalk_sock *at = AT_SK(s); + + if (to->sat_port != at->src_port) continue; if (to->sat_addr.s_net == ATADDR_ANYNET && to->sat_addr.s_node == ATADDR_BCAST && - s->protinfo.af_at.src_net == atif->address.s_net) + at->src_net == atif->address.s_net) break; - if (to->sat_addr.s_net == s->protinfo.af_at.src_net && - (to->sat_addr.s_node == s->protinfo.af_at.src_node || + if (to->sat_addr.s_net == at->src_net && + (to->sat_addr.s_node == at->src_node || to->sat_addr.s_node == ATADDR_BCAST || to->sat_addr.s_node == ATADDR_ANYNODE)) break; @@ -170,7 +172,7 @@ * that the node is appropriately set. */ if (to->sat_addr.s_node == ATADDR_ANYNODE && to->sat_addr.s_net != ATADDR_ANYNET && - atif->address.s_node == s->protinfo.af_at.src_node) { + atif->address.s_node == at->src_node) { to->sat_addr.s_node = atif->address.s_node; break; } @@ -192,11 +194,14 @@ struct sock *s; spin_lock_bh(&atalk_sockets_lock); - for (s = atalk_sockets; s; s = s->next) - if (s->protinfo.af_at.src_net == sat->sat_addr.s_net && - s->protinfo.af_at.src_node == sat->sat_addr.s_node && - s->protinfo.af_at.src_port == sat->sat_port) + for (s = atalk_sockets; s; s = s->next) { + struct atalk_sock *at = AT_SK(s); + + if (at->src_net == sat->sat_addr.s_net && + at->src_node == sat->sat_addr.s_node && + at->src_port == sat->sat_port) break; + } if (!s) { /* Wheee, it's free, assign and insert. */ @@ -255,15 +260,14 @@ spin_lock_bh(&atalk_sockets_lock); for (s = atalk_sockets; s; s = s->next) { + struct atalk_sock *at = AT_SK(s); + len += sprintf(buffer + len,"%02X ", s->type); len += sprintf(buffer + len,"%04X:%02X:%02X ", - ntohs(s->protinfo.af_at.src_net), - s->protinfo.af_at.src_node, - s->protinfo.af_at.src_port); + ntohs(at->src_net), at->src_node, at->src_port); len += sprintf(buffer + len,"%04X:%02X:%02X ", - ntohs(s->protinfo.af_at.dest_net), - s->protinfo.af_at.dest_node, - s->protinfo.af_at.dest_port); + ntohs(at->dest_net), at->dest_node, + at->dest_port); len += sprintf(buffer + len,"%08X:%08X ", atomic_read(&s->wmem_alloc), atomic_read(&s->rmem_alloc)); @@ -1112,42 +1116,34 @@ */ static int atalk_create(struct socket *sock, int protocol) { - struct sock *sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, 1); - - if (!sk) - return -ENOMEM; - - switch (sock->type) { - /* - * We permit SOCK_DGRAM and RAW is an extension. It is - * trivial to do and gives you the full ELAP frame. - * Should be handy for CAP 8) - */ - case SOCK_RAW: - case SOCK_DGRAM: - sock->ops = &atalk_dgram_ops; - break; - - case SOCK_STREAM: - /* - * TODO: if you want to implement ADSP, here's the - * place to start - */ - /* - sock->ops = &atalk_stream_ops; - break; - */ - default: - sk_free(sk); - return -ESOCKTNOSUPPORT; - } + struct sock *sk; + struct atalk_sock *at; + int rc = -ESOCKTNOSUPPORT; MOD_INC_USE_COUNT; + /* + * We permit SOCK_DGRAM and RAW is an extension. It is trivial to do + * and gives you the full ELAP frame. Should be handy for CAP 8) + */ + if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM) + goto decmod; + rc = -ENOMEM; + sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, 1, NULL); + if (!sk) + goto decmod; + at = kmalloc(sizeof(*at), GFP_KERNEL); + if (!at) + goto outsk; + rc = 0; + sock->ops = &atalk_dgram_ops; sock_init_data(sock, sk); - sk->destruct = NULL; + AT_SK(sk) = at; /* Checksums on by default */ sk->zapped = 1; - return 0; +out: return rc; +outsk: sk_free(sk); +decmod: MOD_DEC_USE_COUNT; + goto out; } /* Free a socket. No work needed */ @@ -1156,15 +1152,13 @@ struct sock *sk = sock->sk; if (!sk) - return 0; - + goto out; if (!sk->dead) sk->state_change(sk); - sk->dead = 1; sock->sk = NULL; atalk_destroy_socket(sk); - return 0; +out: return 0; } /* @@ -1185,10 +1179,11 @@ sat->sat_port < ATPORT_LAST; sat->sat_port++) { for (s = atalk_sockets; s; s = s->next) { - if (s->protinfo.af_at.src_net == sat->sat_addr.s_net && - s->protinfo.af_at.src_node == - sat->sat_addr.s_node && - s->protinfo.af_at.src_port == sat->sat_port) + struct atalk_sock *at = AT_SK(s); + + if (at->src_net == sat->sat_addr.s_net && + at->src_node == sat->sat_addr.s_node && + at->src_port == sat->sat_port) goto try_next_port; } @@ -1198,7 +1193,7 @@ atalk_sockets->pprev = &sk->next; atalk_sockets = sk; sk->pprev = &atalk_sockets; - sk->protinfo.af_at.src_port = sat->sat_port; + AT_SK(sk)->src_port = sat->sat_port; retval = 0; goto out; @@ -1213,6 +1208,7 @@ static int atalk_autobind(struct sock *sk) { + struct atalk_sock *at = AT_SK(sk); struct sockaddr_at sat; int n; struct at_addr *ap = atalk_find_primary(); @@ -1220,8 +1216,8 @@ if (!ap || ap->s_net == htons(ATADDR_ANYNET)) return -EADDRNOTAVAIL; - sk->protinfo.af_at.src_net = sat.sat_addr.s_net = ap->s_net; - sk->protinfo.af_at.src_node = sat.sat_addr.s_node = ap->s_node; + at->src_net = sat.sat_addr.s_net = ap->s_net; + at->src_node = sat.sat_addr.s_node = ap->s_node; n = atalk_pick_and_bind_port(sk, &sat); if (n < 0) @@ -1236,6 +1232,7 @@ { struct sockaddr_at *addr = (struct sockaddr_at *)uaddr; struct sock *sk = sock->sk; + struct atalk_sock *at = AT_SK(sk); if (!sk->zapped || addr_len != sizeof(struct sockaddr_at)) return -EINVAL; @@ -1249,15 +1246,15 @@ if (!ap) return -EADDRNOTAVAIL; - sk->protinfo.af_at.src_net = addr->sat_addr.s_net = ap->s_net; - sk->protinfo.af_at.src_node = addr->sat_addr.s_node= ap->s_node; + at->src_net = addr->sat_addr.s_net = ap->s_net; + at->src_node = addr->sat_addr.s_node= ap->s_node; } else { if (!atalk_find_interface(addr->sat_addr.s_net, addr->sat_addr.s_node)) return -EADDRNOTAVAIL; - sk->protinfo.af_at.src_net = addr->sat_addr.s_net; - sk->protinfo.af_at.src_node = addr->sat_addr.s_node; + at->src_net = addr->sat_addr.s_net; + at->src_node = addr->sat_addr.s_node; } if (addr->sat_port == ATADDR_ANYPORT) { @@ -1266,7 +1263,7 @@ if (n < 0) return n; } else { - sk->protinfo.af_at.src_port = addr->sat_port; + at->src_port = addr->sat_port; if (atalk_find_or_insert_socket(sk, addr)) return -EADDRINUSE; @@ -1281,6 +1278,7 @@ int addr_len, int flags) { struct sock *sk = sock->sk; + struct atalk_sock *at = AT_SK(sk); struct sockaddr_at *addr; sk->state = TCP_CLOSE; @@ -1312,9 +1310,9 @@ if (!atrtr_get_dev(&addr->sat_addr)) return -ENETUNREACH; - sk->protinfo.af_at.dest_port = addr->sat_port; - sk->protinfo.af_at.dest_net = addr->sat_addr.s_net; - sk->protinfo.af_at.dest_node = addr->sat_addr.s_node; + at->dest_port = addr->sat_port; + at->dest_net = addr->sat_addr.s_net; + at->dest_node = addr->sat_addr.s_node; sock->state = SS_CONNECTED; sk->state = TCP_ESTABLISHED; @@ -1331,6 +1329,7 @@ { struct sockaddr_at sat; struct sock *sk = sock->sk; + struct atalk_sock *at = AT_SK(sk); if (sk->zapped) if (atalk_autobind(sk) < 0) @@ -1342,13 +1341,13 @@ if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; - sat.sat_addr.s_net = sk->protinfo.af_at.dest_net; - sat.sat_addr.s_node = sk->protinfo.af_at.dest_node; - sat.sat_port = sk->protinfo.af_at.dest_port; + sat.sat_addr.s_net = at->dest_net; + sat.sat_addr.s_node = at->dest_node; + sat.sat_port = at->dest_port; } else { - sat.sat_addr.s_net = sk->protinfo.af_at.src_net; - sat.sat_addr.s_node = sk->protinfo.af_at.src_node; - sat.sat_port = sk->protinfo.af_at.src_port; + sat.sat_addr.s_net = at->src_net; + sat.sat_addr.s_node = at->src_node; + sat.sat_port = at->src_port; } sat.sat_family = AF_APPLETALK; @@ -1597,6 +1596,7 @@ struct scm_cookie *scm) { struct sock *sk = sock->sk; + struct atalk_sock *at = AT_SK(sk); struct sockaddr_at *usat = (struct sockaddr_at *)msg->msg_name; int flags = msg->msg_flags; int loopback = 0; @@ -1635,10 +1635,10 @@ if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; usat = &local_satalk; - usat->sat_family = AF_APPLETALK; - usat->sat_port = sk->protinfo.af_at.dest_port; - usat->sat_addr.s_node = sk->protinfo.af_at.dest_node; - usat->sat_addr.s_net = sk->protinfo.af_at.dest_net; + usat->sat_family = AF_APPLETALK; + usat->sat_port = at->dest_port; + usat->sat_addr.s_node = at->dest_node; + usat->sat_addr.s_net = at->dest_net; } /* Build a packet */ @@ -1657,7 +1657,7 @@ struct at_addr at_hint; at_hint.s_node = 0; - at_hint.s_net = sk->protinfo.af_at.src_net; + at_hint.s_net = at->src_net; rt = atrtr_find(&at_hint); if (!rt) @@ -1693,11 +1693,11 @@ *((__u16 *)ddp) = ntohs(*((__u16 *)ddp)); ddp->deh_dnet = usat->sat_addr.s_net; - ddp->deh_snet = sk->protinfo.af_at.src_net; + ddp->deh_snet = at->src_net; ddp->deh_dnode = usat->sat_addr.s_node; - ddp->deh_snode = sk->protinfo.af_at.src_node; + ddp->deh_snode = at->src_node; ddp->deh_dport = usat->sat_port; - ddp->deh_sport = sk->protinfo.af_at.src_port; + ddp->deh_sport = at->src_port; SOCK_DEBUG(sk, "SK %p: Copy user data (%d bytes).\n", sk, len); @@ -1894,10 +1894,9 @@ return put_user(amount, (int *)arg); } -static struct net_proto_family atalk_family_ops = -{ - PF_APPLETALK, - atalk_create +static struct net_proto_family atalk_family_ops = { + family: PF_APPLETALK, + create: atalk_create, }; static struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops)= Index: kernel-acme/net/atm/common.c diff -u kernel-acme/net/atm/common.c:1.1.1.6 kernel-acme/net/atm/common.c:1.1.1.6.4.1 --- kernel-acme/net/atm/common.c:1.1.1.6 Fri Nov 23 18:09:30 2001 +++ kernel-acme/net/atm/common.c Tue Dec 11 00:26:45 2001 @@ -105,7 +105,7 @@ sock->sk = NULL; if (sock->type == SOCK_STREAM) return -EINVAL; if (!(sk = alloc_atm_vcc_sk(family))) return -ENOMEM; - vcc = sk->protinfo.af_atm; + vcc = ATM_SK(sk); memset(&vcc->flags,0,sizeof(vcc->flags)); vcc->dev = NULL; vcc->family = sock->ops->family; @@ -136,7 +136,7 @@ struct atm_vcc *vcc; struct sk_buff *skb; - vcc = sk->protinfo.af_atm; + vcc = ATM_SK(sk); clear_bit(ATM_VF_READY,&vcc->flags); if (vcc->dev) { if (vcc->dev->ops->close) vcc->dev->ops->close(vcc); Index: kernel-acme/net/atm/mpc.c diff -u kernel-acme/net/atm/mpc.c:1.1.1.3 kernel-acme/net/atm/mpc.c:1.1.1.3.6.1 --- kernel-acme/net/atm/mpc.c:1.1.1.3 Tue Nov 6 18:55:05 2001 +++ kernel-acme/net/atm/mpc.c Fri Dec 21 02:12:14 2001 @@ -13,7 +13,7 @@ #include #include #include -#include /* for ip_fast_csum() */ +#include /* for ip_fast_csum() */ #include #include #include Index: kernel-acme/net/atm/pvc.c diff -u kernel-acme/net/atm/pvc.c:1.1.1.1 kernel-acme/net/atm/pvc.c:1.1.1.1.12.1 --- kernel-acme/net/atm/pvc.c:1.1.1.1 Tue Jun 26 17:28:54 2001 +++ kernel-acme/net/atm/pvc.c Thu Dec 13 23:14:53 2001 @@ -111,11 +111,8 @@ static struct net_proto_family pvc_family_ops = { - PF_ATMPVC, - pvc_create, - 0, /* no authentication */ - 0, /* no encryption */ - 0 /* no encrypt_net */ + family: PF_ATMPVC, + create: pvc_create, }; Index: kernel-acme/net/atm/resources.c diff -u kernel-acme/net/atm/resources.c:1.1.1.2 kernel-acme/net/atm/resources.c:1.1.1.2.4.2 --- kernel-acme/net/atm/resources.c:1.1.1.2 Fri Nov 23 18:09:20 2001 +++ kernel-acme/net/atm/resources.c Fri Dec 21 02:12:14 2001 @@ -143,7 +143,7 @@ /* Handler for sk->destruct, invoked by sk_free() */ static void atm_free_sock(struct sock *sk) { - kfree(sk->protinfo.af_atm); + kfree(ATM_SK(sk)); } @@ -152,9 +152,9 @@ struct sock *sk; struct atm_vcc *vcc; - sk = sk_alloc(family, GFP_KERNEL, 1); + sk = sk_alloc(family, GFP_KERNEL, 1, NULL); if (!sk) return NULL; - vcc = sk->protinfo.af_atm = kmalloc(sizeof(*vcc),GFP_KERNEL); + vcc = ATM_SK(sk) = kmalloc(sizeof(*vcc),GFP_KERNEL); if (!vcc) { sk_free(sk); return NULL; @@ -186,7 +186,7 @@ void free_atm_vcc_sk(struct sock *sk) { - unlink_vcc(sk->protinfo.af_atm,NULL); + unlink_vcc(ATM_SK(sk),NULL); sk_free(sk); } Index: kernel-acme/net/atm/svc.c diff -u kernel-acme/net/atm/svc.c:1.1.1.1 kernel-acme/net/atm/svc.c:1.1.1.1.12.1 --- kernel-acme/net/atm/svc.c:1.1.1.1 Tue Jun 26 17:28:55 2001 +++ kernel-acme/net/atm/svc.c Thu Dec 13 23:14:53 2001 @@ -430,11 +430,8 @@ static struct net_proto_family svc_family_ops = { - PF_ATMSVC, - svc_create, - 0, /* no authentication */ - 0, /* no encryption */ - 0 /* no encrypt_net */ + family: PF_ATMSVC, + create: svc_create, }; Index: kernel-acme/net/ax25/af_ax25.c diff -u kernel-acme/net/ax25/af_ax25.c:1.1.1.3 kernel-acme/net/ax25/af_ax25.c:1.1.1.3.8.2 --- kernel-acme/net/ax25/af_ax25.c:1.1.1.3 Wed Sep 26 22:00:20 2001 +++ kernel-acme/net/ax25/af_ax25.c Fri Dec 21 02:12:14 2001 @@ -161,7 +161,7 @@ static void ax25_free_sock(struct sock *sk) { - ax25_free_cb(sk->protinfo.ax25); + ax25_free_cb(AX25_SK(sk)); } /* @@ -424,8 +424,8 @@ while ((skb = skb_dequeue(&ax25->sk->receive_queue)) != NULL) { if (skb->sk != ax25->sk) { /* A pending connection */ skb->sk->dead = 1; /* Queue the unaccepted socket for death */ - ax25_start_heartbeat(skb->sk->protinfo.ax25); - skb->sk->protinfo.ax25->state = AX25_STATE_0; + ax25_start_heartbeat(AX25_SK(skb->sk)); + AX25_SK(skb->sk)->state = AX25_STATE_0; } kfree_skb(skb); @@ -631,6 +631,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) { struct sock *sk = sock->sk; + ax25_cb *ax25 = AX25_SK(sk); struct net_device *dev; char devname[IFNAMSIZ]; int opt; @@ -646,69 +647,69 @@ switch (optname) { case AX25_WINDOW: - if (sk->protinfo.ax25->modulus == AX25_MODULUS) { + if (ax25->modulus == AX25_MODULUS) { if (opt < 1 || opt > 7) return -EINVAL; } else { if (opt < 1 || opt > 63) return -EINVAL; } - sk->protinfo.ax25->window = opt; + ax25->window = opt; return 0; case AX25_T1: if (opt < 1) return -EINVAL; - sk->protinfo.ax25->rtt = (opt * HZ) / 2; - sk->protinfo.ax25->t1 = opt * HZ; + ax25->rtt = (opt * HZ) / 2; + ax25->t1 = opt * HZ; return 0; case AX25_T2: if (opt < 1) return -EINVAL; - sk->protinfo.ax25->t2 = opt * HZ; + ax25->t2 = opt * HZ; return 0; case AX25_N2: if (opt < 1 || opt > 31) return -EINVAL; - sk->protinfo.ax25->n2 = opt; + ax25->n2 = opt; return 0; case AX25_T3: if (opt < 1) return -EINVAL; - sk->protinfo.ax25->t3 = opt * HZ; + ax25->t3 = opt * HZ; return 0; case AX25_IDLE: if (opt < 0) return -EINVAL; - sk->protinfo.ax25->idle = opt * 60 * HZ; + ax25->idle = opt * 60 * HZ; return 0; case AX25_BACKOFF: if (opt < 0 || opt > 2) return -EINVAL; - sk->protinfo.ax25->backoff = opt; + ax25->backoff = opt; return 0; case AX25_EXTSEQ: - sk->protinfo.ax25->modulus = opt ? AX25_EMODULUS : AX25_MODULUS; + ax25->modulus = opt ? AX25_EMODULUS : AX25_MODULUS; return 0; case AX25_PIDINCL: - sk->protinfo.ax25->pidincl = opt ? 1 : 0; + ax25->pidincl = opt ? 1 : 0; return 0; case AX25_IAMDIGI: - sk->protinfo.ax25->iamdigi = opt ? 1 : 0; + ax25->iamdigi = opt ? 1 : 0; return 0; case AX25_PACLEN: if (opt < 16 || opt > 65535) return -EINVAL; - sk->protinfo.ax25->paclen = opt; + ax25->paclen = opt; return 0; case SO_BINDTODEVICE: @@ -723,8 +724,8 @@ (sock->state != SS_UNCONNECTED || sk->state == TCP_LISTEN)) return -EADDRNOTAVAIL; - sk->protinfo.ax25->ax25_dev = ax25_dev_ax25dev(dev); - ax25_fillin_cb(sk->protinfo.ax25, sk->protinfo.ax25->ax25_dev); + ax25->ax25_dev = ax25_dev_ax25dev(dev); + ax25_fillin_cb(ax25, ax25->ax25_dev); return 0; default: @@ -735,6 +736,7 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) { struct sock *sk = sock->sk; + ax25_cb *ax25 = AX25_SK(sk); struct ax25_dev *ax25_dev; char devname[IFNAMSIZ]; void *valptr; @@ -755,51 +757,51 @@ switch (optname) { case AX25_WINDOW: - val = sk->protinfo.ax25->window; + val = ax25->window; break; case AX25_T1: - val = sk->protinfo.ax25->t1 / HZ; + val = ax25->t1 / HZ; break; case AX25_T2: - val = sk->protinfo.ax25->t2 / HZ; + val = ax25->t2 / HZ; break; case AX25_N2: - val = sk->protinfo.ax25->n2; + val = ax25->n2; break; case AX25_T3: - val = sk->protinfo.ax25->t3 / HZ; + val = ax25->t3 / HZ; break; case AX25_IDLE: - val = sk->protinfo.ax25->idle / (60 * HZ); + val = ax25->idle / (60 * HZ); break; case AX25_BACKOFF: - val = sk->protinfo.ax25->backoff; + val = ax25->backoff; break; case AX25_EXTSEQ: - val = (sk->protinfo.ax25->modulus == AX25_EMODULUS); + val = (ax25->modulus == AX25_EMODULUS); break; case AX25_PIDINCL: - val = sk->protinfo.ax25->pidincl; + val = ax25->pidincl; break; case AX25_IAMDIGI: - val = sk->protinfo.ax25->iamdigi; + val = ax25->iamdigi; break; case AX25_PACLEN: - val = sk->protinfo.ax25->paclen; + val = ax25->paclen; break; case SO_BINDTODEVICE: - ax25_dev = sk->protinfo.ax25->ax25_dev; + ax25_dev = ax25->ax25_dev; if (ax25_dev != NULL && ax25_dev->dev != NULL) { strncpy(devname, ax25_dev->dev->name, IFNAMSIZ); @@ -884,7 +886,7 @@ return -ESOCKTNOSUPPORT; } - if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, 1)) == NULL) + if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, 1, NULL)) == NULL) return -ENOMEM; if ((ax25 = ax25_create_cb()) == NULL) { @@ -898,8 +900,8 @@ sock->ops = &ax25_proto_ops; sk->protocol = protocol; - ax25->sk = sk; - sk->protinfo.ax25 = ax25; + ax25->sk = sk; + AX25_SK(sk) = ax25; return 0; } @@ -907,9 +909,9 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev) { struct sock *sk; - ax25_cb *ax25; + ax25_cb *ax25, *oax25; - if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, 1)) == NULL) + if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, 1, NULL)) == NULL) return NULL; if ((ax25 = ax25_create_cb()) == NULL) { @@ -941,34 +943,36 @@ sk->state = TCP_ESTABLISHED; sk->sleep = osk->sleep; sk->zapped = osk->zapped; + + oax25 = AX25_SK(osk); - ax25->modulus = osk->protinfo.ax25->modulus; - ax25->backoff = osk->protinfo.ax25->backoff; - ax25->pidincl = osk->protinfo.ax25->pidincl; - ax25->iamdigi = osk->protinfo.ax25->iamdigi; - ax25->rtt = osk->protinfo.ax25->rtt; - ax25->t1 = osk->protinfo.ax25->t1; - ax25->t2 = osk->protinfo.ax25->t2; - ax25->t3 = osk->protinfo.ax25->t3; - ax25->n2 = osk->protinfo.ax25->n2; - ax25->idle = osk->protinfo.ax25->idle; - ax25->paclen = osk->protinfo.ax25->paclen; - ax25->window = osk->protinfo.ax25->window; + ax25->modulus = oax25->modulus; + ax25->backoff = oax25->backoff; + ax25->pidincl = oax25->pidincl; + ax25->iamdigi = oax25->iamdigi; + ax25->rtt = oax25->rtt; + ax25->t1 = oax25->t1; + ax25->t2 = oax25->t2; + ax25->t3 = oax25->t3; + ax25->n2 = oax25->n2; + ax25->idle = oax25->idle; + ax25->paclen = oax25->paclen; + ax25->window = oax25->window; ax25->ax25_dev = ax25_dev; - ax25->source_addr = osk->protinfo.ax25->source_addr; + ax25->source_addr = oax25->source_addr; - if (osk->protinfo.ax25->digipeat != NULL) { + if (oax25->digipeat != NULL) { if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { sk_free(sk); return NULL; } - memcpy(ax25->digipeat, osk->protinfo.ax25->digipeat, sizeof(ax25_digi)); + memcpy(ax25->digipeat, oax25->digipeat, sizeof(ax25_digi)); } - sk->protinfo.ax25 = ax25; - ax25->sk = sk; + AX25_SK(sk) = ax25; + ax25->sk = sk; return sk; } @@ -976,45 +980,51 @@ static int ax25_release(struct socket *sock) { struct sock *sk = sock->sk; + ax25_cb *ax25; if (sk == NULL) return 0; + ax25 = AX25_SK(sk); + if (sk->type == SOCK_SEQPACKET) { - switch (sk->protinfo.ax25->state) { + switch (ax25->state) { case AX25_STATE_0: - ax25_disconnect(sk->protinfo.ax25, 0); - ax25_destroy_socket(sk->protinfo.ax25); + ax25_disconnect(ax25, 0); + ax25_destroy_socket(ax25); break; case AX25_STATE_1: case AX25_STATE_2: - ax25_send_control(sk->protinfo.ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); - ax25_disconnect(sk->protinfo.ax25, 0); - ax25_destroy_socket(sk->protinfo.ax25); + ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); + ax25_disconnect(ax25, 0); + ax25_destroy_socket(ax25); break; case AX25_STATE_3: case AX25_STATE_4: - ax25_clear_queues(sk->protinfo.ax25); - sk->protinfo.ax25->n2count = 0; - switch (sk->protinfo.ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { + ax25_clear_queues(ax25); + ax25->n2count = 0; + switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { case AX25_PROTO_STD_SIMPLEX: case AX25_PROTO_STD_DUPLEX: - ax25_send_control(sk->protinfo.ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); - ax25_stop_t2timer(sk->protinfo.ax25); - ax25_stop_t3timer(sk->protinfo.ax25); - ax25_stop_idletimer(sk->protinfo.ax25); + ax25_send_control(ax25, + AX25_DISC, + AX25_POLLON, + AX25_COMMAND); + ax25_stop_t2timer(ax25); + ax25_stop_t3timer(ax25); + ax25_stop_idletimer(ax25); break; #ifdef CONFIG_AX25_DAMA_SLAVE case AX25_PROTO_DAMA_SLAVE: - ax25_stop_t3timer(sk->protinfo.ax25); - ax25_stop_idletimer(sk->protinfo.ax25); + ax25_stop_t3timer(ax25); + ax25_stop_idletimer(ax25); break; #endif } - ax25_calculate_t1(sk->protinfo.ax25); - ax25_start_t1timer(sk->protinfo.ax25); - sk->protinfo.ax25->state = AX25_STATE_2; + ax25_calculate_t1(ax25); + ax25_start_t1timer(ax25); + ax25->state = AX25_STATE_2; sk->state = TCP_CLOSE; sk->shutdown |= SEND_SHUTDOWN; sk->state_change(sk); @@ -1030,7 +1040,7 @@ sk->shutdown |= SEND_SHUTDOWN; sk->state_change(sk); sk->dead = 1; - ax25_destroy_socket(sk->protinfo.ax25); + ax25_destroy_socket(ax25); } sock->sk = NULL; @@ -1048,6 +1058,7 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; + ax25_cb *ax25 = AX25_SK(sk); struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr; ax25_address *call; ax25_dev *ax25_dev = NULL; @@ -1074,15 +1085,15 @@ return -EACCES; if (call == NULL) - sk->protinfo.ax25->source_addr = addr->fsa_ax25.sax25_call; + ax25->source_addr = addr->fsa_ax25.sax25_call; else - sk->protinfo.ax25->source_addr = *call; + ax25->source_addr = *call; /* * User already set interface with SO_BINDTODEVICE */ - if (sk->protinfo.ax25->ax25_dev != NULL) + if (ax25->ax25_dev != NULL) goto done; if (addr_len > sizeof(struct sockaddr_ax25) && addr->fsa_ax25.sax25_ndigis == 1) { @@ -1095,10 +1106,10 @@ } if (ax25_dev != NULL) - ax25_fillin_cb(sk->protinfo.ax25, ax25_dev); + ax25_fillin_cb(ax25, ax25_dev); done: - ax25_insert_socket(sk->protinfo.ax25); + ax25_insert_socket(ax25); sk->zapped = 0; return 0; } @@ -1109,6 +1120,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { struct sock *sk = sock->sk; + ax25_cb *ax25 = AX25_SK(sk); struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr; ax25_digi *digi = NULL; int ct = 0, err; @@ -1157,9 +1169,9 @@ if (fsa->fsa_ax25.sax25_family != AF_AX25) return -EINVAL; - if (sk->protinfo.ax25->digipeat != NULL) { - kfree(sk->protinfo.ax25->digipeat); - sk->protinfo.ax25->digipeat = NULL; + if (ax25->digipeat != NULL) { + kfree(ax25->digipeat); + ax25->digipeat = NULL; } /* @@ -1177,7 +1189,8 @@ digi->lastrepeat = -1; while (ct < fsa->fsa_ax25.sax25_ndigis) { - if ((fsa->fsa_digipeater[ct].ax25_call[6] & AX25_HBIT) && sk->protinfo.ax25->iamdigi) { + if ((fsa->fsa_digipeater[ct].ax25_call[6] & + AX25_HBIT) && ax25->iamdigi) { digi->repeated[ct] = 1; digi->lastrepeat = ct; } else { @@ -1197,22 +1210,24 @@ /* check if we can remove this feature. It is broken. */ printk(KERN_WARNING "ax25_connect(): %s uses autobind, please contact jreuter@yaina.de\n", current->comm); - if ((err = ax25_rt_autobind(sk->protinfo.ax25, &fsa->fsa_ax25.sax25_call)) < 0) + if ((err = ax25_rt_autobind(ax25, &fsa->fsa_ax25.sax25_call)) < 0) return err; - ax25_fillin_cb(sk->protinfo.ax25, sk->protinfo.ax25->ax25_dev); - ax25_insert_socket(sk->protinfo.ax25); + ax25_fillin_cb(ax25, ax25->ax25_dev); + ax25_insert_socket(ax25); } else { - if (sk->protinfo.ax25->ax25_dev == NULL) + if (ax25->ax25_dev == NULL) return -EHOSTUNREACH; } - if (sk->type == SOCK_SEQPACKET && ax25_find_cb(&sk->protinfo.ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi, sk->protinfo.ax25->ax25_dev->dev) != NULL) { + if (sk->type == SOCK_SEQPACKET && + ax25_find_cb(&ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi, + ax25->ax25_dev->dev)) { if (digi != NULL) kfree(digi); return -EADDRINUSE; /* Already such a connection */ } - sk->protinfo.ax25->dest_addr = fsa->fsa_ax25.sax25_call; - sk->protinfo.ax25->digipeat = digi; + ax25->dest_addr = fsa->fsa_ax25.sax25_call; + ax25->digipeat = digi; /* First the easy one */ if (sk->type != SOCK_SEQPACKET) { @@ -1225,27 +1240,28 @@ sock->state = SS_CONNECTING; sk->state = TCP_SYN_SENT; - switch (sk->protinfo.ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { + switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { case AX25_PROTO_STD_SIMPLEX: case AX25_PROTO_STD_DUPLEX: - ax25_std_establish_data_link(sk->protinfo.ax25); + ax25_std_establish_data_link(ax25); break; #ifdef CONFIG_AX25_DAMA_SLAVE case AX25_PROTO_DAMA_SLAVE: - sk->protinfo.ax25->modulus = AX25_MODULUS; - sk->protinfo.ax25->window = sk->protinfo.ax25->ax25_dev->values[AX25_VALUES_WINDOW]; - if (sk->protinfo.ax25->ax25_dev->dama.slave) - ax25_ds_establish_data_link(sk->protinfo.ax25); + ax25->modulus = AX25_MODULUS; + ax25->window = + ax25->ax25_dev->values[AX25_VALUES_WINDOW]; + if (ax25->ax25_dev->dama.slave) + ax25_ds_establish_data_link(ax25); else - ax25_std_establish_data_link(sk->protinfo.ax25); + ax25_std_establish_data_link(ax25); break; #endif } - sk->protinfo.ax25->state = AX25_STATE_1; + ax25->state = AX25_STATE_1; - ax25_start_heartbeat(sk->protinfo.ax25); + ax25_start_heartbeat(ax25); /* Now the loop */ if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) @@ -1327,6 +1343,7 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) { struct sock *sk = sock->sk; + ax25_cb *ax25 = AX25_SK(sk); struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr; unsigned char ndigi, i; @@ -1335,21 +1352,23 @@ return -ENOTCONN; fsa->fsa_ax25.sax25_family = AF_AX25; - fsa->fsa_ax25.sax25_call = sk->protinfo.ax25->dest_addr; + fsa->fsa_ax25.sax25_call = ax25->dest_addr; fsa->fsa_ax25.sax25_ndigis = 0; - if (sk->protinfo.ax25->digipeat != NULL) { - ndigi = sk->protinfo.ax25->digipeat->ndigi; + if (ax25->digipeat != NULL) { + ndigi = ax25->digipeat->ndigi; fsa->fsa_ax25.sax25_ndigis = ndigi; for (i = 0; i < ndigi; i++) - fsa->fsa_digipeater[i] = sk->protinfo.ax25->digipeat->calls[i]; + fsa->fsa_digipeater[i] = + ax25->digipeat->calls[i]; } } else { fsa->fsa_ax25.sax25_family = AF_AX25; - fsa->fsa_ax25.sax25_call = sk->protinfo.ax25->source_addr; + fsa->fsa_ax25.sax25_call = ax25->source_addr; fsa->fsa_ax25.sax25_ndigis = 1; - if (sk->protinfo.ax25->ax25_dev != NULL) { - memcpy(&fsa->fsa_digipeater[0], sk->protinfo.ax25->ax25_dev->dev->dev_addr, AX25_ADDR_LEN); + if (ax25->ax25_dev != NULL) { + memcpy(&fsa->fsa_digipeater[0], + ax25->ax25_dev->dev->dev_addr, AX25_ADDR_LEN); } else { fsa->fsa_digipeater[0] = null_ax25_address; } @@ -1361,6 +1380,7 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) { struct sock *sk = sock->sk; + ax25_cb *ax25 = AX25_SK(sk); struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name; int err; struct sockaddr_ax25 sax; @@ -1383,7 +1403,7 @@ return -EPIPE; } - if (sk->protinfo.ax25->ax25_dev == NULL) + if (ax25->ax25_dev == NULL) return -ENETUNREACH; if (usax != NULL) { @@ -1424,7 +1444,7 @@ } sax = *usax; - if (sk->type == SOCK_SEQPACKET && ax25cmp(&sk->protinfo.ax25->dest_addr, &sax.sax25_call) != 0) + if (sk->type == SOCK_SEQPACKET && ax25cmp(&ax25->dest_addr, &sax.sax25_call) != 0) return -EISCONN; if (usax->sax25_ndigis == 0) dp = NULL; @@ -1439,8 +1459,8 @@ if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; sax.sax25_family = AF_AX25; - sax.sax25_call = sk->protinfo.ax25->dest_addr; - dp = sk->protinfo.ax25->digipeat; + sax.sax25_call = ax25->dest_addr; + dp = ax25->digipeat; } SOCK_DEBUG(sk, "AX.25: sendto: Addresses built.\n"); @@ -1463,7 +1483,7 @@ skb->nh.raw = skb->data; /* Add the PID if one is not supplied by the user in the skb */ - if (!sk->protinfo.ax25->pidincl) { + if (!ax25->pidincl) { asmptr = skb_push(skb, 1); *asmptr = sk->protocol; } @@ -1477,7 +1497,8 @@ return -ENOTCONN; } - ax25_output(sk->protinfo.ax25, sk->protinfo.ax25->paclen, skb); /* Shove it onto the queue and kick */ + /* Shove it onto the queue and kick */ + ax25_output(ax25, ax25->paclen, skb); return len; } else { @@ -1489,7 +1510,9 @@ SOCK_DEBUG(sk, "Num digipeaters=%d\n", dp->ndigi); /* Build an AX.25 header */ - asmptr += (lv = ax25_addr_build(asmptr, &sk->protinfo.ax25->source_addr, &sax.sax25_call, dp, AX25_COMMAND, AX25_MODULUS)); + asmptr += (lv = ax25_addr_build(asmptr, &ax25->source_addr, + &sax.sax25_call, dp, + AX25_COMMAND, AX25_MODULUS)); SOCK_DEBUG(sk, "Built header (%d bytes)\n",lv); @@ -1500,7 +1523,7 @@ *asmptr = AX25_UI; /* Datagram frames go straight out of the door as UI */ - skb->dev = sk->protinfo.ax25->ax25_dev->dev; + skb->dev = ax25->ax25_dev->dev; ax25_queue_xmit(skb); @@ -1526,7 +1549,7 @@ if ((skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &er)) == NULL) return er; - if (!sk->protinfo.ax25->pidincl) + if (!AX25_SK(sk)->pidincl) skb_pull(skb, 1); /* Remove PID */ skb->h.raw = skb->data; @@ -1639,27 +1662,28 @@ case SIOCAX25GETINFO: case SIOCAX25GETINFOOLD: { + ax25_cb *ax25 = AX25_SK(sk); struct ax25_info_struct ax25_info; - ax25_info.t1 = sk->protinfo.ax25->t1 / HZ; - ax25_info.t2 = sk->protinfo.ax25->t2 / HZ; - ax25_info.t3 = sk->protinfo.ax25->t3 / HZ; - ax25_info.idle = sk->protinfo.ax25->idle / (60 * HZ); - ax25_info.n2 = sk->protinfo.ax25->n2; - ax25_info.t1timer = ax25_display_timer(&sk->protinfo.ax25->t1timer) / HZ; - ax25_info.t2timer = ax25_display_timer(&sk->protinfo.ax25->t2timer) / HZ; - ax25_info.t3timer = ax25_display_timer(&sk->protinfo.ax25->t3timer) / HZ; - ax25_info.idletimer = ax25_display_timer(&sk->protinfo.ax25->idletimer) / (60 * HZ); - ax25_info.n2count = sk->protinfo.ax25->n2count; - ax25_info.state = sk->protinfo.ax25->state; + ax25_info.t1 = ax25->t1 / HZ; + ax25_info.t2 = ax25->t2 / HZ; + ax25_info.t3 = ax25->t3 / HZ; + ax25_info.idle = ax25->idle / (60 * HZ); + ax25_info.n2 = ax25->n2; + ax25_info.t1timer = ax25_display_timer(&ax25->t1timer) / HZ; + ax25_info.t2timer = ax25_display_timer(&ax25->t2timer) / HZ; + ax25_info.t3timer = ax25_display_timer(&ax25->t3timer) / HZ; + ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ); + ax25_info.n2count = ax25->n2count; + ax25_info.state = ax25->state; ax25_info.rcv_q = atomic_read(&sk->rmem_alloc); ax25_info.snd_q = atomic_read(&sk->wmem_alloc); - ax25_info.vs = sk->protinfo.ax25->vs; - ax25_info.vr = sk->protinfo.ax25->vr; - ax25_info.va = sk->protinfo.ax25->va; - ax25_info.vs_max = sk->protinfo.ax25->vs; /* reserved */ - ax25_info.paclen = sk->protinfo.ax25->paclen; - ax25_info.window = sk->protinfo.ax25->window; + ax25_info.vs = ax25->vs; + ax25_info.vr = ax25->vr; + ax25_info.va = ax25->va; + ax25_info.vs_max = ax25->vs; /* reserved */ + ax25_info.paclen = ax25->paclen; + ax25_info.window = ax25->window; /* old structure? */ if (cmd == SIOCAX25GETINFOOLD) { Index: kernel-acme/net/ax25/ax25_ds_timer.c diff -u kernel-acme/net/ax25/ax25_ds_timer.c:1.1.1.1 kernel-acme/net/ax25/ax25_ds_timer.c:1.1.1.1.12.1 --- kernel-acme/net/ax25/ax25_ds_timer.c:1.1.1.1 Tue Jun 26 17:28:56 2001 +++ kernel-acme/net/ax25/ax25_ds_timer.c Tue Dec 18 04:23:41 2001 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include Index: kernel-acme/net/ax25/ax25_in.c diff -u kernel-acme/net/ax25/ax25_in.c:1.1.1.3 kernel-acme/net/ax25/ax25_in.c:1.1.1.3.8.1 --- kernel-acme/net/ax25/ax25_in.c:1.1.1.3 Wed Sep 26 22:00:20 2001 +++ kernel-acme/net/ax25/ax25_in.c Tue Dec 11 00:26:45 2001 @@ -388,7 +388,7 @@ return 0; } - ax25 = make->protinfo.ax25; + ax25 = AX25_SK(make); skb_set_owner_r(skb, make); skb_queue_head(&sk->receive_queue, skb); Index: kernel-acme/net/ax25/ax25_std_timer.c diff -u kernel-acme/net/ax25/ax25_std_timer.c:1.1.1.1 kernel-acme/net/ax25/ax25_std_timer.c:1.1.1.1.12.1 --- kernel-acme/net/ax25/ax25_std_timer.c:1.1.1.1 Tue Jun 26 17:28:56 2001 +++ kernel-acme/net/ax25/ax25_std_timer.c Mon Dec 17 15:04:51 2001 @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include Index: kernel-acme/net/ax25/ax25_subr.c diff -u kernel-acme/net/ax25/ax25_subr.c:1.1.1.2 kernel-acme/net/ax25/ax25_subr.c:1.1.1.2.10.1 --- kernel-acme/net/ax25/ax25_subr.c:1.1.1.2 Thu Aug 16 18:44:06 2001 +++ kernel-acme/net/ax25/ax25_subr.c Mon Dec 17 15:04:51 2001 @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include Index: kernel-acme/net/bluetooth/af_bluetooth.c diff -u kernel-acme/net/bluetooth/af_bluetooth.c:1.1.1.2 kernel-acme/net/bluetooth/af_bluetooth.c:1.1.1.2.8.1 --- kernel-acme/net/bluetooth/af_bluetooth.c:1.1.1.2 Wed Sep 26 22:00:33 2001 +++ kernel-acme/net/bluetooth/af_bluetooth.c Thu Dec 13 23:14:53 2001 @@ -25,7 +25,7 @@ /* * BlueZ Bluetooth address family and sockets. * - * $Id: af_bluetooth.c,v 1.1.1.2 2001/09/26 22:00:33 acme Exp $ + * $Id: af_bluetooth.c,v 1.1.1.2.8.1 2001/12/13 23:14:53 acme Exp $ */ #define VERSION "1.1" @@ -122,9 +122,9 @@ write_unlock(&l->lock); } -struct net_proto_family bluez_sock_family_ops = -{ - PF_BLUETOOTH, bluez_sock_create +struct net_proto_family bluez_sock_family_ops = { + family: PF_BLUETOOTH, + create: bluez_sock_create, }; int bluez_init(void) Index: kernel-acme/net/bluetooth/hci_sock.c diff -u kernel-acme/net/bluetooth/hci_sock.c:1.1.1.2 kernel-acme/net/bluetooth/hci_sock.c:1.1.1.2.8.2 --- kernel-acme/net/bluetooth/hci_sock.c:1.1.1.2 Wed Sep 26 22:00:33 2001 +++ kernel-acme/net/bluetooth/hci_sock.c Fri Dec 21 02:12:14 2001 @@ -25,7 +25,7 @@ /* * BlueZ HCI socket layer. * - * $Id: hci_sock.c,v 1.1.1.2 2001/09/26 22:00:33 acme Exp $ + * $Id: hci_sock.c,v 1.1.1.2.8.2 2001/12/21 02:12:14 acme Exp $ */ #include @@ -453,7 +453,7 @@ sock->ops = &hci_sock_ops; - if (!(sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, 1))) + if (!(sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, 1, NULL))) return -ENOMEM; sock->state = SS_UNCONNECTED; @@ -519,7 +519,7 @@ struct net_proto_family hci_sock_family_ops = { family: PF_BLUETOOTH, - create: hci_sock_create + create: hci_sock_create, }; struct notifier_block hci_sock_nblock = { Index: kernel-acme/net/bluetooth/l2cap_core.c diff -u kernel-acme/net/bluetooth/l2cap_core.c:1.1.1.3 kernel-acme/net/bluetooth/l2cap_core.c:1.1.1.3.6.2 --- kernel-acme/net/bluetooth/l2cap_core.c:1.1.1.3 Tue Nov 6 18:55:20 2001 +++ kernel-acme/net/bluetooth/l2cap_core.c Fri Dec 21 02:12:14 2001 @@ -25,7 +25,7 @@ /* * BlueZ L2CAP core and sockets. * - * $Id: l2cap_core.c,v 1.1.1.3 2001/11/06 18:55:20 acme Exp $ + * $Id: l2cap_core.c,v 1.1.1.3.6.2 2001/12/21 02:12:14 acme Exp $ */ #define VERSION "1.1" @@ -640,7 +640,7 @@ { struct sock *sk; - if (!(sk = sk_alloc(PF_BLUETOOTH, prio, 1))) + if (!(sk = sk_alloc(PF_BLUETOOTH, prio, 1, NULL))) return NULL; sock_init_data(sock, sk); @@ -2238,7 +2238,7 @@ struct net_proto_family l2cap_sock_family_ops = { family: PF_BLUETOOTH, - create: l2cap_sock_create + create: l2cap_sock_create, }; struct hci_proto l2cap_hci_proto = { Index: kernel-acme/net/core/Makefile diff -u kernel-acme/net/core/Makefile:1.1.1.2 kernel-acme/net/core/Makefile:1.1.1.2.6.1 --- kernel-acme/net/core/Makefile:1.1.1.2 Tue Nov 6 21:30:33 2001 +++ kernel-acme/net/core/Makefile Thu Nov 29 20:36:55 2001 @@ -9,7 +9,7 @@ O_TARGET := core.o -export-objs := netfilter.o profile.o +export-objs := ext8022.o netfilter.o profile.o obj-y := sock.o skbuff.o iovec.o datagram.o scm.o @@ -22,6 +22,10 @@ obj-$(CONFIG_FILTER) += filter.o obj-$(CONFIG_NET) += dev.o dev_mcast.o dst.o neighbour.o rtnetlink.o utils.o + +ifneq ($(CONFIG_LLC),n) +obj-y += ext8022.o +endif obj-$(CONFIG_NETFILTER) += netfilter.o obj-$(CONFIG_NET_DIVERT) += dv.o Index: kernel-acme/net/core/ext8022.c diff -u /dev/null kernel-acme/net/core/ext8022.c:1.1.12.1 --- /dev/null Sat Dec 22 02:21:07 2001 +++ kernel-acme/net/core/ext8022.c Thu Nov 29 20:36:55 2001 @@ -0,0 +1,76 @@ +/* + * (ext8022.c) + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include + +typedef int (*func_type)(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt); +static int llc_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *); + +static func_type llc_sap_table[128]; +static int llc_users; + +static struct packet_type llc_packet_type = { + type: __constant_htons(ETH_P_802_2), + func: llc_rcv, +}; +static struct packet_type llc_tr_packet_type = { + type: __constant_htons(ETH_P_TR_802_2), + func: llc_rcv, +}; + +static int llc_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt) +{ + unsigned char n = (*(skb->h.raw)) >> 1; + + br_read_lock(BR_LLC_LOCK); + if (llc_sap_table[n]) + llc_sap_table[n](skb, dev, pt); + else + kfree_skb(skb); + br_read_unlock(BR_LLC_LOCK); + return 0; +} + +void llc_register_sap(unsigned char sap, func_type rcvfunc) +{ + sap >>= 1; + br_write_lock_bh(BR_LLC_LOCK); + llc_sap_table[sap] = rcvfunc; + if (!llc_users) { + dev_add_pack(&llc_packet_type); + dev_add_pack(&llc_tr_packet_type); + } + llc_users++; + br_write_unlock_bh(BR_LLC_LOCK); +} + +void llc_unregister_sap(unsigned char sap) +{ + sap >>= 1; + br_write_lock_bh(BR_LLC_LOCK); + llc_sap_table[sap] = NULL; + if (!--llc_users) { + dev_remove_pack(&llc_packet_type); + dev_remove_pack(&llc_tr_packet_type); + } + br_write_unlock_bh(BR_LLC_LOCK); +} + +EXPORT_SYMBOL(llc_register_sap); +EXPORT_SYMBOL(llc_unregister_sap); Index: kernel-acme/net/core/sock.c diff -u kernel-acme/net/core/sock.c:1.1.1.3 kernel-acme/net/core/sock.c:1.1.1.3.10.5 --- kernel-acme/net/core/sock.c:1.1.1.3 Thu Aug 16 21:59:27 2001 +++ kernel-acme/net/core/sock.c Fri Dec 21 02:12:15 2001 @@ -7,7 +7,7 @@ * handler for protocols to use and generic option handler. * * - * Version: $Id: sock.c,v 1.1.1.3 2001/08/16 21:59:27 acme Exp $ + * Version: $Id: sock.c,v 1.1.1.3.10.5 2001/12/21 02:12:15 acme Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -578,19 +578,33 @@ static kmem_cache_t *sk_cachep; -/* - * All socket objects are allocated here. This is for future - * usage. +/** + * sk_alloc - All socket objects are allocated here + * @family - protocol family + * @priority - for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc) + * @zero_it - zeroes the allocated sock + * @slab - alternate slab + * + * All socket objects are allocated here. If @zero_it is non-zero + * it should have the size of the are to be zeroed, because the + * private slabcaches have different sizes of the generic struct sock. + * 1 has been kept as a way to say sizeof(struct sock). */ - -struct sock *sk_alloc(int family, int priority, int zero_it) +struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab) { - struct sock *sk = kmem_cache_alloc(sk_cachep, priority); - - if(sk && zero_it) { - memset(sk, 0, sizeof(struct sock)); - sk->family = family; - sock_lock_init(sk); + struct sock *sk; + + if (!slab) + slab = sk_cachep; + sk = kmem_cache_alloc(slab, priority); + if (sk) { + if (zero_it) { + memset(sk, 0, + zero_it == 1 ? sizeof(struct sock) : zero_it); + sk->family = family; + sock_lock_init(sk); + } + sk->slab = slab; } return sk; @@ -616,7 +630,7 @@ if (atomic_read(&sk->omem_alloc)) printk(KERN_DEBUG "sk_free: optmem leakage (%d bytes) detected.\n", atomic_read(&sk->omem_alloc)); - kmem_cache_free(sk_cachep, sk); + kmem_cache_free(sk->slab, sk); } void __init sk_init(void) @@ -1144,8 +1158,8 @@ void sock_def_destruct(struct sock *sk) { - if (sk->protinfo.destruct_hook) - kfree(sk->protinfo.destruct_hook); + if (sk->protinfo) + kfree(sk->protinfo); } void sock_init_data(struct socket *sock, struct sock *sk) Index: kernel-acme/net/decnet/af_decnet.c diff -u kernel-acme/net/decnet/af_decnet.c:1.1.1.3 kernel-acme/net/decnet/af_decnet.c:1.1.1.3.4.3 --- kernel-acme/net/decnet/af_decnet.c:1.1.1.3 Fri Nov 23 18:22:54 2001 +++ kernel-acme/net/decnet/af_decnet.c Fri Dec 21 02:12:16 2001 @@ -112,6 +112,7 @@ #include #include #include +#include #include #include #include @@ -404,14 +405,17 @@ struct sock *sk; struct dn_scp *scp; - if ((sk = sk_alloc(PF_DECnet, gfp, 1)) == NULL) + if ((sk = sk_alloc(PF_DECnet, gfp, 1, NULL)) == NULL) goto no_sock; + scp = kmalloc(sizeof(*scp), gfp); + if (!scp) + goto free_sock; if (sock) { sock->ops = &dn_proto_ops; } sock_init_data(sock,sk); - scp = DN_SK(sk); + DN_SK(sk) = scp; sk->backlog_rcv = dn_nsp_backlog_rcv; sk->destruct = dn_destruct; @@ -472,6 +476,8 @@ MOD_INC_USE_COUNT; return sk; +free_sock: + sk_free(sk); no_sock: return NULL; } Index: kernel-acme/net/decnet/dn_nsp_in.c diff -u kernel-acme/net/decnet/dn_nsp_in.c:1.1.1.2 kernel-acme/net/decnet/dn_nsp_in.c:1.1.1.2.4.2 --- kernel-acme/net/decnet/dn_nsp_in.c:1.1.1.2 Fri Nov 23 18:23:07 2001 +++ kernel-acme/net/decnet/dn_nsp_in.c Mon Dec 17 15:04:51 2001 @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,7 @@ #include #include #include +#include #include #include #include @@ -100,7 +102,7 @@ switch(type) { case 0: /* ACK - Data */ - if (after(ack, scp->ackrcv_dat)) { + if (dn_after(ack, scp->ackrcv_dat)) { scp->ackrcv_dat = ack & 0x0fff; wakeup |= dn_nsp_check_xmit_queue(sk, skb, &scp->data_xmit_queue, ack); } @@ -108,7 +110,7 @@ case 1: /* NAK - Data */ break; case 2: /* ACK - OtherData */ - if (after(ack, scp->ackrcv_oth)) { + if (dn_after(ack, scp->ackrcv_oth)) { scp->ackrcv_oth = ack & 0x0fff; wakeup |= dn_nsp_check_xmit_queue(sk, skb, &scp->other_xmit_queue, ack); } Index: kernel-acme/net/decnet/dn_nsp_out.c diff -u kernel-acme/net/decnet/dn_nsp_out.c:1.1.1.1 kernel-acme/net/decnet/dn_nsp_out.c:1.1.1.1.12.2 --- kernel-acme/net/decnet/dn_nsp_out.c:1.1.1.1 Tue Jun 26 17:29:33 2001 +++ kernel-acme/net/decnet/dn_nsp_out.c Mon Dec 17 15:04:51 2001 @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -402,7 +403,7 @@ while(list != skb2) { struct dn_skb_cb *cb2 = DN_SKB_CB(skb2); - if (before_or_equal(cb2->segnum, acknum)) + if (dn_before_or_equal(cb2->segnum, acknum)) ack = skb2; /* printk(KERN_DEBUG "ack: %s %04x %04x\n", ack ? "ACK" : "SKIP", (int)cb2->segnum, (int)acknum); */ @@ -439,7 +440,7 @@ * further. */ if (xmit_count == 1) { - if (equal(segnum, acknum)) + if (dn_equal(segnum, acknum)) dn_nsp_rtt(sk, (long)(pkttime - reftime)); if (scp->snd_window < scp->max_window) Index: kernel-acme/net/econet/af_econet.c diff -u kernel-acme/net/econet/af_econet.c:1.1.1.2 kernel-acme/net/econet/af_econet.c:1.1.1.2.10.2 --- kernel-acme/net/econet/af_econet.c:1.1.1.2 Thu Aug 16 18:44:24 2001 +++ kernel-acme/net/econet/af_econet.c Fri Dec 21 02:12:16 2001 @@ -176,10 +176,10 @@ sec->sec_family != AF_ECONET) return -EINVAL; - sk->protinfo.af_econet->cb = sec->cb; - sk->protinfo.af_econet->port = sec->port; - sk->protinfo.af_econet->station = sec->addr.station; - sk->protinfo.af_econet->net = sec->addr.net; + EC_SK(sk)->cb = sec->cb; + EC_SK(sk)->port = sec->port; + EC_SK(sk)->station = sec->addr.station; + EC_SK(sk)->net = sec->addr.net; return 0; } @@ -265,10 +265,10 @@ */ if (saddr == NULL) { - addr.station = sk->protinfo.af_econet->station; - addr.net = sk->protinfo.af_econet->net; - port = sk->protinfo.af_econet->port; - cb = sk->protinfo.af_econet->cb; + addr.station = EC_SK(sk)->station; + addr.net = EC_SK(sk)->net; + port = EC_SK(sk)->port; + cb = EC_SK(sk)->cb; } else { if (msg->msg_namelen < sizeof(struct sockaddr_ec)) return -EINVAL; @@ -455,9 +455,9 @@ return -EOPNOTSUPP; sec->sec_family = AF_ECONET; - sec->port = sk->protinfo.af_econet->port; - sec->addr.station = sk->protinfo.af_econet->station; - sec->addr.net = sk->protinfo.af_econet->net; + sec->port = EC_SK(sk)->port; + sec->addr.station = EC_SK(sk)->station; + sec->addr.net = EC_SK(sk)->net; *uaddr_len = sizeof(*sec); return 0; @@ -535,7 +535,7 @@ MOD_INC_USE_COUNT; err = -ENOBUFS; - sk = sk_alloc(PF_ECONET, GFP_KERNEL, 1); + sk = sk_alloc(PF_ECONET, GFP_KERNEL, 1, NULL); if (sk == NULL) goto out; @@ -543,10 +543,10 @@ sock->ops = &econet_ops; sock_init_data(sock,sk); - sk->protinfo.af_econet = kmalloc(sizeof(struct econet_opt), GFP_KERNEL); - if (sk->protinfo.af_econet == NULL) + EC_SK(sk) = kmalloc(sizeof(struct econet_opt), GFP_KERNEL); + if (EC_SK(sk) == NULL) goto out_free; - memset(sk->protinfo.af_econet, 0, sizeof(struct econet_opt)); + memset(EC_SK(sk), 0, sizeof(struct econet_opt)); sk->zapped=0; sk->family = PF_ECONET; sk->num = protocol; @@ -731,7 +731,7 @@ while (sk) { - struct econet_opt *opt = sk->protinfo.af_econet; + struct econet_opt *opt = EC_SK(sk); if ((opt->port == port || opt->port == 0) && (opt->station == station || opt->station == 0) && (opt->net == net || opt->net == 0)) Index: kernel-acme/net/ipv4/af_inet.c diff -u kernel-acme/net/ipv4/af_inet.c:1.1.1.4 kernel-acme/net/ipv4/af_inet.c:1.1.1.4.6.5 --- kernel-acme/net/ipv4/af_inet.c:1.1.1.4 Tue Nov 6 21:30:36 2001 +++ kernel-acme/net/ipv4/af_inet.c Sat Dec 22 02:14:58 2001 @@ -5,7 +5,7 @@ * * PF_INET protocol family socket handler. * - * Version: $Id: af_inet.c,v 1.1.1.4 2001/11/06 21:30:36 acme Exp $ + * Version: $Id: af_inet.c,v 1.1.1.4.6.5 2001/12/22 02:14:58 acme Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -147,6 +147,11 @@ int (*vlan_ioctl_hook)(unsigned long arg); #endif +/* Per protocol sock slabcache */ +kmem_cache_t *tcp_sk_cachep; +static kmem_cache_t *udp_sk_cachep; +static kmem_cache_t *raw4_sk_cachep; + /* The inetsw table contains everything that inet_create needs to * build a new socket. */ @@ -175,8 +180,8 @@ BUG_TRAP(sk->wmem_queued == 0); BUG_TRAP(sk->forward_alloc == 0); - if (sk->protinfo.af_inet.opt) - kfree(sk->protinfo.af_inet.opt); + if (IP_SK(sk)->opt) + kfree(IP_SK(sk)->opt); dst_release(sk->dst_cache); #ifdef INET_REFCNT_DEBUG atomic_dec(&inet_sock_nr); @@ -312,6 +317,28 @@ return err; } +static __inline__ kmem_cache_t *inet_sk_slab(int protocol) +{ + kmem_cache_t* rc = tcp_sk_cachep; + + if (protocol == IPPROTO_UDP) + rc = udp_sk_cachep; + else if (protocol == IPPROTO_RAW) + rc = raw4_sk_cachep; + return rc; +} + +static __inline__ int inet_sk_size(int protocol) +{ + int rc = TCP_SK_SIZE; + + if (protocol == IPPROTO_UDP) + rc = UDP_SK_SIZE; + else if (protocol == IPPROTO_RAW) + rc = RAW4_SK_SIZE; + return rc; +} + /* * Create an inet socket. */ @@ -323,7 +350,8 @@ struct inet_protosw *answer; sock->state = SS_UNCONNECTED; - sk = sk_alloc(PF_INET, GFP_KERNEL, 1); + sk = sk_alloc(PF_INET, GFP_KERNEL, inet_sk_size(protocol), + inet_sk_slab(protocol)); if (sk == NULL) goto do_oom; @@ -366,15 +394,15 @@ if (SOCK_RAW == sock->type) { sk->num = protocol; if (IPPROTO_RAW == protocol) - sk->protinfo.af_inet.hdrincl = 1; + IP_SK(sk)->hdrincl = 1; } if (ipv4_config.no_pmtu_disc) - sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_DONT; + IP_SK(sk)->pmtudisc = IP_PMTUDISC_DONT; else - sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_WANT; + IP_SK(sk)->pmtudisc = IP_PMTUDISC_WANT; - sk->protinfo.af_inet.id = 0; + IP_SK(sk)->id = 0; sock_init_data(sock,sk); @@ -386,12 +414,12 @@ sk->backlog_rcv = sk->prot->backlog_rcv; - sk->protinfo.af_inet.ttl = sysctl_ip_default_ttl; + IP_SK(sk)->ttl = sysctl_ip_default_ttl; - sk->protinfo.af_inet.mc_loop = 1; - sk->protinfo.af_inet.mc_ttl = 1; - sk->protinfo.af_inet.mc_index = 0; - sk->protinfo.af_inet.mc_list = NULL; + IP_SK(sk)->mc_loop = 1; + IP_SK(sk)->mc_ttl = 1; + IP_SK(sk)->mc_index = 0; + IP_SK(sk)->mc_list = NULL; #ifdef INET_REFCNT_DEBUG atomic_inc(&inet_sock_nr); @@ -495,7 +523,7 @@ * is temporarily down) */ if (sysctl_ip_nonlocal_bind == 0 && - sk->protinfo.af_inet.freebind == 0 && + IP_SK(sk)->freebind == 0 && addr->sin_addr.s_addr != INADDR_ANY && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && @@ -992,8 +1020,8 @@ }; struct net_proto_family inet_family_ops = { - family: PF_INET, - create: inet_create + family: PF_INET, + create: inet_create, }; @@ -1120,6 +1148,15 @@ return -EINVAL; } + tcp_sk_cachep = kmem_cache_create("tcp_sock", TCP_SK_SIZE, 0, + SLAB_HWCACHE_ALIGN, 0, 0); + udp_sk_cachep = kmem_cache_create("udp_sock", UDP_SK_SIZE, 0, + SLAB_HWCACHE_ALIGN, 0, 0); + raw4_sk_cachep = kmem_cache_create("raw4_sock", RAW4_SK_SIZE, 0, + SLAB_HWCACHE_ALIGN, 0, 0); + if (!tcp_sk_cachep || !udp_sk_cachep || !raw4_sk_cachep) + printk(KERN_CRIT __FUNCTION__ + ": Can't create protocol sock SLAB caches!\n"); /* * Tell SOCKET that we are alive... */ Index: kernel-acme/net/ipv4/icmp.c diff -u kernel-acme/net/ipv4/icmp.c:1.1.1.5 kernel-acme/net/ipv4/icmp.c:1.1.1.5.4.1 --- kernel-acme/net/ipv4/icmp.c:1.1.1.5 Fri Nov 23 18:12:50 2001 +++ kernel-acme/net/ipv4/icmp.c Thu Dec 13 23:14:53 2001 @@ -3,7 +3,7 @@ * * Alan Cox, * - * Version: $Id: icmp.c,v 1.1.1.5 2001/11/23 18:12:50 acme Exp $ + * Version: $Id: icmp.c,v 1.1.1.5.4.1 2001/12/13 23:14:53 acme Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -353,7 +353,7 @@ icmp_param->csum=0; icmp_out_count(icmp_param->data.icmph.type); - sk->protinfo.af_inet.tos = skb->nh.iph->tos; + IP_SK(sk)->tos = skb->nh.iph->tos; daddr = ipc.addr = rt->rt_src; ipc.opt = NULL; if (icmp_param->replyopts.optlen) { @@ -497,7 +497,7 @@ icmp_param.skb=skb_in; icmp_param.offset=skb_in->nh.raw - skb_in->data; icmp_out_count(icmp_param.data.icmph.type); - icmp_socket->sk->protinfo.af_inet.tos = tos; + IP_SK(icmp_socket->sk)->tos = tos; ipc.addr = iph->saddr; ipc.opt = &icmp_param.replyopts; if (icmp_param.replyopts.srr) { @@ -996,8 +996,8 @@ panic("Failed to create the ICMP control socket.\n"); icmp_socket->sk->allocation=GFP_ATOMIC; icmp_socket->sk->sndbuf = SK_WMEM_MAX*2; - icmp_socket->sk->protinfo.af_inet.ttl = MAXTTL; - icmp_socket->sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_DONT; + IP_SK(icmp_socket->sk)->ttl = MAXTTL; + IP_SK(icmp_socket->sk)->pmtudisc = IP_PMTUDISC_DONT; /* Unhash it so that IP input processing does not even * see it, we do not wish this socket to see incoming Index: kernel-acme/net/ipv4/igmp.c diff -u kernel-acme/net/ipv4/igmp.c:1.1.1.2 kernel-acme/net/ipv4/igmp.c:1.1.1.2.10.1 --- kernel-acme/net/ipv4/igmp.c:1.1.1.2 Thu Aug 16 21:59:29 2001 +++ kernel-acme/net/ipv4/igmp.c Thu Dec 13 23:14:53 2001 @@ -8,7 +8,7 @@ * the older version didn't come out right using gcc 2.5.8, the newer one * seems to fall out with gcc 2.6.2. * - * Version: $Id: igmp.c,v 1.1.1.2 2001/08/16 21:59:29 acme Exp $ + * Version: $Id: igmp.c,v 1.1.1.2.10.1 2001/12/13 23:14:53 acme Exp $ * * Authors: * Alan Cox @@ -668,7 +668,7 @@ iml = (struct ip_mc_socklist *)sock_kmalloc(sk, sizeof(*iml), GFP_KERNEL); err = -EADDRINUSE; - for (i=sk->protinfo.af_inet.mc_list; i; i=i->next) { + for (i=IP_SK(sk)->mc_list; i; i=i->next) { if (memcmp(&i->multi, imr, sizeof(*imr)) == 0) { /* New style additions are reference counted */ if (imr->imr_address.s_addr == 0) { @@ -683,9 +683,9 @@ if (iml == NULL || count >= sysctl_igmp_max_memberships) goto done; memcpy(&iml->multi, imr, sizeof(*imr)); - iml->next = sk->protinfo.af_inet.mc_list; + iml->next = IP_SK(sk)->mc_list; iml->count = 1; - sk->protinfo.af_inet.mc_list = iml; + IP_SK(sk)->mc_list = iml; ip_mc_inc_group(in_dev, addr); iml = NULL; err = 0; @@ -706,7 +706,7 @@ struct ip_mc_socklist *iml, **imlp; rtnl_lock(); - for (imlp=&sk->protinfo.af_inet.mc_list; (iml=*imlp)!=NULL; imlp=&iml->next) { + for (imlp=&IP_SK(sk)->mc_list; (iml=*imlp)!=NULL; imlp=&iml->next) { if (iml->multi.imr_multiaddr.s_addr==imr->imr_multiaddr.s_addr && iml->multi.imr_address.s_addr==imr->imr_address.s_addr && (!imr->imr_ifindex || iml->multi.imr_ifindex==imr->imr_ifindex)) { @@ -740,13 +740,13 @@ { struct ip_mc_socklist *iml; - if (sk->protinfo.af_inet.mc_list == NULL) + if (IP_SK(sk)->mc_list == NULL) return; rtnl_lock(); - while ((iml=sk->protinfo.af_inet.mc_list) != NULL) { + while ((iml=IP_SK(sk)->mc_list) != NULL) { struct in_device *in_dev; - sk->protinfo.af_inet.mc_list = iml->next; + IP_SK(sk)->mc_list = iml->next; if ((in_dev = inetdev_by_index(iml->multi.imr_ifindex)) != NULL) { ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr); Index: kernel-acme/net/ipv4/ip_output.c diff -u kernel-acme/net/ipv4/ip_output.c:1.1.1.7 kernel-acme/net/ipv4/ip_output.c:1.1.1.7.6.1 --- kernel-acme/net/ipv4/ip_output.c:1.1.1.7 Tue Nov 6 20:13:46 2001 +++ kernel-acme/net/ipv4/ip_output.c Thu Dec 13 23:14:53 2001 @@ -5,7 +5,7 @@ * * The Internet Protocol (IP) output module. * - * Version: $Id: ip_output.c,v 1.1.1.7 2001/11/06 20:13:46 acme Exp $ + * Version: $Id: ip_output.c,v 1.1.1.7.6.1 2001/12/13 23:14:53 acme Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -133,11 +133,11 @@ iph->version = 4; iph->ihl = 5; - iph->tos = sk->protinfo.af_inet.tos; + iph->tos = IP_SK(sk)->tos; iph->frag_off = 0; if (ip_dont_fragment(sk, &rt->u.dst)) iph->frag_off |= htons(IP_DF); - iph->ttl = sk->protinfo.af_inet.ttl; + iph->ttl = IP_SK(sk)->ttl; iph->daddr = rt->rt_dst; iph->saddr = rt->rt_src; iph->protocol = sk->protocol; @@ -214,7 +214,7 @@ */ if (rt->rt_flags&RTCF_MULTICAST) { - if ((!sk || sk->protinfo.af_inet.mc_loop) + if ((!sk || IP_SK(sk)->mc_loop) #ifdef CONFIG_IP_MROUTE /* Small optimization: do not loopback not local frames, which returned after forwarding; they will be dropped @@ -341,7 +341,7 @@ int ip_queue_xmit(struct sk_buff *skb) { struct sock *sk = skb->sk; - struct ip_options *opt = sk->protinfo.af_inet.opt; + struct ip_options *opt = IP_SK(sk)->opt; struct rtable *rt; struct iphdr *iph; @@ -381,10 +381,10 @@ /* OK, we know where to send it, allocate and build IP header. */ iph = (struct iphdr *) skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0)); - *((__u16 *)iph) = htons((4 << 12) | (5 << 8) | (sk->protinfo.af_inet.tos & 0xff)); + *((__u16 *)iph) = htons((4 << 12) | (5 << 8) | (IP_SK(sk)->tos & 0xff)); iph->tot_len = htons(skb->len); iph->frag_off = 0; - iph->ttl = sk->protinfo.af_inet.ttl; + iph->ttl = IP_SK(sk)->ttl; iph->protocol = sk->protocol; iph->saddr = rt->rt_src; iph->daddr = rt->rt_dst; @@ -499,7 +499,7 @@ * Don't fragment packets for path mtu discovery. */ - if (offset > 0 && sk->protinfo.af_inet.pmtudisc==IP_PMTUDISC_DO) { + if (offset > 0 && IP_SK(sk)->pmtudisc==IP_PMTUDISC_DO) { ip_local_error(sk, EMSGSIZE, rt->rt_dst, sk->dport, mtu); return -EMSGSIZE; } @@ -510,7 +510,7 @@ * Begin outputting the bytes. */ - id = sk->protinfo.af_inet.id++; + id = IP_SK(sk)->id++; do { char *data; @@ -553,7 +553,7 @@ ip_options_build(skb, opt, ipc->addr, rt, offset); } - iph->tos = sk->protinfo.af_inet.tos; + iph->tos = IP_SK(sk)->tos; iph->tot_len = htons(fraglen - fragheaderlen + iph->ihl*4); iph->frag_off = htons(offset>>3)|mf|df; iph->id = id; @@ -573,9 +573,9 @@ mf = htons(IP_MF); } if (rt->rt_type == RTN_MULTICAST) - iph->ttl = sk->protinfo.af_inet.mc_ttl; + iph->ttl = IP_SK(sk)->mc_ttl; else - iph->ttl = sk->protinfo.af_inet.ttl; + iph->ttl = IP_SK(sk)->ttl; iph->protocol = sk->protocol; iph->check = 0; iph->saddr = rt->rt_src; @@ -603,7 +603,7 @@ skb->dst->dev, output_maybe_reroute); if (err) { if (err > 0) - err = sk->protinfo.af_inet.recverr ? net_xmit_errno(err) : 0; + err = IP_SK(sk)->recverr ? net_xmit_errno(err) : 0; if (err) goto error; } @@ -645,7 +645,7 @@ * choice RAW frames within 20 bytes of maximum size(rare) to the long path */ - if (!sk->protinfo.af_inet.hdrincl) { + if (!IP_SK(sk)->hdrincl) { length += sizeof(struct iphdr); /* @@ -687,16 +687,16 @@ skb->nh.iph = iph = (struct iphdr *)skb_put(skb, length); - if(!sk->protinfo.af_inet.hdrincl) { + if(!IP_SK(sk)->hdrincl) { iph->version=4; iph->ihl=5; - iph->tos=sk->protinfo.af_inet.tos; + iph->tos=IP_SK(sk)->tos; iph->tot_len = htons(length); iph->frag_off = df; - iph->ttl=sk->protinfo.af_inet.mc_ttl; + iph->ttl=IP_SK(sk)->mc_ttl; ip_select_ident(iph, &rt->u.dst, sk); if (rt->rt_type != RTN_MULTICAST) - iph->ttl=sk->protinfo.af_inet.ttl; + iph->ttl=IP_SK(sk)->ttl; iph->protocol=sk->protocol; iph->saddr=rt->rt_src; iph->daddr=rt->rt_dst; @@ -713,7 +713,7 @@ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, output_maybe_reroute); if (err > 0) - err = sk->protinfo.af_inet.recverr ? net_xmit_errno(err) : 0; + err = IP_SK(sk)->recverr ? net_xmit_errno(err) : 0; if (err) goto error; out: @@ -974,7 +974,7 @@ with locally disabled BH and that sk cannot be already spinlocked. */ bh_lock_sock(sk); - sk->protinfo.af_inet.tos = skb->nh.iph->tos; + IP_SK(sk)->tos = skb->nh.iph->tos; sk->priority = skb->priority; sk->protocol = skb->nh.iph->protocol; ip_build_xmit(sk, ip_reply_glue_bits, arg, len, &ipc, rt, MSG_DONTWAIT); Index: kernel-acme/net/ipv4/ip_sockglue.c diff -u kernel-acme/net/ipv4/ip_sockglue.c:1.1.1.4 kernel-acme/net/ipv4/ip_sockglue.c:1.1.1.4.6.1 --- kernel-acme/net/ipv4/ip_sockglue.c:1.1.1.4 Tue Nov 6 21:30:35 2001 +++ kernel-acme/net/ipv4/ip_sockglue.c Thu Dec 13 23:14:53 2001 @@ -5,7 +5,7 @@ * * The IP to API glue. * - * Version: $Id: ip_sockglue.c,v 1.1.1.4 2001/11/06 21:30:35 acme Exp $ + * Version: $Id: ip_sockglue.c,v 1.1.1.4.6.1 2001/12/13 23:14:53 acme Exp $ * * Authors: see ip.c * @@ -110,7 +110,7 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) { - unsigned flags = skb->sk->protinfo.af_inet.cmsg_flags; + unsigned flags = IP_SK(skb->sk)->cmsg_flags; /* Ordered by supposed usage frequency */ if (flags & 1) @@ -236,7 +236,7 @@ { struct sock_exterr_skb *serr; - if (!sk->protinfo.af_inet.recverr) + if (!IP_SK(sk)->recverr) return; skb = skb_clone(skb, GFP_ATOMIC); @@ -266,7 +266,7 @@ struct iphdr *iph; struct sk_buff *skb; - if (!sk->protinfo.af_inet.recverr) + if (!IP_SK(sk)->recverr) return; skb = alloc_skb(sizeof(struct iphdr), GFP_ATOMIC); @@ -344,7 +344,7 @@ sin->sin_addr.s_addr = skb->nh.iph->saddr; sin->sin_port = 0; memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); - if (sk->protinfo.af_inet.cmsg_flags) + if (IP_SK(sk)->cmsg_flags) ip_cmsg_recv(msg, skb); } @@ -425,7 +425,7 @@ if (err) break; if (sk->type == SOCK_STREAM) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) if (sk->family == PF_INET || (!((1<state)&(TCPF_LISTEN|TCPF_CLOSE)) @@ -438,53 +438,53 @@ } #endif } - opt = xchg(&sk->protinfo.af_inet.opt, opt); + opt = xchg(&IP_SK(sk)->opt, opt); if (opt) kfree(opt); break; } case IP_PKTINFO: if (val) - sk->protinfo.af_inet.cmsg_flags |= IP_CMSG_PKTINFO; + IP_SK(sk)->cmsg_flags |= IP_CMSG_PKTINFO; else - sk->protinfo.af_inet.cmsg_flags &= ~IP_CMSG_PKTINFO; + IP_SK(sk)->cmsg_flags &= ~IP_CMSG_PKTINFO; break; case IP_RECVTTL: if (val) - sk->protinfo.af_inet.cmsg_flags |= IP_CMSG_TTL; + IP_SK(sk)->cmsg_flags |= IP_CMSG_TTL; else - sk->protinfo.af_inet.cmsg_flags &= ~IP_CMSG_TTL; + IP_SK(sk)->cmsg_flags &= ~IP_CMSG_TTL; break; case IP_RECVTOS: if (val) - sk->protinfo.af_inet.cmsg_flags |= IP_CMSG_TOS; + IP_SK(sk)->cmsg_flags |= IP_CMSG_TOS; else - sk->protinfo.af_inet.cmsg_flags &= ~IP_CMSG_TOS; + IP_SK(sk)->cmsg_flags &= ~IP_CMSG_TOS; break; case IP_RECVOPTS: if (val) - sk->protinfo.af_inet.cmsg_flags |= IP_CMSG_RECVOPTS; + IP_SK(sk)->cmsg_flags |= IP_CMSG_RECVOPTS; else - sk->protinfo.af_inet.cmsg_flags &= ~IP_CMSG_RECVOPTS; + IP_SK(sk)->cmsg_flags &= ~IP_CMSG_RECVOPTS; break; case IP_RETOPTS: if (val) - sk->protinfo.af_inet.cmsg_flags |= IP_CMSG_RETOPTS; + IP_SK(sk)->cmsg_flags |= IP_CMSG_RETOPTS; else - sk->protinfo.af_inet.cmsg_flags &= ~IP_CMSG_RETOPTS; + IP_SK(sk)->cmsg_flags &= ~IP_CMSG_RETOPTS; break; case IP_TOS: /* This sets both TOS and Precedence */ if (sk->type == SOCK_STREAM) { val &= ~3; - val |= sk->protinfo.af_inet.tos & 3; + val |= IP_SK(sk)->tos & 3; } if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP && !capable(CAP_NET_ADMIN)) { err = -EPERM; break; } - if (sk->protinfo.af_inet.tos != val) { - sk->protinfo.af_inet.tos=val; + if (IP_SK(sk)->tos != val) { + IP_SK(sk)->tos=val; sk->priority = rt_tos2priority(val); sk_dst_reset(sk); } @@ -496,22 +496,22 @@ val = sysctl_ip_default_ttl; if(val<1||val>255) goto e_inval; - sk->protinfo.af_inet.ttl=val; + IP_SK(sk)->ttl=val; break; case IP_HDRINCL: if(sk->type!=SOCK_RAW) { err = -ENOPROTOOPT; break; } - sk->protinfo.af_inet.hdrincl=val?1:0; + IP_SK(sk)->hdrincl=val?1:0; break; case IP_MTU_DISCOVER: if (val<0 || val>2) goto e_inval; - sk->protinfo.af_inet.pmtudisc = val; + IP_SK(sk)->pmtudisc = val; break; case IP_RECVERR: - sk->protinfo.af_inet.recverr = !!val; + IP_SK(sk)->recverr = !!val; if (!val) skb_queue_purge(&sk->error_queue); break; @@ -524,12 +524,12 @@ val = 1; if (val < 0 || val > 255) goto e_inval; - sk->protinfo.af_inet.mc_ttl=val; + IP_SK(sk)->mc_ttl=val; break; case IP_MULTICAST_LOOP: if (optlen<1) goto e_inval; - sk->protinfo.af_inet.mc_loop = val ? 1 : 0; + IP_SK(sk)->mc_loop = val ? 1 : 0; break; case IP_MULTICAST_IF: { @@ -555,8 +555,8 @@ if (!mreq.imr_ifindex) { if (mreq.imr_address.s_addr == INADDR_ANY) { - sk->protinfo.af_inet.mc_index = 0; - sk->protinfo.af_inet.mc_addr = 0; + IP_SK(sk)->mc_index = 0; + IP_SK(sk)->mc_addr = 0; err = 0; break; } @@ -577,8 +577,8 @@ if (sk->bound_dev_if && mreq.imr_ifindex != sk->bound_dev_if) break; - sk->protinfo.af_inet.mc_index = mreq.imr_ifindex; - sk->protinfo.af_inet.mc_addr = mreq.imr_address.s_addr; + IP_SK(sk)->mc_index = mreq.imr_ifindex; + IP_SK(sk)->mc_addr = mreq.imr_address.s_addr; err = 0; break; } @@ -613,7 +613,7 @@ case IP_FREEBIND: if (optlen<1) goto e_inval; - sk->protinfo.af_inet.freebind = !!val; + IP_SK(sk)->freebind = !!val; break; default: @@ -666,10 +666,10 @@ unsigned char optbuf[sizeof(struct ip_options)+40]; struct ip_options * opt = (struct ip_options*)optbuf; opt->optlen = 0; - if (sk->protinfo.af_inet.opt) - memcpy(optbuf, sk->protinfo.af_inet.opt, + if (IP_SK(sk)->opt) + memcpy(optbuf, IP_SK(sk)->opt, sizeof(struct ip_options)+ - sk->protinfo.af_inet.opt->optlen); + IP_SK(sk)->opt->optlen); release_sock(sk); if (opt->optlen == 0) @@ -685,31 +685,31 @@ return 0; } case IP_PKTINFO: - val = (sk->protinfo.af_inet.cmsg_flags & IP_CMSG_PKTINFO) != 0; + val = (IP_SK(sk)->cmsg_flags & IP_CMSG_PKTINFO) != 0; break; case IP_RECVTTL: - val = (sk->protinfo.af_inet.cmsg_flags & IP_CMSG_TTL) != 0; + val = (IP_SK(sk)->cmsg_flags & IP_CMSG_TTL) != 0; break; case IP_RECVTOS: - val = (sk->protinfo.af_inet.cmsg_flags & IP_CMSG_TOS) != 0; + val = (IP_SK(sk)->cmsg_flags & IP_CMSG_TOS) != 0; break; case IP_RECVOPTS: - val = (sk->protinfo.af_inet.cmsg_flags & IP_CMSG_RECVOPTS) != 0; + val = (IP_SK(sk)->cmsg_flags & IP_CMSG_RECVOPTS) != 0; break; case IP_RETOPTS: - val = (sk->protinfo.af_inet.cmsg_flags & IP_CMSG_RETOPTS) != 0; + val = (IP_SK(sk)->cmsg_flags & IP_CMSG_RETOPTS) != 0; break; case IP_TOS: - val=sk->protinfo.af_inet.tos; + val=IP_SK(sk)->tos; break; case IP_TTL: - val=sk->protinfo.af_inet.ttl; + val=IP_SK(sk)->ttl; break; case IP_HDRINCL: - val=sk->protinfo.af_inet.hdrincl; + val=IP_SK(sk)->hdrincl; break; case IP_MTU_DISCOVER: - val=sk->protinfo.af_inet.pmtudisc; + val=IP_SK(sk)->pmtudisc; break; case IP_MTU: { @@ -727,19 +727,19 @@ break; } case IP_RECVERR: - val=sk->protinfo.af_inet.recverr; + val=IP_SK(sk)->recverr; break; case IP_MULTICAST_TTL: - val=sk->protinfo.af_inet.mc_ttl; + val=IP_SK(sk)->mc_ttl; break; case IP_MULTICAST_LOOP: - val=sk->protinfo.af_inet.mc_loop; + val=IP_SK(sk)->mc_loop; break; case IP_MULTICAST_IF: { struct in_addr addr; len = min_t(unsigned int, len, sizeof(struct in_addr)); - addr.s_addr = sk->protinfo.af_inet.mc_addr; + addr.s_addr = IP_SK(sk)->mc_addr; release_sock(sk); if(put_user(len, optlen)) @@ -761,23 +761,23 @@ msg.msg_controllen = len; msg.msg_flags = 0; - if (sk->protinfo.af_inet.cmsg_flags&IP_CMSG_PKTINFO) { + if (IP_SK(sk)->cmsg_flags&IP_CMSG_PKTINFO) { struct in_pktinfo info; info.ipi_addr.s_addr = sk->rcv_saddr; info.ipi_spec_dst.s_addr = sk->rcv_saddr; - info.ipi_ifindex = sk->protinfo.af_inet.mc_index; + info.ipi_ifindex = IP_SK(sk)->mc_index; put_cmsg(&msg, SOL_IP, IP_PKTINFO, sizeof(info), &info); } - if (sk->protinfo.af_inet.cmsg_flags&IP_CMSG_TTL) { - int hlim = sk->protinfo.af_inet.mc_ttl; + if (IP_SK(sk)->cmsg_flags&IP_CMSG_TTL) { + int hlim = IP_SK(sk)->mc_ttl; put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim); } len -= msg.msg_controllen; return put_user(len, optlen); } case IP_FREEBIND: - val = sk->protinfo.af_inet.freebind; + val = IP_SK(sk)->freebind; break; default: #ifdef CONFIG_NETFILTER Index: kernel-acme/net/ipv4/ipconfig.c diff -u kernel-acme/net/ipv4/ipconfig.c:1.1.1.5 kernel-acme/net/ipv4/ipconfig.c:1.1.1.5.4.1 --- kernel-acme/net/ipv4/ipconfig.c:1.1.1.5 Fri Nov 23 18:12:43 2001 +++ kernel-acme/net/ipv4/ipconfig.c Tue Dec 18 04:23:42 2001 @@ -1,5 +1,5 @@ /* - * $Id: ipconfig.c,v 1.1.1.5 2001/11/23 18:12:43 acme Exp $ + * $Id: ipconfig.c,v 1.1.1.5.4.1 2001/12/18 04:23:42 acme Exp $ * * Automatic Configuration of IP -- use DHCP, BOOTP, RARP, or * user-supplied information to configure own IP address and routes. @@ -52,7 +52,7 @@ #include #include -#include +#include #include /* Define this to allow debugging output */ Index: kernel-acme/net/ipv4/raw.c diff -u kernel-acme/net/ipv4/raw.c:1.1.1.3 kernel-acme/net/ipv4/raw.c:1.1.1.3.10.2 --- kernel-acme/net/ipv4/raw.c:1.1.1.3 Thu Aug 16 21:43:11 2001 +++ kernel-acme/net/ipv4/raw.c Mon Dec 17 15:04:52 2001 @@ -5,7 +5,7 @@ * * RAW - implementation of IP "raw" sockets. * - * Version: $Id: raw.c,v 1.1.1.3 2001/08/16 21:43:11 acme Exp $ + * Version: $Id: raw.c,v 1.1.1.3.10.2 2001/12/17 15:04:52 acme Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -122,7 +122,7 @@ type = skb->h.icmph->type; if (type < 32) { - __u32 data = sk->tp_pinfo.tp_raw4.filter.data; + __u32 data = RAW4_PINFO(sk)->filter.data; return ((1 << type) & data) != 0; } @@ -186,7 +186,7 @@ 2. Socket is connected (otherwise the error indication is useless without ip_recverr and error is hard. */ - if (!sk->protinfo.af_inet.recverr && sk->state != TCP_ESTABLISHED) + if (!IP_SK(sk)->recverr && sk->state != TCP_ESTABLISHED) return; switch (type) { @@ -207,22 +207,22 @@ err = icmp_err_convert[code].errno; harderr = icmp_err_convert[code].fatal; if (code == ICMP_FRAG_NEEDED) { - harderr = sk->protinfo.af_inet.pmtudisc != + harderr = IP_SK(sk)->pmtudisc != IP_PMTUDISC_DONT; err = EMSGSIZE; } } - if (sk->protinfo.af_inet.recverr) { + if (IP_SK(sk)->recverr) { struct iphdr *iph = (struct iphdr*)skb->data; u8 *payload = skb->data + (iph->ihl << 2); - if (sk->protinfo.af_inet.hdrincl) + if (IP_SK(sk)->hdrincl) payload = skb->data; ip_icmp_error(sk, skb, err, 0, info, payload); } - if (sk->protinfo.af_inet.recverr || harderr) { + if (IP_SK(sk)->recverr || harderr) { sk->err = err; sk->error_report(sk); } @@ -382,14 +382,14 @@ ipc.addr = daddr; if (!ipc.opt) - ipc.opt = sk->protinfo.af_inet.opt; + ipc.opt = IP_SK(sk)->opt; if (ipc.opt) { err = -EINVAL; /* Linux does not mangle headers on raw sockets, * so that IP options + IP_HDRINCL is non-sense. */ - if (sk->protinfo.af_inet.hdrincl) + if (IP_SK(sk)->hdrincl) goto done; if (ipc.opt->srr) { if (!daddr) @@ -397,15 +397,15 @@ daddr = ipc.opt->faddr; } } - tos = RT_TOS(sk->protinfo.af_inet.tos) | sk->localroute; + tos = RT_TOS(IP_SK(sk)->tos) | sk->localroute; if (msg->msg_flags & MSG_DONTROUTE) tos |= RTO_ONLINK; if (MULTICAST(daddr)) { if (!ipc.oif) - ipc.oif = sk->protinfo.af_inet.mc_index; + ipc.oif = IP_SK(sk)->mc_index; if (!rfh.saddr) - rfh.saddr = sk->protinfo.af_inet.mc_addr; + rfh.saddr = IP_SK(sk)->mc_addr; } err = ip_route_output(&rt, daddr, rfh.saddr, tos, ipc.oif); @@ -426,7 +426,7 @@ rfh.dst = &rt->u.dst; if (!ipc.addr) ipc.addr = rt->rt_dst; - err = ip_build_xmit(sk, sk->protinfo.af_inet.hdrincl ? raw_getrawfrag : + err = ip_build_xmit(sk, IP_SK(sk)->hdrincl ? raw_getrawfrag : raw_getfrag, &rfh, len, &ipc, rt, msg->msg_flags); done: @@ -522,7 +522,7 @@ sin->sin_addr.s_addr = skb->nh.iph->saddr; memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); } - if (sk->protinfo.af_inet.cmsg_flags) + if (IP_SK(sk)->cmsg_flags) ip_cmsg_recv(msg, skb); done: skb_free_datagram(sk, skb); @@ -531,7 +531,7 @@ static int raw_init(struct sock *sk) { - struct raw_opt *tp = &(sk->tp_pinfo.tp_raw4); + struct raw_opt *tp = RAW4_PINFO(sk); if (sk->num == IPPROTO_ICMP) memset(&tp->filter, 0, sizeof(tp->filter)); return 0; @@ -541,7 +541,7 @@ { if (optlen > sizeof(struct icmp_filter)) optlen = sizeof(struct icmp_filter); - if (copy_from_user(&sk->tp_pinfo.tp_raw4.filter, optval, optlen)) + if (copy_from_user(&RAW4_PINFO(sk)->filter, optval, optlen)) return -EFAULT; return 0; } @@ -559,7 +559,7 @@ len = sizeof(struct icmp_filter); ret = -EFAULT; if (put_user(len, optlen) || - copy_to_user(optval, &sk->tp_pinfo.tp_raw4.filter, len)) + copy_to_user(optval, &RAW4_PINFO(sk)->filter, len)) goto out; ret = 0; out: return ret; Index: kernel-acme/net/ipv4/syncookies.c diff -u kernel-acme/net/ipv4/syncookies.c:1.1.1.3 kernel-acme/net/ipv4/syncookies.c:1.1.1.3.6.1 --- kernel-acme/net/ipv4/syncookies.c:1.1.1.3 Tue Nov 6 21:30:36 2001 +++ kernel-acme/net/ipv4/syncookies.c Tue Dec 18 04:23:42 2001 @@ -9,7 +9,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * $Id: syncookies.c,v 1.1.1.3 2001/11/06 21:30:36 acme Exp $ + * $Id: syncookies.c,v 1.1.1.3.6.1 2001/12/18 04:23:42 acme Exp $ * * Missing: IPv6 support. */ @@ -52,7 +52,7 @@ const __u16 mss = *mssp; - sk->tp_pinfo.af_tcp.last_synq_overflow = jiffies; + TCP_PINFO(sk)->last_synq_overflow = jiffies; /* XXX sort msstab[] by probability? Binary search? */ for (mssind = 0; mss > msstab[mssind + 1]; mssind++) @@ -98,7 +98,7 @@ struct open_request *req, struct dst_entry *dst) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct sock *child; child = tp->af_specific->syn_recv_sock(sk, skb, req, dst); @@ -123,7 +123,7 @@ if (!sysctl_tcp_syncookies || !skb->h.th->ack) goto out; - if (time_after(jiffies, sk->tp_pinfo.af_tcp.last_synq_overflow + TCP_TIMEOUT_INIT) || + if (time_after(jiffies, TCP_PINFO(sk)->last_synq_overflow + TCP_TIMEOUT_INIT) || (mss = cookie_check(skb, cookie)) == 0) { NET_INC_STATS_BH(SyncookiesFailed); goto out; Index: kernel-acme/net/ipv4/tcp.c diff -u kernel-acme/net/ipv4/tcp.c:1.1.1.6 kernel-acme/net/ipv4/tcp.c:1.1.1.6.6.2 --- kernel-acme/net/ipv4/tcp.c:1.1.1.6 Tue Nov 6 21:30:35 2001 +++ kernel-acme/net/ipv4/tcp.c Mon Dec 17 03:11:13 2001 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp.c,v 1.1.1.6 2001/11/06 21:30:35 acme Exp $ + * Version: $Id: tcp.c,v 1.1.1.6.6.2 2001/12/17 03:11:13 acme Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -363,7 +363,7 @@ */ static __inline__ unsigned int tcp_listen_poll(struct sock *sk, poll_table *wait) { - return sk->tp_pinfo.af_tcp.accept_queue ? (POLLIN | POLLRDNORM) : 0; + return TCP_PINFO(sk)->accept_queue ? (POLLIN | POLLRDNORM) : 0; } /* @@ -377,7 +377,7 @@ { unsigned int mask; struct sock *sk = sock->sk; - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); poll_wait(file, sk->sleep, wait); if (sk->state == TCP_LISTEN) @@ -477,7 +477,7 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int answ; switch(cmd) { @@ -524,7 +524,7 @@ int tcp_listen_start(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct tcp_listen_opt *lopt; sk->max_ack_backlog = 0; @@ -576,7 +576,7 @@ static void tcp_listen_stop (struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct tcp_listen_opt *lopt = tp->listen_opt; struct open_request *acc_req = tp->accept_queue; struct open_request *req; @@ -663,7 +663,7 @@ __set_task_state(tsk, TASK_INTERRUPTIBLE); add_wait_queue(sk->sleep, &wait); - sk->tp_pinfo.af_tcp.write_pending++; + TCP_PINFO(sk)->write_pending++; release_sock(sk); *timeo_p = schedule_timeout(*timeo_p); @@ -671,7 +671,7 @@ __set_task_state(tsk, TASK_RUNNING); remove_wait_queue(sk->sleep, &wait); - sk->tp_pinfo.af_tcp.write_pending--; + TCP_PINFO(sk)->write_pending--; } return 0; } @@ -711,12 +711,12 @@ break; set_bit(SOCK_NOSPACE, &sk->socket->flags); - sk->tp_pinfo.af_tcp.write_pending++; + TCP_PINFO(sk)->write_pending++; release_sock(sk); if (!tcp_memory_free(sk) || vm_wait) current_timeo = schedule_timeout(current_timeo); lock_sock(sk); - sk->tp_pinfo.af_tcp.write_pending--; + TCP_PINFO(sk)->write_pending--; if (vm_wait) { vm_wait -= current_timeo; @@ -825,7 +825,7 @@ ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int mss_now; int err; ssize_t copied; @@ -950,8 +950,8 @@ return res; } -#define TCP_PAGE(sk) (sk->tp_pinfo.af_tcp.sndmsg_page) -#define TCP_OFF(sk) (sk->tp_pinfo.af_tcp.sndmsg_off) +#define TCP_PAGE(sk) (TCP_PINFO(sk)->sndmsg_page) +#define TCP_OFF(sk) (TCP_PINFO(sk)->sndmsg_off) static inline int tcp_copy_to_page(struct sock *sk, char *from, struct sk_buff *skb, @@ -1015,7 +1015,7 @@ int err, copied; long timeo; - tp = &(sk->tp_pinfo.af_tcp); + tp = TCP_PINFO(sk); lock_sock(sk); TCP_CHECK_TIMER(sk); @@ -1216,7 +1216,7 @@ struct msghdr *msg, int len, int flags, int *addr_len) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); /* No URG data to read. */ if (sk->urginline || !tp->urg_data || tp->urg_data == TCP_URG_READ) @@ -1277,7 +1277,7 @@ */ static void cleanup_rbuf(struct sock *sk, int copied) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int time_to_ack = 0; #if TCP_DEBUG @@ -1362,7 +1362,7 @@ static void tcp_prequeue_process(struct sock *sk) { struct sk_buff *skb; - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); net_statistics[smp_processor_id()*2+1].TCPPrequeued += skb_queue_len(&tp->ucopy.prequeue); @@ -1387,7 +1387,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, int len, int nonblock, int flags, int *addr_len) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int copied = 0; u32 peek_seq; u32 *seq; @@ -1936,7 +1936,7 @@ */ if (sk->state == TCP_FIN_WAIT2) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); if (tp->linger2 < 0) { tcp_set_state(sk, TCP_CLOSE); tcp_send_active_reset(sk, GFP_ATOMIC); @@ -1988,7 +1988,7 @@ int tcp_disconnect(struct sock *sk, int flags) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); int old_state; int err = 0; @@ -2021,8 +2021,10 @@ sk->rcv_saddr = 0; sk->saddr = 0; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - memset(&sk->net_pinfo.af_inet6.saddr, 0, 16); - memset(&sk->net_pinfo.af_inet6.rcv_saddr, 0, 16); + if (sk->family == PF_INET6) { + memset(&IP6_PINFO(sk)->saddr, 0, 16); + memset(&IP6_PINFO(sk)->rcv_saddr, 0, 16); + } #endif } @@ -2078,11 +2080,11 @@ for (;;) { current->state = TASK_INTERRUPTIBLE; release_sock(sk); - if (sk->tp_pinfo.af_tcp.accept_queue == NULL) + if (TCP_PINFO(sk)->accept_queue == NULL) timeo = schedule_timeout(timeo); lock_sock(sk); err = 0; - if (sk->tp_pinfo.af_tcp.accept_queue) + if (TCP_PINFO(sk)->accept_queue) break; err = -EINVAL; if (sk->state != TCP_LISTEN) @@ -2105,7 +2107,7 @@ struct sock *tcp_accept(struct sock *sk, int flags, int *err) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); struct open_request *req; struct sock *newsk; int error; @@ -2157,7 +2159,7 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int val; int err = 0; @@ -2316,7 +2318,7 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int val, len; if(level != SOL_TCP) Index: kernel-acme/net/ipv4/tcp_input.c diff -u kernel-acme/net/ipv4/tcp_input.c:1.1.1.7 kernel-acme/net/ipv4/tcp_input.c:1.1.1.7.4.1 --- kernel-acme/net/ipv4/tcp_input.c:1.1.1.7 Fri Nov 23 18:11:55 2001 +++ kernel-acme/net/ipv4/tcp_input.c Thu Dec 13 23:14:53 2001 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.1.1.7 2001/11/23 18:11:55 acme Exp $ + * Version: $Id: tcp_input.c,v 1.1.1.7.4.1 2001/12/13 23:14:53 acme Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -190,7 +190,7 @@ static void tcp_fixup_sndbuf(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int sndmem = tp->mss_clamp+MAX_TCP_HEADER+16+sizeof(struct sk_buff); if (sk->sndbuf < 3*sndmem) @@ -268,7 +268,7 @@ static void tcp_fixup_rcvbuf(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int rcvmem = tp->advmss+MAX_TCP_HEADER+16+sizeof(struct sk_buff); /* Try to select rcvbuf so that 4 mss-sized segments @@ -286,7 +286,7 @@ */ static void tcp_init_buffer_space(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int maxwin; if (!(sk->userlocks&SOCK_RCVBUF_LOCK)) @@ -512,7 +512,7 @@ */ void tcp_update_metrics(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct dst_entry *dst = __sk_dst_get(sk); dst_confirm(dst); @@ -620,7 +620,7 @@ static void tcp_init_metrics(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct dst_entry *dst = __sk_dst_get(sk); if (dst == NULL) @@ -762,7 +762,7 @@ static int tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_una) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); unsigned char *ptr = ack_skb->h.raw + TCP_SKB_CB(ack_skb)->sacked; struct tcp_sack_block *sp = (struct tcp_sack_block *)(ptr+2); int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3; @@ -977,7 +977,7 @@ */ void tcp_enter_loss(struct sock *sk, int how) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); struct sk_buff *skb; int cnt = 0; @@ -1493,7 +1493,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, int prior_packets, int flag) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int is_dupack = (tp->snd_una == prior_snd_una && !(flag&FLAG_NOT_DUP)); /* Some technical things: @@ -1735,7 +1735,7 @@ /* Remove acknowledged frames from the retransmission queue. */ static int tcp_clean_rtx_queue(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct sk_buff *skb; __u32 now = tcp_time_stamp; int acked = 0; @@ -1820,7 +1820,7 @@ static void tcp_ack_probe(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); /* Was it a usable window open? */ @@ -1897,7 +1897,7 @@ /* This routine deals with incoming acks, but not outgoing ones. */ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); u32 prior_snd_una = tp->snd_una; u32 ack_seq = TCP_SKB_CB(skb)->seq; u32 ack = TCP_SKB_CB(skb)->ack_seq; @@ -2230,7 +2230,7 @@ */ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); tcp_schedule_ack(tp); @@ -2333,7 +2333,7 @@ static void tcp_send_dupack(struct sock *sk, struct sk_buff *skb) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq && before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { @@ -2396,7 +2396,7 @@ static void tcp_sack_new_ofo_skb(struct sock *sk, u32 seq, u32 end_seq) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct tcp_sack_block *sp = &tp->selective_acks[0]; int cur_sacks = tp->num_sacks; int this_sack; @@ -2480,7 +2480,7 @@ */ static void tcp_ofo_queue(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); __u32 dsack_high = tp->rcv_nxt; struct sk_buff *skb; @@ -2524,7 +2524,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) { struct tcphdr *th = skb->h.th; - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int eaten = -1; if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) @@ -2828,7 +2828,7 @@ */ static void tcp_collapse_ofo_queue(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct sk_buff *skb = skb_peek(&tp->out_of_order_queue); struct sk_buff *head; u32 start, end; @@ -2873,7 +2873,7 @@ */ static int tcp_prune_queue(struct sock *sk) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); SOCK_DEBUG(sk, "prune_queue: c=%x\n", tp->copied_seq); @@ -2932,7 +2932,7 @@ */ void tcp_cwnd_application_limited(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); if (tp->ca_state == TCP_CA_Open && sk->socket && !test_bit(SOCK_NOSPACE, &sk->socket->flags)) { @@ -2954,7 +2954,7 @@ */ static void tcp_new_space(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); if (tp->packets_out < tp->snd_cwnd && !(sk->userlocks&SOCK_SNDBUF_LOCK) && @@ -2975,7 +2975,7 @@ static inline void tcp_check_space(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); if (tp->queue_shrunk) { tp->queue_shrunk = 0; @@ -2986,7 +2986,7 @@ static void __tcp_data_snd_check(struct sock *sk, struct sk_buff *skb) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); if (after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd) || tcp_packets_in_flight(tp) >= tp->snd_cwnd || @@ -2996,7 +2996,7 @@ static __inline__ void tcp_data_snd_check(struct sock *sk) { - struct sk_buff *skb = sk->tp_pinfo.af_tcp.send_head; + struct sk_buff *skb = TCP_PINFO(sk)->send_head; if (skb != NULL) __tcp_data_snd_check(sk, skb); @@ -3008,7 +3008,7 @@ */ static __inline__ void __tcp_ack_snd_check(struct sock *sk, int ofo_possible) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); /* More than one full frame received... */ if (((tp->rcv_nxt - tp->rcv_wup) > tp->ack.rcv_mss @@ -3031,7 +3031,7 @@ static __inline__ void tcp_ack_snd_check(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); if (!tcp_ack_scheduled(tp)) { /* We sent a data segment already. */ return; @@ -3051,7 +3051,7 @@ static void tcp_check_urg(struct sock * sk, struct tcphdr * th) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); u32 ptr = ntohs(th->urg_ptr); if (ptr && !sysctl_tcp_stdurg) @@ -3124,7 +3124,7 @@ /* This is the 'fast' part of urgent handling. */ static inline void tcp_urg(struct sock *sk, struct sk_buff *skb, struct tcphdr *th) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); /* Check if we get a new urgent pointer - normally not. */ if (th->urg) @@ -3148,7 +3148,7 @@ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int chunk = skb->len - hlen; int err; @@ -3223,7 +3223,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, struct tcphdr *th, unsigned len) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); /* * Header prediction. @@ -3441,7 +3441,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, struct tcphdr *th, unsigned len) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int saved_clamp = tp->mss_clamp; tcp_parse_options(skb, tp, 0); @@ -3670,7 +3670,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, struct tcphdr *th, unsigned len) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int queued = 0; tp->saw_tstamp = 0; Index: kernel-acme/net/ipv4/tcp_ipv4.c diff -u kernel-acme/net/ipv4/tcp_ipv4.c:1.1.1.5 kernel-acme/net/ipv4/tcp_ipv4.c:1.1.1.5.6.1 --- kernel-acme/net/ipv4/tcp_ipv4.c:1.1.1.5 Tue Nov 6 21:30:35 2001 +++ kernel-acme/net/ipv4/tcp_ipv4.c Thu Dec 13 23:14:53 2001 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.1.1.5 2001/11/06 21:30:35 acme Exp $ + * Version: $Id: tcp_ipv4.c,v 1.1.1.5.6.1 2001/12/13 23:14:53 acme Exp $ * * IPv4 specific functions * @@ -550,7 +550,7 @@ tw = (struct tcp_tw_bucket*)sk2; if(TCP_IPV4_MATCH(sk2, acookie, saddr, daddr, ports, dif)) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); /* With PAWS, it is safe from the viewpoint of data integrity. Even without PAWS it @@ -645,7 +645,7 @@ /* This will initiate an outgoing connection. */ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct sockaddr_in *usin = (struct sockaddr_in *) uaddr; struct sk_buff *buff; struct rtable *rt; @@ -660,10 +660,10 @@ return(-EAFNOSUPPORT); nexthop = daddr = usin->sin_addr.s_addr; - if (sk->protinfo.af_inet.opt && sk->protinfo.af_inet.opt->srr) { + if (IP_SK(sk)->opt && IP_SK(sk)->opt->srr) { if (daddr == 0) return -EINVAL; - nexthop = sk->protinfo.af_inet.opt->faddr; + nexthop = IP_SK(sk)->opt->faddr; } tmp = ip_route_connect(&rt, nexthop, sk->saddr, @@ -679,7 +679,7 @@ __sk_dst_set(sk, &rt->u.dst); sk->route_caps = rt->u.dst.dev->features; - if (!sk->protinfo.af_inet.opt || !sk->protinfo.af_inet.opt->srr) + if (!IP_SK(sk)->opt || !IP_SK(sk)->opt->srr) daddr = rt->rt_dst; err = -ENOBUFS; @@ -723,9 +723,9 @@ sk->sport, usin->sin_port); tp->ext_header_len = 0; - if (sk->protinfo.af_inet.opt) - tp->ext_header_len = sk->protinfo.af_inet.opt->optlen; - sk->protinfo.af_inet.id = tp->write_seq^jiffies; + if (IP_SK(sk)->opt) + tp->ext_header_len = IP_SK(sk)->opt->optlen; + IP_SK(sk)->id = tp->write_seq^jiffies; tp->mss_clamp = 536; @@ -781,7 +781,7 @@ static void tcp_v4_synq_add(struct sock *sk, struct open_request *req) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); struct tcp_listen_opt *lopt = tp->listen_opt; unsigned h = tcp_v4_synq_hash(req->af.v4_req.rmt_addr, req->rmt_port); @@ -805,7 +805,7 @@ static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *ip, unsigned mtu) { struct dst_entry *dst; - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); /* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs * send out by Linux are always <576bytes so they should go through @@ -831,7 +831,7 @@ if (mtu < dst->pmtu && ip_dont_fragment(sk, dst)) sk->err_soft = EMSGSIZE; - if (sk->protinfo.af_inet.pmtudisc != IP_PMTUDISC_DONT && + if (IP_SK(sk)->pmtudisc != IP_PMTUDISC_DONT && tp->pmtu_cookie > dst->pmtu) { tcp_sync_mss(sk, dst->pmtu); @@ -896,7 +896,7 @@ if (sk->state == TCP_CLOSE) goto out; - tp = &sk->tp_pinfo.af_tcp; + tp = TCP_PINFO(sk); seq = ntohl(th->seq); if (sk->state != TCP_LISTEN && !between(seq, tp->snd_una, tp->snd_nxt)) { NET_INC_STATS(OutOfWindowIcmps); @@ -995,7 +995,7 @@ * --ANK (980905) */ - if (sk->lock.users == 0 && sk->protinfo.af_inet.recverr) { + if (sk->lock.users == 0 && IP_SK(sk)->recverr) { sk->err = err; sk->error_report(sk); } else { /* Only an error on timeout */ @@ -1314,7 +1314,7 @@ tcp_clear_options(&tp); tp.mss_clamp = 536; - tp.user_mss = sk->tp_pinfo.af_tcp.user_mss; + tp.user_mss = TCP_PINFO(sk)->user_mss; tcp_parse_options(skb, &tp, 0); @@ -1439,18 +1439,18 @@ newsk->dst_cache = dst; newsk->route_caps = dst->dev->features; - newtp = &(newsk->tp_pinfo.af_tcp); + newtp = TCP_PINFO(newsk); newsk->daddr = req->af.v4_req.rmt_addr; newsk->saddr = req->af.v4_req.loc_addr; newsk->rcv_saddr = req->af.v4_req.loc_addr; - newsk->protinfo.af_inet.opt = req->af.v4_req.opt; + IP_SK(newsk)->opt = req->af.v4_req.opt; req->af.v4_req.opt = NULL; - newsk->protinfo.af_inet.mc_index = tcp_v4_iif(skb); - newsk->protinfo.af_inet.mc_ttl = skb->nh.iph->ttl; + IP_SK(newsk)->mc_index = tcp_v4_iif(skb); + IP_SK(newsk)->mc_ttl = skb->nh.iph->ttl; newtp->ext_header_len = 0; - if (newsk->protinfo.af_inet.opt) - newtp->ext_header_len = newsk->protinfo.af_inet.opt->optlen; - newsk->protinfo.af_inet.id = newtp->write_seq^jiffies; + if (IP_SK(newsk)->opt) + newtp->ext_header_len = IP_SK(newsk)->opt->optlen; + IP_SK(newsk)->id = newtp->write_seq^jiffies; tcp_sync_mss(newsk, dst->pmtu); newtp->advmss = dst->advmss; @@ -1473,7 +1473,7 @@ { struct open_request *req, **prev; struct tcphdr *th = skb->h.th; - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct sock *nsk; /* Find possible connection requests. */ @@ -1727,12 +1727,12 @@ __u32 new_saddr; __u32 daddr = sk->daddr; - if(sk->protinfo.af_inet.opt && sk->protinfo.af_inet.opt->srr) - daddr = sk->protinfo.af_inet.opt->faddr; + if(IP_SK(sk)->opt && IP_SK(sk)->opt->srr) + daddr = IP_SK(sk)->opt->faddr; /* Query new route. */ err = ip_route_connect(&rt, daddr, 0, - RT_TOS(sk->protinfo.af_inet.tos)|sk->localroute, + RT_TOS(IP_SK(sk)->tos)|sk->localroute, sk->bound_dev_if); if (err) return err; @@ -1778,8 +1778,8 @@ /* Reroute. */ daddr = sk->daddr; - if(sk->protinfo.af_inet.opt && sk->protinfo.af_inet.opt->srr) - daddr = sk->protinfo.af_inet.opt->faddr; + if(IP_SK(sk)->opt && IP_SK(sk)->opt->srr) + daddr = IP_SK(sk)->opt->faddr; err = ip_route_output(&rt, daddr, sk->saddr, RT_CONN_FLAGS(sk), sk->bound_dev_if); @@ -1818,7 +1818,7 @@ int tcp_v4_remember_stamp(struct sock *sk) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); struct rtable *rt = (struct rtable*)__sk_dst_get(sk); struct inet_peer *peer = NULL; int release_it = 0; @@ -1888,7 +1888,7 @@ */ static int tcp_v4_init_sock(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); skb_queue_head_init(&tp->out_of_order_queue); tcp_init_xmit_timers(sk); @@ -1918,7 +1918,7 @@ sk->write_space = tcp_write_space; sk->use_write_queue = 1; - sk->tp_pinfo.af_tcp.af_specific = &ipv4_specific; + TCP_PINFO(sk)->af_specific = &ipv4_specific; sk->sndbuf = sysctl_tcp_wmem[1]; sk->rcvbuf = sysctl_tcp_rmem[1]; @@ -1930,7 +1930,7 @@ static int tcp_v4_destroy_sock(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); tcp_clear_xmit_timers(sk); @@ -1987,7 +1987,7 @@ __u16 destp, srcp; int timer_active; unsigned long timer_expires; - struct tcp_opt *tp = &sp->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sp); dest = sp->daddr; src = sp->rcv_saddr; @@ -2068,7 +2068,7 @@ for (sk = tcp_listening_hash[i]; sk; sk = sk->next, num++) { struct open_request *req; int uid; - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); if (!TCP_INET_FAMILY(sk->family)) goto skip_listen; @@ -2207,7 +2207,7 @@ if ((err=ops->create(tcp_socket, IPPROTO_TCP))<0) panic("Failed to create the TCP control socket.\n"); tcp_socket->sk->allocation=GFP_ATOMIC; - tcp_socket->sk->protinfo.af_inet.ttl = MAXTTL; + IP_SK(tcp_socket->sk)->ttl = MAXTTL; /* Unhash it so that IP input processing does not even * see it, we do not wish this socket to see incoming Index: kernel-acme/net/ipv4/tcp_minisocks.c diff -u kernel-acme/net/ipv4/tcp_minisocks.c:1.1.1.5 kernel-acme/net/ipv4/tcp_minisocks.c:1.1.1.5.6.3 --- kernel-acme/net/ipv4/tcp_minisocks.c:1.1.1.5 Tue Nov 6 18:55:07 2001 +++ kernel-acme/net/ipv4/tcp_minisocks.c Fri Dec 21 02:12:16 2001 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_minisocks.c,v 1.1.1.5 2001/11/06 18:55:07 acme Exp $ + * Version: $Id: tcp_minisocks.c,v 1.1.1.5.6.3 2001/12/21 02:12:16 acme Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -347,7 +347,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) { struct tcp_tw_bucket *tw = NULL; - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int recycle_ok = 0; if (sysctl_tcp_tw_recycle && tp->ts_recent_stamp) @@ -384,10 +384,10 @@ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) if(tw->family == PF_INET6) { memcpy(&tw->v6_daddr, - &sk->net_pinfo.af_inet6.daddr, + &IP6_PINFO(sk)->daddr, sizeof(struct in6_addr)); memcpy(&tw->v6_rcv_saddr, - &sk->net_pinfo.af_inet6.rcv_saddr, + &IP6_PINFO(sk)->rcv_saddr, sizeof(struct in6_addr)); } #endif @@ -641,7 +641,7 @@ */ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, struct sk_buff *skb) { - struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, 0); + struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, 0, tcp_sk_cachep); if(newsk != NULL) { struct tcp_opt *newtp; @@ -649,7 +649,7 @@ struct sk_filter *filter; #endif - memcpy(newsk, sk, sizeof(*newsk)); + memcpy(newsk, sk, TCP_SK_SIZE); newsk->state = TCP_SYN_RECV; /* SANITY */ @@ -684,7 +684,7 @@ #endif /* Now setup tcp_opt */ - newtp = &(newsk->tp_pinfo.af_tcp); + newtp = TCP_PINFO(newsk); newtp->pred_flags = 0; newtp->rcv_nxt = req->rcv_isn + 1; newtp->snd_nxt = req->snt_isn + 1; @@ -797,7 +797,7 @@ struct open_request **prev) { struct tcphdr *th = skb->h.th; - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); u32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK); int paws_reject = 0; struct tcp_opt ttp; Index: kernel-acme/net/ipv4/tcp_output.c diff -u kernel-acme/net/ipv4/tcp_output.c:1.1.1.7 kernel-acme/net/ipv4/tcp_output.c:1.1.1.7.6.2 --- kernel-acme/net/ipv4/tcp_output.c:1.1.1.7 Tue Nov 6 21:30:38 2001 +++ kernel-acme/net/ipv4/tcp_output.c Mon Dec 17 03:11:13 2001 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_output.c,v 1.1.1.7 2001/11/06 21:30:38 acme Exp $ + * Version: $Id: tcp_output.c,v 1.1.1.7.6.2 2001/12/17 03:11:13 acme Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -84,7 +84,7 @@ */ static __u16 tcp_advertise_mss(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct dst_entry *dst = __sk_dst_get(sk); int mss = tp->advmss; @@ -132,7 +132,7 @@ static __inline__ void tcp_event_ack_sent(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); tcp_dec_quickack_mode(tp); tcp_clear_xmit_timer(sk, TCP_TIME_DACK); @@ -145,7 +145,7 @@ */ static __inline__ u16 tcp_select_window(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); u32 cur_win = tcp_receive_window(tp); u32 new_win = __tcp_select_window(sk); @@ -188,7 +188,7 @@ int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb) { if(skb != NULL) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct tcp_skb_cb *tcb = TCP_SKB_CB(skb); int tcp_header_size = tp->tcp_header_len; struct tcphdr *th; @@ -303,7 +303,7 @@ */ void tcp_send_skb(struct sock *sk, struct sk_buff *skb, int force_queue, unsigned cur_mss) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); /* Advance write_seq and place onto the write_queue. */ tp->write_seq = TCP_SKB_CB(skb)->end_seq; @@ -331,7 +331,7 @@ */ void tcp_push_one(struct sock *sk, unsigned cur_mss) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct sk_buff *skb = tp->send_head; if (tcp_snd_test(tp, skb, cur_mss, 1)) { @@ -418,7 +418,7 @@ */ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); struct sk_buff *buff; int nsize = skb->len - len; u16 flags; @@ -501,7 +501,7 @@ int tcp_sync_mss(struct sock *sk, u32 pmtu) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); int mss_now; /* Calculate base mss without TCP options: @@ -509,7 +509,6 @@ */ mss_now = pmtu - tp->af_specific->net_header_len - sizeof(struct tcphdr); - /* Clamp it (mss_clamp does not include tcp options) */ if (mss_now > tp->mss_clamp) mss_now = tp->mss_clamp; @@ -544,7 +543,7 @@ */ int tcp_write_xmit(struct sock *sk, int nonagle) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); unsigned int mss_now; /* If we are closed, the bytes will have to remain here. @@ -642,7 +641,7 @@ */ u32 __tcp_select_window(struct sock *sk) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); /* MSS for the peer's data. Previous verions used mss_clamp * here. I don't know if the value based on our guesses * of peer's MSS is better for the performance. It's more correct @@ -688,7 +687,7 @@ /* Attempt to collapse two adjacent SKB's during retransmission. */ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int mss_now) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); struct sk_buff *next_skb = skb->next; /* The first test we must make is that neither of these two @@ -764,7 +763,7 @@ */ void tcp_simple_retransmit(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct sk_buff *skb; unsigned int mss = tcp_current_mss(sk); int lost = 0; @@ -810,7 +809,7 @@ */ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); unsigned int cur_mss = tcp_current_mss(sk); int err; @@ -909,7 +908,7 @@ */ void tcp_xmit_retransmit_queue(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct sk_buff *skb; int packet_cnt = tp->lost_out; @@ -989,7 +988,7 @@ */ void tcp_send_fin(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct sk_buff *skb = skb_peek_tail(&sk->write_queue); unsigned int mss_now; @@ -1034,7 +1033,7 @@ */ void tcp_send_active_reset(struct sock *sk, int priority) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct sk_buff *skb; /* NOTE: No TCP options attached and we never retransmit this. */ @@ -1085,7 +1084,7 @@ } TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_ACK; - TCP_ECN_send_synack(&sk->tp_pinfo.af_tcp, skb); + TCP_ECN_send_synack(TCP_PINFO(sk), skb); } TCP_SKB_CB(skb)->when = tcp_time_stamp; return tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)); @@ -1097,7 +1096,7 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, struct open_request *req) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct tcphdr *th; int tcp_header_size; struct sk_buff *skb; @@ -1160,7 +1159,7 @@ int tcp_connect(struct sock *sk, struct sk_buff *buff) { struct dst_entry *dst = __sk_dst_get(sk); - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); /* Reserve space for headers. */ skb_reserve(buff, MAX_TCP_HEADER); @@ -1247,7 +1246,7 @@ */ void tcp_send_delayed_ack(struct sock *sk) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); int ato = tp->ack.ato; unsigned long timeout; @@ -1300,7 +1299,7 @@ { /* If we have been reset, we may not send again. */ if(sk->state != TCP_CLOSE) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct sk_buff *buff; /* We are not putting this on the write queue, so @@ -1341,7 +1340,7 @@ */ static int tcp_xmit_probe_skb(struct sock *sk, int urgent) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct sk_buff *skb; /* We don't queue it, tcp_transmit_skb() sets ownership. */ @@ -1368,7 +1367,7 @@ int tcp_write_wakeup(struct sock *sk) { if (sk->state != TCP_CLOSE) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct sk_buff *skb; if ((skb = tp->send_head) != NULL && @@ -1413,7 +1412,7 @@ */ void tcp_send_probe0(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int err; err = tcp_write_wakeup(sk); Index: kernel-acme/net/ipv4/tcp_timer.c diff -u kernel-acme/net/ipv4/tcp_timer.c:1.1.1.4 kernel-acme/net/ipv4/tcp_timer.c:1.1.1.4.6.1 --- kernel-acme/net/ipv4/tcp_timer.c:1.1.1.4 Tue Nov 6 18:55:09 2001 +++ kernel-acme/net/ipv4/tcp_timer.c Thu Dec 13 23:14:53 2001 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_timer.c,v 1.1.1.4 2001/11/06 18:55:09 acme Exp $ + * Version: $Id: tcp_timer.c,v 1.1.1.4.6.1 2001/12/13 23:14:53 acme Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -45,7 +45,7 @@ void tcp_init_xmit_timers(struct sock *sk) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); init_timer(&tp->retransmit_timer); tp->retransmit_timer.function=&tcp_write_timer; @@ -64,7 +64,7 @@ void tcp_clear_xmit_timers(struct sock *sk) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); tp->pending = 0; if (timer_pending(&tp->retransmit_timer) && @@ -103,7 +103,7 @@ */ static int tcp_out_of_resources(struct sock *sk, int do_reset) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int orphans = atomic_read(&tcp_orphan_count); /* If peer does not open window for long time, or did not transmit @@ -156,7 +156,7 @@ /* A write timeout has occurred. Process the after effects. */ static int tcp_write_timeout(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); int retry_until; if ((1<state)&(TCPF_SYN_SENT|TCPF_SYN_RECV)) { @@ -210,7 +210,7 @@ static void tcp_delack_timer(unsigned long data) { struct sock *sk = (struct sock*)data; - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); bh_lock_sock(sk); if (sk->lock.users) { @@ -271,7 +271,7 @@ static void tcp_probe_timer(struct sock *sk) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); int max_probes; if (tp->packets_out || !tp->send_head) { @@ -319,7 +319,7 @@ static void tcp_retransmit_timer(struct sock *sk) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); if (tp->packets_out == 0) goto out; @@ -415,7 +415,7 @@ static void tcp_write_timer(unsigned long data) { struct sock *sk = (struct sock*)data; - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); int event; bh_lock_sock(sk); @@ -461,7 +461,7 @@ static void tcp_synack_timer(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct tcp_listen_opt *lopt = tp->listen_opt; int max_retries = tp->syn_retries ? : sysctl_tcp_synack_retries; int thresh = max_retries; @@ -565,7 +565,7 @@ return; if (val && !sk->keepopen) - tcp_reset_keepalive_timer(sk, keepalive_time_when(&sk->tp_pinfo.af_tcp)); + tcp_reset_keepalive_timer(sk, keepalive_time_when(TCP_PINFO(sk))); else if (!val) tcp_delete_keepalive_timer(sk); } @@ -574,7 +574,7 @@ static void tcp_keepalive_timer (unsigned long data) { struct sock *sk = (struct sock *) data; - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); __u32 elapsed; /* Only process if socket is not in use. */ Index: kernel-acme/net/ipv4/udp.c diff -u kernel-acme/net/ipv4/udp.c:1.1.1.3 kernel-acme/net/ipv4/udp.c:1.1.1.3.6.2 --- kernel-acme/net/ipv4/udp.c:1.1.1.3 Tue Nov 6 20:13:48 2001 +++ kernel-acme/net/ipv4/udp.c Mon Dec 17 03:11:13 2001 @@ -5,7 +5,7 @@ * * The User Datagram Protocol (UDP). * - * Version: $Id: udp.c,v 1.1.1.3 2001/11/06 20:13:48 acme Exp $ + * Version: $Id: udp.c,v 1.1.1.3.6.2 2001/12/17 03:11:13 acme Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -323,7 +323,7 @@ break; case ICMP_DEST_UNREACH: if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */ - if (sk->protinfo.af_inet.pmtudisc != IP_PMTUDISC_DONT) { + if (IP_SK(sk)->pmtudisc != IP_PMTUDISC_DONT) { err = EMSGSIZE; harderr = 1; break; @@ -342,7 +342,7 @@ * RFC1122: OK. Passes ICMP errors back to application, as per * 4.1.3.3. */ - if (!sk->protinfo.af_inet.recverr) { + if (!IP_SK(sk)->recverr) { if (!harderr || sk->state != TCP_ESTABLISHED) goto out; } else { @@ -487,7 +487,7 @@ connected = 0; } if (!ipc.opt) - ipc.opt = sk->protinfo.af_inet.opt; + ipc.opt = IP_SK(sk)->opt; ufh.saddr = ipc.addr; ipc.addr = daddr = ufh.daddr; @@ -498,7 +498,7 @@ daddr = ipc.opt->faddr; connected = 0; } - tos = RT_TOS(sk->protinfo.af_inet.tos); + tos = RT_TOS(IP_SK(sk)->tos); if (sk->localroute || (msg->msg_flags&MSG_DONTROUTE) || (ipc.opt && ipc.opt->is_strictroute)) { tos |= RTO_ONLINK; @@ -507,9 +507,9 @@ if (MULTICAST(daddr)) { if (!ipc.oif) - ipc.oif = sk->protinfo.af_inet.mc_index; + ipc.oif = IP_SK(sk)->mc_index; if (!ufh.saddr) - ufh.saddr = sk->protinfo.af_inet.mc_addr; + ufh.saddr = IP_SK(sk)->mc_addr; connected = 0; } @@ -678,7 +678,7 @@ sin->sin_addr.s_addr = skb->nh.iph->saddr; memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); } - if (sk->protinfo.af_inet.cmsg_flags) + if (IP_SK(sk)->cmsg_flags) ip_cmsg_recv(msg, skb); err = copied; @@ -738,7 +738,7 @@ sk->daddr = rt->rt_dst; sk->dport = usin->sin_port; sk->state = TCP_ESTABLISHED; - sk->protinfo.af_inet.id = jiffies; + IP_SK(sk)->id = jiffies; sk_dst_set(sk, &rt->u.dst); return(0); @@ -758,8 +758,10 @@ sk->rcv_saddr = 0; sk->saddr = 0; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - memset(&sk->net_pinfo.af_inet6.saddr, 0, 16); - memset(&sk->net_pinfo.af_inet6.rcv_saddr, 0, 16); + if (sk->family == PF_INET6) { + memset(&IP6_PINFO(sk)->saddr, 0, 16); + memset(&IP6_PINFO(sk)->rcv_saddr, 0, 16); + } #endif } if (!(sk->userlocks&SOCK_BINDPORT_LOCK)) { Index: kernel-acme/net/ipv4/netfilter/ip_conntrack_core.c diff -u kernel-acme/net/ipv4/netfilter/ip_conntrack_core.c:1.1.1.2 kernel-acme/net/ipv4/netfilter/ip_conntrack_core.c:1.1.1.2.10.1 --- kernel-acme/net/ipv4/netfilter/ip_conntrack_core.c:1.1.1.2 Thu Aug 16 21:59:30 2001 +++ kernel-acme/net/ipv4/netfilter/ip_conntrack_core.c Tue Dec 18 04:23:42 2001 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include Index: kernel-acme/net/ipv4/netfilter/ip_nat_snmp_basic.c diff -u kernel-acme/net/ipv4/netfilter/ip_nat_snmp_basic.c:1.1.1.1 kernel-acme/net/ipv4/netfilter/ip_nat_snmp_basic.c:1.1.1.1.6.1 --- kernel-acme/net/ipv4/netfilter/ip_nat_snmp_basic.c:1.1.1.1 Tue Nov 6 21:30:41 2001 +++ kernel-acme/net/ipv4/netfilter/ip_nat_snmp_basic.c Tue Dec 18 04:23:42 2001 @@ -52,10 +52,11 @@ #include #include #include +#include #include #include #include -#include +#include Index: kernel-acme/net/ipv4/netfilter/ip_nat_standalone.c diff -u kernel-acme/net/ipv4/netfilter/ip_nat_standalone.c:1.1.1.2 kernel-acme/net/ipv4/netfilter/ip_nat_standalone.c:1.1.1.2.6.1 --- kernel-acme/net/ipv4/netfilter/ip_nat_standalone.c:1.1.1.2 Tue Nov 6 18:55:10 2001 +++ kernel-acme/net/ipv4/netfilter/ip_nat_standalone.c Tue Dec 18 04:23:42 2001 @@ -9,6 +9,7 @@ #include #include +#include #include #include #include Index: kernel-acme/net/ipv6/af_inet6.c diff -u kernel-acme/net/ipv6/af_inet6.c:1.1.1.4 kernel-acme/net/ipv6/af_inet6.c:1.1.1.4.6.2 --- kernel-acme/net/ipv6/af_inet6.c:1.1.1.4 Tue Nov 6 20:13:52 2001 +++ kernel-acme/net/ipv6/af_inet6.c Fri Dec 21 02:12:16 2001 @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/af_inet.c * - * $Id: af_inet6.c,v 1.1.1.4 2001/11/06 20:13:52 acme Exp $ + * $Id: af_inet6.c,v 1.1.1.4.6.2 2001/12/21 02:12:16 acme Exp $ * * Fixes: * piggy, Karl Knutson : Socket protocol table @@ -92,6 +92,9 @@ atomic_t inet6_sock_nr; #endif +/* Per protocol sock slabcache */ +kmem_cache_t *inet6_sk_cachep; + /* The inetsw table contains everything that inet_create needs to * build a new socket. */ @@ -113,7 +116,7 @@ struct list_head *p; struct inet_protosw *answer; - sk = sk_alloc(PF_INET6, GFP_KERNEL, 1); + sk = sk_alloc(PF_INET6, GFP_KERNEL, IP6_SK_SIZE, inet6_sk_cachep); if (sk == NULL) goto do_oom; @@ -158,7 +161,7 @@ if (SOCK_RAW == sock->type) { sk->num = protocol; if (IPPROTO_RAW == protocol) - sk->protinfo.af_inet.hdrincl = 1; + IP_SK(sk)->hdrincl = 1; } sk->destruct = inet6_sock_destruct; @@ -168,25 +171,25 @@ sk->backlog_rcv = answer->prot->backlog_rcv; - sk->net_pinfo.af_inet6.hop_limit = -1; - sk->net_pinfo.af_inet6.mcast_hops = -1; - sk->net_pinfo.af_inet6.mc_loop = 1; - sk->net_pinfo.af_inet6.pmtudisc = IPV6_PMTUDISC_WANT; + IP6_PINFO(sk)->hop_limit = -1; + IP6_PINFO(sk)->mcast_hops = -1; + IP6_PINFO(sk)->mc_loop = 1; + IP6_PINFO(sk)->pmtudisc = IPV6_PMTUDISC_WANT; /* Init the ipv4 part of the socket since we can have sockets * using v6 API for ipv4. */ - sk->protinfo.af_inet.ttl = 64; + IP_SK(sk)->ttl = 64; - sk->protinfo.af_inet.mc_loop = 1; - sk->protinfo.af_inet.mc_ttl = 1; - sk->protinfo.af_inet.mc_index = 0; - sk->protinfo.af_inet.mc_list = NULL; + IP_SK(sk)->mc_loop = 1; + IP_SK(sk)->mc_ttl = 1; + IP_SK(sk)->mc_index = 0; + IP_SK(sk)->mc_list = NULL; if (ipv4_config.no_pmtu_disc) - sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_DONT; + IP_SK(sk)->pmtudisc = IP_PMTUDISC_DONT; else - sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_WANT; + IP_SK(sk)->pmtudisc = IP_PMTUDISC_WANT; #ifdef INET_REFCNT_DEBUG @@ -296,17 +299,17 @@ sk->rcv_saddr = v4addr; sk->saddr = v4addr; - ipv6_addr_copy(&sk->net_pinfo.af_inet6.rcv_saddr, &addr->sin6_addr); + ipv6_addr_copy(&IP6_PINFO(sk)->rcv_saddr, &addr->sin6_addr); if (!(addr_type & IPV6_ADDR_MULTICAST)) - ipv6_addr_copy(&sk->net_pinfo.af_inet6.saddr, &addr->sin6_addr); + ipv6_addr_copy(&IP6_PINFO(sk)->saddr, &addr->sin6_addr); /* Make sure we are allowed to bind here. */ if (sk->prot->get_port(sk, snum) != 0) { sk->rcv_saddr = 0; sk->saddr = 0; - memset(&sk->net_pinfo.af_inet6.rcv_saddr, 0, sizeof(struct in6_addr)); - memset(&sk->net_pinfo.af_inet6.saddr, 0, sizeof(struct in6_addr)); + memset(&IP6_PINFO(sk)->rcv_saddr, 0, sizeof(struct in6_addr)); + memset(&IP6_PINFO(sk)->saddr, 0, sizeof(struct in6_addr)); release_sock(sk); return -EADDRINUSE; @@ -350,7 +353,7 @@ /* Release rx options */ - if ((skb = xchg(&sk->net_pinfo.af_inet6.pktoptions, NULL)) != NULL) + if ((skb = xchg(&IP6_PINFO(sk)->pktoptions, NULL)) != NULL) kfree_skb(skb); /* Free flowlabels */ @@ -358,7 +361,7 @@ /* Free tx options */ - if ((opt = xchg(&sk->net_pinfo.af_inet6.opt, NULL)) != NULL) + if ((opt = xchg(&IP6_PINFO(sk)->opt, NULL)) != NULL) sock_kfree_s(sk, opt, opt->tot_len); return 0; @@ -383,18 +386,18 @@ if (((1<state)&(TCPF_CLOSE|TCPF_SYN_SENT)) && peer == 1) return -ENOTCONN; sin->sin6_port = sk->dport; - memcpy(&sin->sin6_addr, &sk->net_pinfo.af_inet6.daddr, + memcpy(&sin->sin6_addr, &IP6_PINFO(sk)->daddr, sizeof(struct in6_addr)); - if (sk->net_pinfo.af_inet6.sndflow) - sin->sin6_flowinfo = sk->net_pinfo.af_inet6.flow_label; + if (IP6_PINFO(sk)->sndflow) + sin->sin6_flowinfo = IP6_PINFO(sk)->flow_label; } else { - if (ipv6_addr_type(&sk->net_pinfo.af_inet6.rcv_saddr) == IPV6_ADDR_ANY) + if (ipv6_addr_type(&IP6_PINFO(sk)->rcv_saddr) == IPV6_ADDR_ANY) memcpy(&sin->sin6_addr, - &sk->net_pinfo.af_inet6.saddr, + &IP6_PINFO(sk)->saddr, sizeof(struct in6_addr)); else memcpy(&sin->sin6_addr, - &sk->net_pinfo.af_inet6.rcv_saddr, + &IP6_PINFO(sk)->rcv_saddr, sizeof(struct in6_addr)); sin->sin6_port = sk->sport; @@ -502,8 +505,8 @@ }; struct net_proto_family inet6_family_ops = { - PF_INET6, - inet6_create + family: PF_INET6, + create: inet6_create, }; #ifdef MODULE @@ -606,6 +609,12 @@ printk(KERN_CRIT "inet6_proto_init: size fault\n"); return -EINVAL; } + /* allocate our sock slab cache */ + inet6_sk_cachep = kmem_cache_create("inet6_sock", IP6_SK_SIZE, 0, + SLAB_HWCACHE_ALIGN, 0, 0); + if (!inet6_sk_cachep) + printk(KERN_CRIT __FUNCTION__ + ": Can't create inet6_sock SLAB cache!\n"); /* Register the socket-side information for inet6_create. */ for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r) Index: kernel-acme/net/ipv6/datagram.c diff -u kernel-acme/net/ipv6/datagram.c:1.1.1.2 kernel-acme/net/ipv6/datagram.c:1.1.1.2.8.1 --- kernel-acme/net/ipv6/datagram.c:1.1.1.2 Wed Sep 26 22:00:28 2001 +++ kernel-acme/net/ipv6/datagram.c Thu Dec 13 23:14:54 2001 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: datagram.c,v 1.1.1.2 2001/09/26 22:00:28 acme Exp $ + * $Id: datagram.c,v 1.1.1.2.8.1 2001/12/13 23:14:54 acme Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -38,7 +38,7 @@ struct icmp6hdr *icmph = (struct icmp6hdr *)skb->h.raw; struct sock_exterr_skb *serr; - if (!sk->net_pinfo.af_inet6.recverr) + if (!IP6_PINFO(sk)->recverr) return; skb = skb_clone(skb, GFP_ATOMIC); @@ -69,7 +69,7 @@ struct ipv6hdr *iph; struct sk_buff *skb; - if (!sk->net_pinfo.af_inet6.recverr) + if (!IP6_PINFO(sk)->recverr) return; skb = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC); @@ -139,7 +139,7 @@ sin->sin6_scope_id = 0; if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { memcpy(&sin->sin6_addr, skb->nh.raw + serr->addr_offset, 16); - if (sk->net_pinfo.af_inet6.sndflow) + if (IP6_PINFO(sk)->sndflow) sin->sin6_flowinfo = *(u32*)(skb->nh.raw + serr->addr_offset - 24) & IPV6_FLOWINFO_MASK; if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) { struct inet6_skb_parm *opt = (struct inet6_skb_parm *) skb->cb; @@ -160,7 +160,7 @@ sin->sin6_flowinfo = 0; if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { memcpy(&sin->sin6_addr, &skb->nh.ipv6h->saddr, 16); - if (sk->net_pinfo.af_inet6.rxopt.all) + if (IP6_PINFO(sk)->rxopt.all) datagram_recv_ctl(sk, msg, skb); if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) { struct inet6_skb_parm *opt = (struct inet6_skb_parm *) skb->cb; @@ -170,7 +170,7 @@ ipv6_addr_set(&sin->sin6_addr, 0, 0, __constant_htonl(0xffff), skb->nh.iph->saddr); - if (sk->protinfo.af_inet.cmsg_flags) + if (IP_SK(sk)->cmsg_flags) ip_cmsg_recv(msg, skb); } } @@ -203,7 +203,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); struct inet6_skb_parm *opt = (struct inet6_skb_parm *) skb->cb; if (np->rxopt.bits.rxinfo) { Index: kernel-acme/net/ipv6/ip6_flowlabel.c diff -u kernel-acme/net/ipv6/ip6_flowlabel.c:1.1.1.1 kernel-acme/net/ipv6/ip6_flowlabel.c:1.1.1.1.12.1 --- kernel-acme/net/ipv6/ip6_flowlabel.c:1.1.1.1 Tue Jun 26 17:29:11 2001 +++ kernel-acme/net/ipv6/ip6_flowlabel.c Thu Dec 13 23:14:54 2001 @@ -180,7 +180,7 @@ struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, u32 label) { struct ipv6_fl_socklist *sfl; - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); label &= IPV6_FLOWLABEL_MASK; @@ -197,7 +197,7 @@ void fl6_free_socklist(struct sock *sk) { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); struct ipv6_fl_socklist *sfl; while ((sfl = np->ipv6_fl_list) != NULL) { @@ -361,7 +361,7 @@ if (room > FL_MAX_SIZE - FL_MAX_PER_SOCK) return 0; - for (sfl = sk->net_pinfo.af_inet6.ipv6_fl_list; sfl; sfl = sfl->next) + for (sfl = IP6_PINFO(sk)->ipv6_fl_list; sfl; sfl = sfl->next) count++; if (room <= 0 || @@ -404,7 +404,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char *optval, int optlen) { int err; - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); struct in6_flowlabel_req freq; struct ipv6_fl_socklist *sfl1=NULL; struct ipv6_fl_socklist *sfl, **sflp; Index: kernel-acme/net/ipv6/ip6_output.c diff -u kernel-acme/net/ipv6/ip6_output.c:1.1.1.2 kernel-acme/net/ipv6/ip6_output.c:1.1.1.2.8.1 --- kernel-acme/net/ipv6/ip6_output.c:1.1.1.2 Wed Sep 26 22:00:28 2001 +++ kernel-acme/net/ipv6/ip6_output.c Thu Dec 13 23:14:54 2001 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: ip6_output.c,v 1.1.1.2 2001/09/26 22:00:28 acme Exp $ + * $Id: ip6_output.c,v 1.1.1.2.8.1 2001/12/13 23:14:54 acme Exp $ * * Based on linux/net/ipv4/ip_output.c * @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -106,7 +107,7 @@ if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) { if (!(dev->flags&IFF_LOOPBACK) && - (skb->sk == NULL || skb->sk->net_pinfo.af_inet6.mc_loop) && + (skb->sk == NULL || IP6_PINFO(skb->sk)->mc_loop) && ipv6_chk_mcast_addr(dev, &skb->nh.ipv6h->daddr)) { struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); @@ -182,7 +183,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, struct ipv6_txoptions *opt) { - struct ipv6_pinfo * np = sk ? &sk->net_pinfo.af_inet6 : NULL; + struct ipv6_pinfo * np = sk ? IP6_PINFO(sk) : NULL; struct in6_addr *first_hop = fl->nl_u.ip6_u.daddr; struct dst_entry *dst = skb->dst; struct ipv6hdr *hdr; @@ -258,7 +259,7 @@ struct in6_addr *saddr, struct in6_addr *daddr, int proto, int len) { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); struct ipv6hdr *hdr; int totlen; @@ -500,7 +501,7 @@ struct flowi *fl, unsigned length, struct ipv6_txoptions *opt, int hlimit, int flags) { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); struct in6_addr *final_dst = NULL; struct dst_entry *dst; int err = 0; @@ -582,7 +583,7 @@ jumbolen = 0; - if (!sk->protinfo.af_inet.hdrincl) { + if (!IP_SK(sk)->hdrincl) { pktlength += sizeof(struct ipv6hdr); if (opt) pktlength += opt->opt_flen + opt->opt_nflen; @@ -642,7 +643,7 @@ hdr = (struct ipv6hdr *) skb->tail; skb->nh.ipv6h = hdr; - if (!sk->protinfo.af_inet.hdrincl) { + if (!IP_SK(sk)->hdrincl) { ip6_bld_1(sk, skb, fl, hlimit, jumbolen ? sizeof(struct ipv6hdr) : pktlength); @@ -667,7 +668,7 @@ kfree_skb(skb); } } else { - if (sk->protinfo.af_inet.hdrincl || jumbolen || + if (IP_SK(sk)->hdrincl || jumbolen || np->pmtudisc == IPV6_PMTUDISC_DO) { ipv6_local_error(sk, EMSGSIZE, fl, mtu); err = -EMSGSIZE; Index: kernel-acme/net/ipv6/ipv6_sockglue.c diff -u kernel-acme/net/ipv6/ipv6_sockglue.c:1.1.1.3 kernel-acme/net/ipv6/ipv6_sockglue.c:1.1.1.3.8.1 --- kernel-acme/net/ipv6/ipv6_sockglue.c:1.1.1.3 Wed Sep 26 22:00:26 2001 +++ kernel-acme/net/ipv6/ipv6_sockglue.c Thu Dec 13 23:14:54 2001 @@ -7,7 +7,7 @@ * * Based on linux/net/ipv4/ip_sockglue.c * - * $Id: ipv6_sockglue.c,v 1.1.1.3 2001/09/26 22:00:26 acme Exp $ + * $Id: ipv6_sockglue.c,v 1.1.1.3.8.1 2001/12/13 23:14:54 acme Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -122,7 +122,7 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen) { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); int val, valbool; int retv = -ENOPROTOOPT; @@ -166,7 +166,7 @@ ipv6_sock_mc_close(sk); if (sk->protocol == IPPROTO_TCP) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); local_bh_disable(); sock_prot_dec_use(sk->prot); @@ -281,7 +281,7 @@ retv = 0; if (sk->type == SOCK_STREAM) { if (opt) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); if (!((1<state)&(TCPF_LISTEN|TCPF_CLOSE)) && sk->daddr != LOOPBACK4_IPV6) { tp->ext_header_len = opt->opt_flen + opt->opt_nflen; @@ -401,7 +401,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen) { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); int len; int val; Index: kernel-acme/net/ipv6/mcast.c diff -u kernel-acme/net/ipv6/mcast.c:1.1.1.2 kernel-acme/net/ipv6/mcast.c:1.1.1.2.10.1 --- kernel-acme/net/ipv6/mcast.c:1.1.1.2 Thu Aug 16 22:20:03 2001 +++ kernel-acme/net/ipv6/mcast.c Thu Dec 13 23:14:54 2001 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: mcast.c,v 1.1.1.2 2001/08/16 22:20:03 acme Exp $ + * $Id: mcast.c,v 1.1.1.2.10.1 2001/12/13 23:14:54 acme Exp $ * * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c * @@ -77,7 +77,7 @@ { struct net_device *dev = NULL; struct ipv6_mc_socklist *mc_lst; - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); int err; if (!(ipv6_addr_type(addr) & IPV6_ADDR_MULTICAST)) @@ -136,7 +136,7 @@ */ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); struct ipv6_mc_socklist *mc_lst, **lnk; write_lock_bh(&ipv6_sk_mc_lock); @@ -163,7 +163,7 @@ void ipv6_sock_mc_close(struct sock *sk) { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); struct ipv6_mc_socklist *mc_lst; write_lock_bh(&ipv6_sk_mc_lock); @@ -191,7 +191,7 @@ struct ipv6_mc_socklist *mc; read_lock(&ipv6_sk_mc_lock); - for (mc = sk->net_pinfo.af_inet6.ipv6_mc_list; mc; mc=mc->next) { + for (mc = IP6_PINFO(sk)->ipv6_mc_list; mc; mc=mc->next) { if (ipv6_addr_cmp(&mc->addr, addr) == 0) { read_unlock(&ipv6_sk_mc_lock); return 1; @@ -774,7 +774,7 @@ sk->allocation = GFP_ATOMIC; sk->prot->unhash(sk); - sk->net_pinfo.af_inet6.hop_limit = 1; + IP6_PINFO(sk)->hop_limit = 1; #ifdef CONFIG_PROC_FS create_proc_read_entry("net/igmp6", 0, 0, igmp6_read_proc, NULL); #endif Index: kernel-acme/net/ipv6/ndisc.c diff -u kernel-acme/net/ipv6/ndisc.c:1.1.1.3 kernel-acme/net/ipv6/ndisc.c:1.1.1.3.8.1 --- kernel-acme/net/ipv6/ndisc.c:1.1.1.3 Wed Sep 26 22:00:27 2001 +++ kernel-acme/net/ipv6/ndisc.c Thu Dec 13 23:14:54 2001 @@ -1308,9 +1308,9 @@ sk = ndisc_socket->sk; sk->allocation = GFP_ATOMIC; - sk->net_pinfo.af_inet6.hop_limit = 255; + IP6_PINFO(sk)->hop_limit = 255; /* Do not loopback ndisc messages */ - sk->net_pinfo.af_inet6.mc_loop = 0; + IP6_PINFO(sk)->mc_loop = 0; sk->prot->unhash(sk); /* Index: kernel-acme/net/ipv6/proc.c diff -u kernel-acme/net/ipv6/proc.c:1.1.1.1 kernel-acme/net/ipv6/proc.c:1.1.1.1.12.1 --- kernel-acme/net/ipv6/proc.c:1.1.1.1 Tue Jun 26 17:29:11 2001 +++ kernel-acme/net/ipv6/proc.c Mon Dec 17 15:04:52 2001 @@ -7,7 +7,7 @@ * PROC file system. This is very similar to the IPv4 version, * except it reports the sockets in the INET6 address family. * - * Version: $Id: proc.c,v 1.1.1.1 2001/06/26 17:29:11 acme Exp $ + * Version: $Id: proc.c,v 1.1.1.1.12.1 2001/12/17 15:04:52 acme Exp $ * * Authors: David S. Miller (davem@caip.rutgers.edu) * @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include Index: kernel-acme/net/ipv6/raw.c diff -u kernel-acme/net/ipv6/raw.c:1.1.1.4 kernel-acme/net/ipv6/raw.c:1.1.1.4.8.2 --- kernel-acme/net/ipv6/raw.c:1.1.1.4 Wed Sep 26 22:00:26 2001 +++ kernel-acme/net/ipv6/raw.c Mon Dec 17 15:04:52 2001 @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/raw.c * - * $Id: raw.c,v 1.1.1.4 2001/09/26 22:00:26 acme Exp $ + * $Id: raw.c,v 1.1.1.4.8.2 2001/12/17 15:04:52 acme Exp $ * * Fixes: * Hideaki YOSHIFUJI : sin6_scope_id support @@ -86,7 +86,7 @@ for(s = sk; s; s = s->next) { if(s->num == num) { - struct ipv6_pinfo *np = &s->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(s); if (!ipv6_addr_any(&np->daddr) && ipv6_addr_cmp(&np->daddr, rmt_addr)) @@ -115,7 +115,7 @@ struct icmp6hdr *icmph; struct raw6_opt *opt; - opt = &sk->tp_pinfo.tp_raw; + opt = RAW6_PINFO(sk); if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) { __u32 *data = &opt->filter.data[0]; int bit_nr; @@ -235,9 +235,9 @@ sk->rcv_saddr = v4addr; sk->saddr = v4addr; - ipv6_addr_copy(&sk->net_pinfo.af_inet6.rcv_saddr, &addr->sin6_addr); + ipv6_addr_copy(&IP6_PINFO(sk)->rcv_saddr, &addr->sin6_addr); if (!(addr_type & IPV6_ADDR_MULTICAST)) - ipv6_addr_copy(&sk->net_pinfo.af_inet6.saddr, &addr->sin6_addr); + ipv6_addr_copy(&IP6_PINFO(sk)->saddr, &addr->sin6_addr); err = 0; out: release_sock(sk); @@ -256,21 +256,21 @@ 2. Socket is connected (otherwise the error indication is useless without recverr and error is hard. */ - if (!sk->net_pinfo.af_inet6.recverr && sk->state != TCP_ESTABLISHED) + if (!IP6_PINFO(sk)->recverr && sk->state != TCP_ESTABLISHED) return; harderr = icmpv6_err_convert(type, code, &err); if (type == ICMPV6_PKT_TOOBIG) - harderr = (sk->net_pinfo.af_inet6.pmtudisc == IPV6_PMTUDISC_DO); + harderr = (IP6_PINFO(sk)->pmtudisc == IPV6_PMTUDISC_DO); - if (sk->net_pinfo.af_inet6.recverr) { + if (IP6_PINFO(sk)->recverr) { u8 *payload = skb->data; - if (!sk->protinfo.af_inet.hdrincl) + if (!IP_SK(sk)->hdrincl) payload += offset; ipv6_icmp_error(sk, skb, err, 0, ntohl(info), payload); } - if (sk->net_pinfo.af_inet6.recverr || harderr) { + if (IP6_PINFO(sk)->recverr || harderr) { sk->err = err; sk->error_report(sk); } @@ -298,7 +298,7 @@ */ int rawv6_rcv(struct sock *sk, struct sk_buff *skb) { - if (sk->protinfo.af_inet.hdrincl) { + if (IP_SK(sk)->hdrincl) { __skb_push(skb, skb->nh.raw - skb->data); skb->h.raw = skb->nh.raw; } @@ -358,7 +358,7 @@ sock_recv_timestamp(msg, sk, skb); - if (sk->net_pinfo.af_inet6.rxopt.all) + if (IP6_PINFO(sk)->rxopt.all) datagram_recv_ctl(sk, msg, skb); err = copied; @@ -405,7 +405,7 @@ struct in6_addr *daddr; sk = hdr->sk; - opt = &sk->tp_pinfo.tp_raw; + opt = RAW6_PINFO(sk); if (hdr->daddr) daddr = hdr->daddr; @@ -434,7 +434,7 @@ { struct ipv6_txoptions opt_space; struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); struct ipv6_txoptions *opt = NULL; struct ip6_flowlabel *flowlabel = NULL; struct flowi fl; @@ -491,8 +491,8 @@ /* Otherwise it will be difficult to maintain sk->dst_cache. */ if (sk->state == TCP_ESTABLISHED && - !ipv6_addr_cmp(daddr, &sk->net_pinfo.af_inet6.daddr)) - daddr = &sk->net_pinfo.af_inet6.daddr; + !ipv6_addr_cmp(daddr, &IP6_PINFO(sk)->daddr)) + daddr = &IP6_PINFO(sk)->daddr; if (addr_len >= sizeof(struct sockaddr_in6) && sin6->sin6_scope_id && @@ -503,7 +503,7 @@ return(-EINVAL); proto = sk->num; - daddr = &(sk->net_pinfo.af_inet6.daddr); + daddr = &(IP6_PINFO(sk)->daddr); fl.fl6_flowlabel = np->flow_label; } @@ -541,7 +541,7 @@ if (flowlabel) opt = fl6_merge_options(&opt_space, flowlabel, opt); - raw_opt = &sk->tp_pinfo.tp_raw; + raw_opt = RAW6_PINFO(sk); fl.proto = proto; fl.fl6_dst = daddr; @@ -583,7 +583,7 @@ case ICMPV6_FILTER: if (optlen > sizeof(struct icmp6_filter)) optlen = sizeof(struct icmp6_filter); - if (copy_from_user(&sk->tp_pinfo.tp_raw.filter, optval, optlen)) + if (copy_from_user(&RAW6_PINFO(sk)->filter, optval, optlen)) return -EFAULT; return 0; default: @@ -608,7 +608,7 @@ len = sizeof(struct icmp6_filter); if (put_user(len, optlen)) return -EFAULT; - if (copy_to_user(optval, &sk->tp_pinfo.tp_raw.filter, len)) + if (copy_to_user(optval, &RAW6_PINFO(sk)->filter, len)) return -EFAULT; return 0; default: @@ -622,7 +622,7 @@ static int rawv6_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen) { - struct raw6_opt *opt = &sk->tp_pinfo.tp_raw; + struct raw6_opt *opt = RAW6_PINFO(sk); int val; switch(level) { @@ -665,7 +665,7 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen) { - struct raw6_opt *opt = &sk->tp_pinfo.tp_raw; + struct raw6_opt *opt = RAW6_PINFO(sk); int val, len; switch(level) { @@ -755,8 +755,8 @@ struct in6_addr *dest, *src; __u16 destp, srcp; - dest = &sp->net_pinfo.af_inet6.daddr; - src = &sp->net_pinfo.af_inet6.rcv_saddr; + dest = &IP6_PINFO(sp)->daddr; + src = &IP6_PINFO(sp)->rcv_saddr; destp = 0; srcp = sp->num; sprintf(tmpbuf, Index: kernel-acme/net/ipv6/tcp_ipv6.c diff -u kernel-acme/net/ipv6/tcp_ipv6.c:1.1.1.5 kernel-acme/net/ipv6/tcp_ipv6.c:1.1.1.5.6.2 --- kernel-acme/net/ipv6/tcp_ipv6.c:1.1.1.5 Tue Nov 6 20:13:52 2001 +++ kernel-acme/net/ipv6/tcp_ipv6.c Mon Dec 17 03:11:13 2001 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: tcp_ipv6.c,v 1.1.1.5 2001/11/06 20:13:52 acme Exp $ + * $Id: tcp_ipv6.c,v 1.1.1.5.6.2 2001/12/17 03:11:13 acme Exp $ * * Based on: * linux/net/ipv4/tcp.c @@ -47,6 +47,7 @@ #include #include #include +#include #include @@ -75,8 +76,8 @@ static __inline__ int tcp_v6_sk_hashfn(struct sock *sk) { - struct in6_addr *laddr = &sk->net_pinfo.af_inet6.rcv_saddr; - struct in6_addr *faddr = &sk->net_pinfo.af_inet6.daddr; + struct in6_addr *laddr = &IP6_PINFO(sk)->rcv_saddr; + struct in6_addr *faddr = &IP6_PINFO(sk)->daddr; __u16 lport = sk->num; __u16 fport = sk->dport; return tcp_v6_hashfn(laddr, lport, faddr, fport); @@ -138,7 +139,7 @@ } else { struct sock *sk2 = tb->owners; int sk_reuse = sk->reuse; - int addr_type = ipv6_addr_type(&sk->net_pinfo.af_inet6.rcv_saddr); + int addr_type = ipv6_addr_type(&IP6_PINFO(sk)->rcv_saddr); /* We must walk the whole port owner list in this case. -DaveM */ for( ; sk2 != NULL; sk2 = sk2->bind_next) { @@ -150,9 +151,9 @@ /* NOTE: IPv6 tw bucket have different format */ if (!sk2->rcv_saddr || addr_type == IPV6_ADDR_ANY || - !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr, + !ipv6_addr_cmp(&IP6_PINFO(sk)->rcv_saddr, sk2->state != TCP_TIME_WAIT ? - &sk2->net_pinfo.af_inet6.rcv_saddr : + &IP6_PINFO(sk2)->rcv_saddr : &((struct tcp_tw_bucket*)sk)->v6_rcv_saddr) || (addr_type==IPV6_ADDR_MAPPED && sk2->family==AF_INET && sk->rcv_saddr==sk2->rcv_saddr)) @@ -228,7 +229,7 @@ static void tcp_v6_hash(struct sock *sk) { if(sk->state != TCP_CLOSE) { - if (sk->tp_pinfo.af_tcp.af_specific == &ipv6_mapped) { + if (TCP_PINFO(sk)->af_specific == &ipv6_mapped) { tcp_prot.hash(sk); return; } @@ -249,7 +250,7 @@ sk = tcp_listening_hash[tcp_lhashfn(hnum)]; for(; sk; sk = sk->next) { if((sk->num == hnum) && (sk->family == PF_INET6)) { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); score = 1; if(!ipv6_addr_any(&np->rcv_saddr)) { @@ -417,8 +418,8 @@ static int tcp_v6_check_established(struct sock *sk) { - struct in6_addr *daddr = &sk->net_pinfo.af_inet6.rcv_saddr; - struct in6_addr *saddr = &sk->net_pinfo.af_inet6.daddr; + struct in6_addr *daddr = &IP6_PINFO(sk)->rcv_saddr; + struct in6_addr *saddr = &IP6_PINFO(sk)->daddr; int dif = sk->bound_dev_if; u32 ports = TCP_COMBINED_PORTS(sk->dport, sk->num); int hash = tcp_v6_hashfn(daddr, sk->num, saddr, sk->dport); @@ -436,7 +437,7 @@ !ipv6_addr_cmp(&tw->v6_daddr, saddr) && !ipv6_addr_cmp(&tw->v6_rcv_saddr, daddr) && sk2->bound_dev_if == sk->bound_dev_if) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); if (tw->ts_recent_stamp) { /* See comment in tcp_ipv4.c */ @@ -514,8 +515,8 @@ int addr_len) { struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct ipv6_pinfo *np = IP6_PINFO(sk); + struct tcp_opt *tp = TCP_PINFO(sk); struct in6_addr *saddr = NULL; struct in6_addr saddr_buf; struct flowi fl; @@ -597,14 +598,14 @@ sin.sin_port = usin->sin6_port; sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3]; - sk->tp_pinfo.af_tcp.af_specific = &ipv6_mapped; + TCP_PINFO(sk)->af_specific = &ipv6_mapped; sk->backlog_rcv = tcp_v4_do_rcv; err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin)); if (err) { tp->ext_header_len = exthdrlen; - sk->tp_pinfo.af_tcp.af_specific = &ipv6_specific; + TCP_PINFO(sk)->af_specific = &ipv6_specific; sk->backlog_rcv = tcp_v6_do_rcv; goto failure; } else { @@ -720,14 +721,14 @@ if (sk->state == TCP_CLOSE) goto out; - tp = &sk->tp_pinfo.af_tcp; + tp = TCP_PINFO(sk); seq = ntohl(th->seq); if (sk->state != TCP_LISTEN && !between(seq, tp->snd_una, tp->snd_nxt)) { NET_INC_STATS_BH(OutOfWindowIcmps); goto out; } - np = &sk->net_pinfo.af_inet6; + np = IP6_PINFO(sk); if (type == ICMPV6_PKT_TOOBIG) { struct dst_entry *dst = NULL; @@ -843,9 +844,9 @@ fl.uli_u.ports.sport = sk->sport; if (dst == NULL) { - opt = sk->net_pinfo.af_inet6.opt; + opt = IP6_PINFO(sk)->opt; if (opt == NULL && - sk->net_pinfo.af_inet6.rxopt.bits.srcrt == 2 && + IP6_PINFO(sk)->rxopt.bits.srcrt == 2 && req->af.v6_req.pktopts) { struct sk_buff *pktopts = req->af.v6_req.pktopts; struct inet6_skb_parm *rxopt = (struct inet6_skb_parm *)pktopts->cb; @@ -879,7 +880,7 @@ done: dst_release(dst); - if (opt && opt != sk->net_pinfo.af_inet6.opt) + if (opt && opt != IP6_PINFO(sk)->opt) sock_kfree_s(sk, opt, opt->tot_len); return err; } @@ -902,12 +903,12 @@ { struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; - if (sk->net_pinfo.af_inet6.rxopt.all) { - if ((opt->hop && sk->net_pinfo.af_inet6.rxopt.bits.hopopts) || + if (IP6_PINFO(sk)->rxopt.all) { + if ((opt->hop && IP6_PINFO(sk)->rxopt.bits.hopopts) || ((IPV6_FLOWINFO_MASK&*(u32*)skb->nh.raw) && - sk->net_pinfo.af_inet6.rxopt.bits.rxflow) || - (opt->srcrt && sk->net_pinfo.af_inet6.rxopt.bits.srcrt) || - ((opt->dst1 || opt->dst0) && sk->net_pinfo.af_inet6.rxopt.bits.dstopts)) + IP6_PINFO(sk)->rxopt.bits.rxflow) || + (opt->srcrt && IP6_PINFO(sk)->rxopt.bits.srcrt) || + ((opt->dst1 || opt->dst0) && IP6_PINFO(sk)->rxopt.bits.dstopts)) return 1; } return 0; @@ -917,7 +918,7 @@ static void tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len, struct sk_buff *skb) { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); if (skb->ip_summed == CHECKSUM_HW) { th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); @@ -1084,7 +1085,7 @@ { struct open_request *req, **prev; struct tcphdr *th = skb->h.th; - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); struct sock *nsk; /* Find possible connection requests. */ @@ -1116,7 +1117,7 @@ static void tcp_v6_synq_add(struct sock *sk, struct open_request *req) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sk); struct tcp_listen_opt *lopt = tp->listen_opt; unsigned h = tcp_v6_synq_hash(&req->af.v6_req.rmt_addr, req->rmt_port); @@ -1168,7 +1169,7 @@ tcp_clear_options(&tp); tp.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); - tp.user_mss = sk->tp_pinfo.af_tcp.user_mss; + tp.user_mss = TCP_PINFO(sk)->user_mss; tcp_parse_options(skb, &tp, 0); @@ -1180,8 +1181,8 @@ TCP_ECN_create_request(req, skb->h.th); req->af.v6_req.pktopts = NULL; if (ipv6_opt_accepted(sk, skb) || - sk->net_pinfo.af_inet6.rxopt.bits.rxinfo || - sk->net_pinfo.af_inet6.rxopt.bits.rxhlim) { + IP6_PINFO(sk)->rxopt.bits.rxinfo || + IP6_PINFO(sk)->rxopt.bits.rxhlim) { atomic_inc(&skb->users); req->af.v6_req.pktopts = skb; } @@ -1231,7 +1232,7 @@ if (newsk == NULL) return NULL; - np = &newsk->net_pinfo.af_inet6; + np = IP6_PINFO(newsk); ipv6_addr_set(&np->daddr, 0, 0, __constant_htonl(0x0000FFFF), newsk->daddr); @@ -1241,12 +1242,12 @@ ipv6_addr_copy(&np->rcv_saddr, &np->saddr); - newsk->tp_pinfo.af_tcp.af_specific = &ipv6_mapped; + TCP_PINFO(sk)->af_specific = &ipv6_mapped; newsk->backlog_rcv = tcp_v4_do_rcv; - newsk->net_pinfo.af_inet6.pktoptions = NULL; - newsk->net_pinfo.af_inet6.opt = NULL; - newsk->net_pinfo.af_inet6.mcast_oif = tcp_v6_iif(skb); - newsk->net_pinfo.af_inet6.mcast_hops = skb->nh.ipv6h->hop_limit; + IP6_PINFO(newsk)->pktoptions = NULL; + IP6_PINFO(newsk)->opt = NULL; + IP6_PINFO(newsk)->mcast_oif = tcp_v6_iif(skb); + IP6_PINFO(newsk)->mcast_hops = skb->nh.ipv6h->hop_limit; /* Charge newly allocated IPv6 socket. Though it is mapped, * it is IPv6 yet. @@ -1260,17 +1261,17 @@ worked with IPv6 af_tcp.af_specific. Sync it now. */ - tcp_sync_mss(newsk, newsk->tp_pinfo.af_tcp.pmtu_cookie); + tcp_sync_mss(newsk, TCP_PINFO(sk)->pmtu_cookie); return newsk; } - opt = sk->net_pinfo.af_inet6.opt; + opt = IP6_PINFO(sk)->opt; if (tcp_acceptq_is_full(sk)) goto out_overflow; - if (sk->net_pinfo.af_inet6.rxopt.bits.srcrt == 2 && + if (IP6_PINFO(sk)->rxopt.bits.srcrt == 2 && opt == NULL && req->af.v6_req.pktopts) { struct inet6_skb_parm *rxopt = (struct inet6_skb_parm *)req->af.v6_req.pktopts->cb; if (rxopt->srcrt) @@ -1309,9 +1310,9 @@ ip6_dst_store(newsk, dst, NULL); sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM; - newtp = &(newsk->tp_pinfo.af_tcp); + newtp = TCP_PINFO(newsk); - np = &newsk->net_pinfo.af_inet6; + np = IP6_PINFO(newsk); ipv6_addr_copy(&np->daddr, &req->af.v6_req.rmt_addr); ipv6_addr_copy(&np->saddr, &req->af.v6_req.loc_addr); ipv6_addr_copy(&np->rcv_saddr, &req->af.v6_req.loc_addr); @@ -1321,10 +1322,10 @@ First: no IPv4 options. */ - newsk->protinfo.af_inet.opt = NULL; + IP_SK(newsk)->opt = NULL; /* Clone RX bits */ - np->rxopt.all = sk->net_pinfo.af_inet6.rxopt.all; + np->rxopt.all = IP6_PINFO(sk)->rxopt.all; /* Clone pktoptions received with SYN */ np->pktoptions = NULL; @@ -1347,7 +1348,7 @@ */ if (opt) { np->opt = ipv6_dup_options(newsk, opt); - if (opt != sk->net_pinfo.af_inet6.opt) + if (opt != IP6_PINFO(sk)->opt) sock_kfree_s(sk, opt, opt->tot_len); } @@ -1372,7 +1373,7 @@ NET_INC_STATS_BH(ListenOverflows); out: NET_INC_STATS_BH(ListenDrops); - if (opt && opt != sk->net_pinfo.af_inet6.opt) + if (opt && opt != IP6_PINFO(sk)->opt) sock_kfree_s(sk, opt, opt->tot_len); dst_release(dst); return NULL; @@ -1451,7 +1452,7 @@ by tcp. Feel free to propose better solution. --ANK (980728) */ - if (sk->net_pinfo.af_inet6.rxopt.all) + if (IP6_PINFO(sk)->rxopt.all) opt_skb = skb_clone(skb, GFP_ATOMIC); if (sk->state == TCP_ESTABLISHED) { /* Fast path */ @@ -1514,18 +1515,18 @@ 3. socket is not in passive state. 4. Finally, it really contains options, which user wants to receive. */ - if (TCP_SKB_CB(opt_skb)->end_seq == sk->tp_pinfo.af_tcp.rcv_nxt && + if (TCP_SKB_CB(opt_skb)->end_seq == TCP_PINFO(sk)->rcv_nxt && !((1<state)&(TCPF_CLOSE|TCPF_LISTEN))) { - if (sk->net_pinfo.af_inet6.rxopt.bits.rxinfo) - sk->net_pinfo.af_inet6.mcast_oif = tcp_v6_iif(opt_skb); - if (sk->net_pinfo.af_inet6.rxopt.bits.rxhlim) - sk->net_pinfo.af_inet6.mcast_hops = opt_skb->nh.ipv6h->hop_limit; + if (IP6_PINFO(sk)->rxopt.bits.rxinfo) + IP6_PINFO(sk)->mcast_oif = tcp_v6_iif(opt_skb); + if (IP6_PINFO(sk)->rxopt.bits.rxhlim) + IP6_PINFO(sk)->mcast_hops = opt_skb->nh.ipv6h->hop_limit; if (ipv6_opt_accepted(sk, opt_skb)) { skb_set_owner_r(opt_skb, sk); - opt_skb = xchg(&sk->net_pinfo.af_inet6.pktoptions, opt_skb); + opt_skb = xchg(&IP6_PINFO(sk)->pktoptions, opt_skb); } else { __kfree_skb(opt_skb); - opt_skb = xchg(&sk->net_pinfo.af_inet6.pktoptions, NULL); + opt_skb = xchg(&IP6_PINFO(sk)->pktoptions, NULL); } } @@ -1655,7 +1656,7 @@ { int err; struct dst_entry *dst; - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); dst = __sk_dst_check(sk, np->dst_cookie); @@ -1694,7 +1695,7 @@ static int tcp_v6_xmit(struct sk_buff *skb) { struct sock *sk = skb->sk; - struct ipv6_pinfo * np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo * np = IP6_PINFO(sk); struct flowi fl; struct dst_entry *dst; @@ -1736,7 +1737,7 @@ static void v6_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr) { - struct ipv6_pinfo * np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo * np = IP6_PINFO(sk); struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) uaddr; sin6->sin6_family = AF_INET6; @@ -1798,7 +1799,7 @@ */ static int tcp_v6_init_sock(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); skb_queue_head_init(&tp->out_of_order_queue); tcp_init_xmit_timers(sk); @@ -1825,7 +1826,7 @@ sk->state = TCP_CLOSE; - sk->tp_pinfo.af_tcp.af_specific = &ipv6_specific; + TCP_PINFO(sk)->af_specific = &ipv6_specific; sk->write_space = tcp_write_space; sk->use_write_queue = 1; @@ -1840,7 +1841,7 @@ static int tcp_v6_destroy_sock(struct sock *sk) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); tcp_clear_xmit_timers(sk); @@ -1904,10 +1905,10 @@ __u16 destp, srcp; int timer_active; unsigned long timer_expires; - struct tcp_opt *tp = &sp->tp_pinfo.af_tcp; + struct tcp_opt *tp = TCP_PINFO(sp); - dest = &sp->net_pinfo.af_inet6.daddr; - src = &sp->net_pinfo.af_inet6.rcv_saddr; + dest = &IP6_PINFO(sp)->daddr; + src = &IP6_PINFO(sp)->rcv_saddr; destp = ntohs(sp->dport); srcp = ntohs(sp->sport); if (tp->pending == TCP_TIME_RETRANS) { @@ -2003,7 +2004,7 @@ for (sk = tcp_listening_hash[i]; sk; sk = sk->next, num++) { struct open_request *req; int uid; - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt *tp = TCP_PINFO(sk); if (sk->family != PF_INET6) continue; @@ -2121,13 +2122,10 @@ static struct inet6_protocol tcpv6_protocol = { - tcp_v6_rcv, /* TCP handler */ - tcp_v6_err, /* TCP error control */ - NULL, /* next */ - IPPROTO_TCP, /* protocol ID */ - 0, /* copy */ - NULL, /* data */ - "TCPv6" /* name */ + handler: tcp_v6_rcv, + err_handler: tcp_v6_err, + protocol: IPPROTO_TCP, + name: "TCPv6", }; extern struct proto_ops inet6_stream_ops; Index: kernel-acme/net/ipv6/udp.c diff -u kernel-acme/net/ipv6/udp.c:1.1.1.3 kernel-acme/net/ipv6/udp.c:1.1.1.3.8.1 --- kernel-acme/net/ipv6/udp.c:1.1.1.3 Wed Sep 26 22:00:26 2001 +++ kernel-acme/net/ipv6/udp.c Thu Dec 13 23:14:54 2001 @@ -7,7 +7,7 @@ * * Based on linux/ipv4/udp.c * - * $Id: udp.c,v 1.1.1.3 2001/09/26 22:00:26 acme Exp $ + * $Id: udp.c,v 1.1.1.3.8.1 2001/12/13 23:14:54 acme Exp $ * * Fixes: * Hideaki YOSHIFUJI : sin6_scope_id support @@ -98,7 +98,7 @@ udp_port_rover = snum = result; } else { struct sock *sk2; - int addr_type = ipv6_addr_type(&sk->net_pinfo.af_inet6.rcv_saddr); + int addr_type = ipv6_addr_type(&IP6_PINFO(sk)->rcv_saddr); for (sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; sk2 != NULL; @@ -108,8 +108,8 @@ sk2->bound_dev_if == sk->bound_dev_if && (!sk2->rcv_saddr || addr_type == IPV6_ADDR_ANY || - !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr, - &sk2->net_pinfo.af_inet6.rcv_saddr) || + !ipv6_addr_cmp(&IP6_PINFO(sk)->rcv_saddr, + &IP6_PINFO(sk2)->rcv_saddr) || (addr_type == IPV6_ADDR_MAPPED && sk2->family == AF_INET && sk->rcv_saddr == sk2->rcv_saddr)) && @@ -167,7 +167,7 @@ for(sk = udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]; sk != NULL; sk = sk->next) { if((sk->num == hnum) && (sk->family == PF_INET6)) { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); int score = 0; if(sk->dport) { if(sk->dport != sport) @@ -211,7 +211,7 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); struct in6_addr *daddr; struct in6_addr saddr; struct dst_entry *dst; @@ -418,13 +418,13 @@ if (skb->protocol == __constant_htons(ETH_P_IP)) { ipv6_addr_set(&sin6->sin6_addr, 0, 0, __constant_htonl(0xffff), skb->nh.iph->saddr); - if (sk->protinfo.af_inet.cmsg_flags) + if (IP_SK(sk)->cmsg_flags) ip_cmsg_recv(msg, skb); } else { memcpy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr, sizeof(struct in6_addr)); - if (sk->net_pinfo.af_inet6.rxopt.all) + if (IP6_PINFO(sk)->rxopt.all) datagram_recv_ctl(sk, msg, skb); if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) { struct inet6_skb_parm *opt = (struct inet6_skb_parm *) skb->cb; @@ -478,14 +478,14 @@ return; if (!icmpv6_err_convert(type, code, &err) && - !sk->net_pinfo.af_inet6.recverr) + !IP6_PINFO(sk)->recverr) goto out; if (sk->state!=TCP_ESTABLISHED && - !sk->net_pinfo.af_inet6.recverr) + !IP6_PINFO(sk)->recverr) goto out; - if (sk->net_pinfo.af_inet6.recverr) + if (IP6_PINFO(sk)->recverr) ipv6_icmp_error(sk, skb, err, uh->dest, ntohl(info), (u8 *)(uh+1)); sk->err = err; @@ -527,7 +527,7 @@ unsigned short num = ntohs(loc_port); for(; s; s = s->next) { if(s->num == num) { - struct ipv6_pinfo *np = &s->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(s); if(s->dport) { if(s->dport != rmt_port) continue; @@ -755,7 +755,7 @@ { struct ipv6_txoptions opt_space; struct udpv6fakehdr udh; - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; + struct ipv6_pinfo *np = IP6_PINFO(sk); struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name; struct ipv6_txoptions *opt = NULL; struct ip6_flowlabel *flowlabel = NULL; @@ -805,8 +805,8 @@ /* Otherwise it will be difficult to maintain sk->dst_cache. */ if (sk->state == TCP_ESTABLISHED && - !ipv6_addr_cmp(daddr, &sk->net_pinfo.af_inet6.daddr)) - daddr = &sk->net_pinfo.af_inet6.daddr; + !ipv6_addr_cmp(daddr, &IP6_PINFO(sk)->daddr)) + daddr = &IP6_PINFO(sk)->daddr; if (addr_len >= sizeof(struct sockaddr_in6) && sin6->sin6_scope_id && @@ -817,7 +817,7 @@ return -ENOTCONN; udh.uh.dest = sk->dport; - daddr = &sk->net_pinfo.af_inet6.daddr; + daddr = &IP6_PINFO(sk)->daddr; fl.fl6_flowlabel = np->flow_label; } @@ -910,8 +910,8 @@ struct in6_addr *dest, *src; __u16 destp, srcp; - dest = &sp->net_pinfo.af_inet6.daddr; - src = &sp->net_pinfo.af_inet6.rcv_saddr; + dest = &IP6_PINFO(sp)->daddr; + src = &IP6_PINFO(sp)->rcv_saddr; destp = ntohs(sp->dport); srcp = ntohs(sp->sport); sprintf(tmpbuf, Index: kernel-acme/net/ipx/af_ipx.c diff -u kernel-acme/net/ipx/af_ipx.c:1.1.1.4 kernel-acme/net/ipx/af_ipx.c:1.1.1.4.6.5 --- kernel-acme/net/ipx/af_ipx.c:1.1.1.4 Tue Nov 6 18:55:05 2001 +++ kernel-acme/net/ipx/af_ipx.c Fri Dec 21 02:12:16 2001 @@ -73,6 +73,9 @@ * Petr Vandrovec for review and good suggestions. (acme) * Revision 047: Cleanups, CodingStyle changes, move the ncp connection * hack out of line (acme) + * Revision 048: Use sk->protinfo to store the pointer to IPX private + * area, remove af_ipx from sk->protinfo and move ipx_opt + * to include/net/ipx.h, use IPX_SK like DecNET, etc * * Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT * pair. Also, now usage count is managed this way @@ -103,6 +106,7 @@ #include #include #include +#include #include #include #include @@ -221,7 +225,7 @@ ipx_interface *intrfc; /* Determine interface with which socket is associated */ - intrfc = sk->protinfo.af_ipx.intrfc; + intrfc = IPX_SK(sk)->intrfc; if (!intrfc) goto out; @@ -323,7 +327,7 @@ ipxitf_hold(intrfc); sock_hold(sk); spin_lock_bh(&intrfc->if_sklist_lock); - sk->protinfo.af_ipx.intrfc = intrfc; + IPX_SK(sk)->intrfc = intrfc; sk->next = NULL; if (!intrfc->if_sklist) intrfc->if_sklist = sk; @@ -343,7 +347,7 @@ { struct sock *s = intrfc->if_sklist; - while (s && s->protinfo.af_ipx.port != port) + while (s && IPX_SK(s)->port != port) s = s->next; return s; @@ -375,8 +379,8 @@ s = intrfc->if_sklist; while (s) { - if (s->protinfo.af_ipx.port == port && - !memcmp(node, s->protinfo.af_ipx.node, IPX_NODE_LEN)) + if (IPX_SK(s)->port == port && + !memcmp(node, IPX_SK(s)->node, IPX_NODE_LEN)) break; s = s->next; } @@ -401,8 +405,8 @@ for (s = intrfc->if_sklist; s;) { s->err = ENOLINK; s->error_report(s); - s->protinfo.af_ipx.intrfc = NULL; - s->protinfo.af_ipx.port = 0; + IPX_SK(s)->intrfc = NULL; + IPX_SK(s)->port = 0; s->zapped = 1; /* Indicates it is no longer bound */ t = s; s = s->next; @@ -491,10 +495,9 @@ s = intrfc->if_sklist; while (s) { - if (s->protinfo.af_ipx.port == ipx->ipx_dest.sock && + if (IPX_SK(s)->port == ipx->ipx_dest.sock && (is_broadcast || !memcmp(ipx->ipx_dest.node, - s->protinfo.af_ipx.node, - IPX_NODE_LEN))) { + IPX_SK(s)->node, IPX_NODE_LEN))) { /* We found a socket to which to send */ struct sk_buff *skb1; @@ -550,7 +553,7 @@ * SIOCIPXNCPCONN. */ spin_lock_bh(&intrfc->if_sklist_lock); for (sk = intrfc->if_sklist; - sk && sk->protinfo.af_ipx.ipx_ncp_conn != connection; + sk && IPX_SK(sk)->ipx_ncp_conn != connection; sk = sk->next); if (sk) sock_hold(sk); @@ -1548,21 +1551,21 @@ IPX_SKB_CB(skb)->last_hop.index = -1; #ifdef CONFIG_IPX_INTERN - IPX_SKB_CB(skb)->ipx_source_net = sk->protinfo.af_ipx.intrfc->if_netnum; - memcpy(ipx->ipx_source.node, sk->protinfo.af_ipx.node, IPX_NODE_LEN); + IPX_SKB_CB(skb)->ipx_source_net = IPX_SK(sk)->intrfc->if_netnum; + memcpy(ipx->ipx_source.node, IPX_SK(sk)->node, IPX_NODE_LEN); #else - err = ntohs(sk->protinfo.af_ipx.port); + err = ntohs(IPX_SK(sk)->port); if (err == 0x453 || err == 0x452) { /* RIP/SAP special handling for mars_nwe */ IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum; memcpy(ipx->ipx_source.node, intrfc->if_node, IPX_NODE_LEN); } else { - IPX_SKB_CB(skb)->ipx_source_net = - sk->protinfo.af_ipx.intrfc->if_netnum; - memcpy(ipx->ipx_source.node, sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN); + IPX_SKB_CB(skb)->ipx_source_net = IPX_SK(sk)->intrfc->if_netnum; + memcpy(ipx->ipx_source.node, IPX_SK(sk)->intrfc->if_node, + IPX_NODE_LEN); } #endif /* CONFIG_IPX_INTERN */ - ipx->ipx_source.sock = sk->protinfo.af_ipx.port; + ipx->ipx_source.sock = IPX_SK(sk)->port; IPX_SKB_CB(skb)->ipx_dest_net = usipx->sipx_network; memcpy(ipx->ipx_dest.node, usipx->sipx_node, IPX_NODE_LEN); ipx->ipx_dest.sock = usipx->sipx_port; @@ -1746,18 +1749,15 @@ #ifdef CONFIG_IPX_INTERN len += sprintf(buffer + len, "%08lX:%02X%02X%02X%02X%02X%02X:%04X ", - (unsigned long) htonl(s->protinfo.af_ipx.intrfc->if_netnum), - s->protinfo.af_ipx.node[0], - s->protinfo.af_ipx.node[1], - s->protinfo.af_ipx.node[2], - s->protinfo.af_ipx.node[3], - s->protinfo.af_ipx.node[4], - s->protinfo.af_ipx.node[5], - htons(s->protinfo.af_ipx.port)); + (unsigned long)htonl(IPX_SK(s)->intrfc->if_netnum), + IPX_SK(s)->node[0], IPX_SK(s)->node[1], + IPX_SK(s)->node[2], IPX_SK(s)->node[3], + IPX_SK(s)->node[4], IPX_SK(s)->node[5], + htons(IPX_SK(s)->port)); #else len += sprintf(buffer + len, "%08lX:%04X ", (unsigned long) htonl(i->if_netnum), - htons(s->protinfo.af_ipx.port)); + htons(IPX_SK(s)->port)); #endif /* CONFIG_IPX_INTERN */ if (s->state != TCP_ESTABLISHED) len += sprintf(buffer + len, "%-28s", @@ -1765,14 +1765,14 @@ else { len += sprintf(buffer + len, "%08lX:%02X%02X%02X%02X%02X%02X:%04X ", - (unsigned long) htonl(s->protinfo.af_ipx.dest_addr.net), - s->protinfo.af_ipx.dest_addr.node[0], - s->protinfo.af_ipx.dest_addr.node[1], - s->protinfo.af_ipx.dest_addr.node[2], - s->protinfo.af_ipx.dest_addr.node[3], - s->protinfo.af_ipx.dest_addr.node[4], - s->protinfo.af_ipx.dest_addr.node[5], - htons(s->protinfo.af_ipx.dest_addr.sock)); + (unsigned long)htonl(IPX_SK(s)->dest_addr.net), + IPX_SK(s)->dest_addr.node[0], + IPX_SK(s)->dest_addr.node[1], + IPX_SK(s)->dest_addr.node[2], + IPX_SK(s)->dest_addr.node[3], + IPX_SK(s)->dest_addr.node[4], + IPX_SK(s)->dest_addr.node[5], + htons(IPX_SK(s)->dest_addr.sock)); } len += sprintf(buffer + len, "%08X %08X ", @@ -1868,7 +1868,7 @@ if (!(level == SOL_IPX && optname == IPX_TYPE)) goto out; - sk->protinfo.af_ipx.type = opt; + IPX_SK(sk)->type = opt; ret = 0; out: return ret; } @@ -1884,7 +1884,7 @@ if (!(level == SOL_IPX && optname == IPX_TYPE)) goto out; - val = sk->protinfo.af_ipx.type; + val = IPX_SK(sk)->type; ret = -EFAULT; if (get_user(len, optlen)) @@ -1906,14 +1906,19 @@ static int ipx_create(struct socket *sock, int protocol) { int ret = -ESOCKTNOSUPPORT; + struct ipx_opt *ipx = NULL; struct sock *sk; + MOD_INC_USE_COUNT; switch (sock->type) { case SOCK_DGRAM: - sk = sk_alloc(PF_IPX, GFP_KERNEL, 1); + sk = sk_alloc(PF_IPX, GFP_KERNEL, 1, NULL); ret = -ENOMEM; if (!sk) - goto out; + goto decmod; + ipx = kmalloc(sizeof(*ipx), GFP_KERNEL); + if (!ipx) + goto outsk; sock->ops = &ipx_dgram_ops; break; @@ -1924,12 +1929,12 @@ */ if (spx_family_ops) { ret = spx_family_ops->create(sock, protocol); - goto out; + goto decmod; } /* Fall through if SPX is not loaded */ case SOCK_STREAM: /* Allow higher levels to piggyback */ default: - goto out; + goto decmod; } #ifdef IPX_REFCNT_DEBUG atomic_inc(&ipx_sock_nr); @@ -1937,12 +1942,13 @@ atomic_read(&ipx_sock_nr)); #endif sock_init_data(sock, sk); - sk->destruct = NULL; - sk->no_check = 1; /* Checksum off by default */ - - MOD_INC_USE_COUNT; + sk->no_check = 1; /* Checksum off by default */ + IPX_SK(sk) = ipx; ret = 0; out: return ret; +outsk: sk_free(sk); +decmod: MOD_DEC_USE_COUNT; + goto out; } static int ipx_release(struct socket *sock) @@ -2016,7 +2022,7 @@ !capable(CAP_NET_ADMIN)) goto out_put; - sk->protinfo.af_ipx.port = addr->sipx_port; + IPX_SK(sk)->port = addr->sipx_port; #ifdef CONFIG_IPX_INTERN if (intrfc == ipx_internal_net) { @@ -2029,16 +2035,13 @@ if (!memcmp(addr->sipx_node, ipx_broadcast_node, IPX_NODE_LEN)) goto out_put; if (!memcmp(addr->sipx_node, ipx_this_node, IPX_NODE_LEN)) - memcpy(sk->protinfo.af_ipx.node, intrfc->if_node, - IPX_NODE_LEN); + memcpy(IPX_SK(sk)->node, intrfc->if_node, IPX_NODE_LEN); else - memcpy(sk->protinfo.af_ipx.node, addr->sipx_node, - IPX_NODE_LEN); + memcpy(IPX_SK(sk)->node, addr->sipx_node, IPX_NODE_LEN); ret = -EADDRINUSE; - if (ipxitf_find_internal_socket(intrfc, - sk->protinfo.af_ipx.node, - sk->protinfo.af_ipx.port)) { + if (ipxitf_find_internal_socket(intrfc, IPX_SK(sk)->node, + IPX_SK(sk)->port)) { SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n", ntohs((int)addr->sipx_port)); @@ -2050,8 +2053,7 @@ * with the ipx routing ioctl() */ - memcpy(sk->protinfo.af_ipx.node, intrfc->if_node, - IPX_NODE_LEN); + memcpy(IPX_SK(sk)->node, intrfc->if_node, IPX_NODE_LEN); ret = -EADDRINUSE; if (ipxitf_find_socket(intrfc, addr->sipx_port)) { @@ -2102,7 +2104,7 @@ addr = (struct sockaddr_ipx *)uaddr; /* put the autobinding in */ - if (!sk->protinfo.af_ipx.port) { + if (!IPX_SK(sk)->port) { struct sockaddr_ipx uaddr; uaddr.sipx_port = 0; @@ -2110,9 +2112,9 @@ #ifdef CONFIG_IPX_INTERN ret = -ENETDOWN; - if (!sk->protinfo.af_ipx.intrfc) + if (!IPX_SK(sk)->intrfc) goto out; /* Someone zonked the iface */ - memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc->if_node, + memcpy(uaddr.sipx_node, IPX_SK(sk)->intrfc->if_node, IPX_NODE_LEN); #endif /* CONFIG_IPX_INTERN */ @@ -2129,11 +2131,10 @@ if (!rt && !(!addr->sipx_network && ipx_primary_net)) goto out; - sk->protinfo.af_ipx.dest_addr.net = addr->sipx_network; - sk->protinfo.af_ipx.dest_addr.sock = addr->sipx_port; - memcpy(sk->protinfo.af_ipx.dest_addr.node, - addr->sipx_node, IPX_NODE_LEN); - sk->protinfo.af_ipx.type = addr->sipx_type; + IPX_SK(sk)->dest_addr.net = addr->sipx_network; + IPX_SK(sk)->dest_addr.sock = addr->sipx_port; + memcpy(IPX_SK(sk)->dest_addr.node, addr->sipx_node, IPX_NODE_LEN); + IPX_SK(sk)->type = addr->sipx_type; if (sock->type == SOCK_DGRAM) { sock->state = SS_CONNECTED; @@ -2162,20 +2163,17 @@ if (sk->state != TCP_ESTABLISHED) goto out; - addr = &sk->protinfo.af_ipx.dest_addr; + addr = &IPX_SK(sk)->dest_addr; sipx.sipx_network = addr->net; sipx.sipx_port = addr->sock; memcpy(sipx.sipx_node, addr->node, IPX_NODE_LEN); } else { - if (sk->protinfo.af_ipx.intrfc) { - sipx.sipx_network = - sk->protinfo.af_ipx.intrfc->if_netnum; + if (IPX_SK(sk)->intrfc) { + sipx.sipx_network = IPX_SK(sk)->intrfc->if_netnum; #ifdef CONFIG_IPX_INTERN - memcpy(sipx.sipx_node, sk->protinfo.af_ipx.node, - IPX_NODE_LEN); + memcpy(sipx.sipx_node, IPX_SK(sk)->node, IPX_NODE_LEN); #else - memcpy(sipx.sipx_node, - sk->protinfo.af_ipx.intrfc->if_node, + memcpy(sipx.sipx_node, IPX_SK(sk)->intrfc->if_node, IPX_NODE_LEN); #endif /* CONFIG_IPX_INTERN */ @@ -2184,11 +2182,11 @@ memset(sipx.sipx_node, '\0', IPX_NODE_LEN); } - sipx.sipx_port = sk->protinfo.af_ipx.port; + sipx.sipx_port = IPX_SK(sk)->port; } sipx.sipx_family = AF_IPX; - sipx.sipx_type = sk->protinfo.af_ipx.type; + sipx.sipx_type = IPX_SK(sk)->type; memcpy(uaddr, &sipx, sizeof(sipx)); ret = 0; @@ -2263,17 +2261,16 @@ goto out; if (usipx) { - if (!sk->protinfo.af_ipx.port) { + if (!IPX_SK(sk)->port) { struct sockaddr_ipx uaddr; uaddr.sipx_port = 0; uaddr.sipx_network = 0; #ifdef CONFIG_IPX_INTERN ret = -ENETDOWN; - if (!sk->protinfo.af_ipx.intrfc) + if (!IPX_SK(sk)->intrfc) goto out; /* Someone zonked the iface */ - memcpy(uaddr.sipx_node, - sk->protinfo.af_ipx.intrfc->if_node, + memcpy(uaddr.sipx_node, IPX_SK(sk)->intrfc->if_node, IPX_NODE_LEN); #endif ret = ipx_bind(sock, (struct sockaddr *)&uaddr, @@ -2293,11 +2290,11 @@ usipx = &local_sipx; usipx->sipx_family = AF_IPX; - usipx->sipx_type = sk->protinfo.af_ipx.type; - usipx->sipx_port = sk->protinfo.af_ipx.dest_addr.sock; - usipx->sipx_network = sk->protinfo.af_ipx.dest_addr.net; - memcpy(usipx->sipx_node, sk->protinfo.af_ipx.dest_addr.node, - IPX_NODE_LEN); + usipx->sipx_type = IPX_SK(sk)->type; + usipx->sipx_port = IPX_SK(sk)->dest_addr.sock; + usipx->sipx_network = IPX_SK(sk)->dest_addr.net; + memcpy(usipx->sipx_node, IPX_SK(sk)->dest_addr.node, + IPX_NODE_LEN); } ret = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len, @@ -2318,7 +2315,7 @@ int copied, err; /* put the autobinding in */ - if (!sk->protinfo.af_ipx.port) { + if (!IPX_SK(sk)->port) { struct sockaddr_ipx uaddr; uaddr.sipx_port = 0; @@ -2326,10 +2323,10 @@ #ifdef CONFIG_IPX_INTERN err = -ENETDOWN; - if (!sk->protinfo.af_ipx.intrfc) + if (!IPX_SK(sk)->intrfc) goto out; /* Someone zonked the iface */ - memcpy(uaddr.sipx_node, - sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN); + memcpy(uaddr.sipx_node, IPX_SK(sk)->intrfc->if_node, + IPX_NODE_LEN); #endif /* CONFIG_IPX_INTERN */ err = ipx_bind(sock, (struct sockaddr *)&uaddr, @@ -2423,7 +2420,7 @@ */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - return get_user(sk->protinfo.af_ipx.ipx_ncp_conn, + return get_user(IPX_SK(sk)->ipx_ncp_conn, (const unsigned short *)(arg)); case SIOCGSTAMP: { @@ -2536,10 +2533,14 @@ static unsigned char ipx_8022_type = 0xE0; static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; -static char banner[] __initdata = - KERN_INFO "NET4: Linux IPX 0.47 for NET4.0\n" +static char ipx_banner[] __initdata = + KERN_INFO "NET4: Linux IPX 0.48 for NET4.0\n" KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n" \ KERN_INFO "IPX Portions Copyright (c) 2000, 2001 Conectiva, Inc.\n"; +static char ipx_llc_err_msg[] __initdata = + KERN_CRIT "IPX: Unable to register with 802.2\n"; +static char ipx_snap_err_msg[] __initdata = + KERN_CRIT "IPX: Unable to register with SNAP\n"; static int __init ipx_init(void) { @@ -2553,11 +2554,11 @@ p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv); if (!p8022_datalink) - printk(KERN_CRIT "IPX: Unable to register with 802.2\n"); + printk(ipx_llc_err_msg); pSNAP_datalink = register_snap_client(ipx_snap_id, ipx_rcv); if (!pSNAP_datalink) - printk(KERN_CRIT "IPX: Unable to register with SNAP\n"); + printk(ipx_snap_err_msg); register_netdevice_notifier(&ipx_dev_notifier); ipx_register_sysctl(); @@ -2566,7 +2567,7 @@ proc_net_create("ipx_interface", 0, ipx_interface_get_info); proc_net_create("ipx_route", 0, ipx_rt_get_info); #endif - printk(banner); + printk(ipx_banner); return 0; } Index: kernel-acme/net/ipx/af_spx.c diff -u kernel-acme/net/ipx/af_spx.c:1.1.1.3 kernel-acme/net/ipx/af_spx.c:1.1.1.3.8.1 --- kernel-acme/net/ipx/af_spx.c:1.1.1.3 Wed Sep 26 22:00:20 2001 +++ kernel-acme/net/ipx/af_spx.c Mon Dec 17 03:55:25 2001 @@ -20,6 +20,8 @@ * Added spx_datagram_poll() so that select() * works now on SPX sockets. Added updating * of the alloc count to follow rmt_seq. + * Arnaldo C. Melo : Use a private slabcache for the old tp_pinfo + * struct sock member, use SPX_PINFO and IPX_SK * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -34,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -60,7 +63,7 @@ static unsigned int spx_datagram_poll(struct file * file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; - struct spx_opt *pdata = &sk->tp_pinfo.af_spx; + struct spx_opt *pdata = SPX_PINFO(sk); unsigned int mask; poll_wait(file, sk->sleep, wait); @@ -95,7 +98,7 @@ /* Create the SPX specific data */ static int spx_sock_init(struct sock *sk) { - struct spx_opt *pdata = &sk->tp_pinfo.af_spx; + struct spx_opt *pdata = SPX_PINFO(sk); pdata->state = SPX_CLOSED; pdata->sequence = 0; @@ -159,7 +162,7 @@ void spx_close_socket(struct sock *sk) { - struct spx_opt *pdata = &sk->tp_pinfo.af_spx; + struct spx_opt *pdata = SPX_PINFO(sk); pdata->state = SPX_CLOSED; sk->state = TCP_CLOSE; @@ -169,7 +172,7 @@ void spx_destroy_socket(struct sock *sk) { - struct spx_opt *pdata = &sk->tp_pinfo.af_spx; + struct spx_opt *pdata = SPX_PINFO(sk); struct sk_buff *skb; ipx_remove_socket(sk); @@ -190,7 +193,7 @@ static int spx_release(struct socket *sock) { struct sock *sk = sock->sk; - struct spx_opt *pdata = &sk->tp_pinfo.af_spx; + struct spx_opt *pdata = SPX_PINFO(sk); if(sk == NULL) return (0); @@ -285,7 +288,7 @@ sk->ack_backlog--; newsock->sk = newsk; newsk->state = TCP_ESTABLISHED; - newsk->protinfo.af_ipx.dest_addr = newsk->tp_pinfo.af_spx.dest_addr; + IPX_SK(newsk)->dest_addr = SPX_PINFO(newsk)->dest_addr; return (0); } @@ -295,7 +298,7 @@ int addr_len, int flags) { struct sock *sk = sock->sk; - struct spx_opt *pdata = &sk->tp_pinfo.af_spx; + struct spx_opt *pdata = SPX_PINFO(sk); struct sockaddr_ipx src; struct sk_buff *skb; int size, err; @@ -313,7 +316,7 @@ if(err) return (err); - pdata->dest_addr = sk->protinfo.af_ipx.dest_addr; + pdata->dest_addr = IPX_SK(sk)->dest_addr; pdata->state = SPX_CONNECTING; sock->state = SS_CONNECTING; sk->state = TCP_SYN_SENT; @@ -423,7 +426,7 @@ /* SPX packet transmit engine */ static int spx_transmit(struct sock *sk, struct sk_buff *skb, int type, int len) { - struct spx_opt *pdata = &sk->tp_pinfo.af_spx; + struct spx_opt *pdata = SPX_PINFO(sk); struct ipxspxhdr *ipxh; unsigned long flags; int err; @@ -520,7 +523,7 @@ static void spx_watchdog(unsigned long data) { struct sock *sk = (struct sock*)data; - struct spx_opt *pdata = &sk->tp_pinfo.af_spx; + struct spx_opt *pdata = SPX_PINFO(sk); del_timer(&pdata->watchdog); if(pdata->state == SPX_CLOSED) @@ -541,7 +544,7 @@ static void spx_retransmit(unsigned long data) { struct sock *sk = (struct sock*)data; - struct spx_opt *pdata = &sk->tp_pinfo.af_spx; + struct spx_opt *pdata = SPX_PINFO(sk); struct sk_buff *skb; unsigned long flags; int err; @@ -614,7 +617,7 @@ { struct sk_buff *skb; struct ipxspxhdr *ipxh; - struct spx_opt *pdata = &sk->tp_pinfo.af_spx; + struct spx_opt *pdata = SPX_PINFO(sk); skb = skb_dequeue(&sk->receive_queue); if(skb == NULL) @@ -736,7 +739,7 @@ if(flags&~MSG_DONTWAIT) return (-EINVAL); - offset = ipx_if_offset(sk->tp_pinfo.af_spx.dest_addr.net); + offset = ipx_if_offset(SPX_PINFO(sk)->dest_addr.net); size = offset + sizeof(struct ipxspxhdr) + len; cli(); @@ -770,7 +773,7 @@ struct sk_buff *skb; struct ipxspxhdr *ispxh; struct sock *sk = sock->sk; - struct spx_opt *pdata = &sk->tp_pinfo.af_spx; + struct spx_opt *pdata = SPX_PINFO(sk); struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)msg->msg_name; int copied, err; @@ -906,8 +909,10 @@ SOCKOPS_WRAP(spx, PF_IPX); static struct net_proto_family spx_family_ops = { - family: PF_IPX, - create: spx_create, + family: PF_IPX, + create: spx_create, + sk_size: sizeof(struct sock) + sizeof(struct ipx_opt) + + sizeof(struct spx_opt), }; static char banner[] __initdata = KERN_INFO "NET4: Sequenced Packet eXchange (SPX) 0.02 for Linux NET4.0\n"; @@ -917,6 +922,16 @@ int error; connids = (__u16)jiffies; /* initalize random */ + + /* allocate our sock slab cache */ + + spx_family_ops.sk_cachep = kmem_cache_create("spx_sock", + spx_family_ops.sk_size, + 0, SLAB_HWCACHE_ALIGN, + 0, 0); + if (!spx_family_ops.sk_cachep) + printk(KERN_CRIT __FUNCTION__ + ": Cannot create spx_sock SLAB cache!\n"); error = ipx_register_spx(&ipx_operations, &spx_family_ops); if (error) Index: kernel-acme/net/irda/af_irda.c diff -u kernel-acme/net/irda/af_irda.c:1.1.1.6 kernel-acme/net/irda/af_irda.c:1.1.1.6.4.4 --- kernel-acme/net/irda/af_irda.c:1.1.1.6 Fri Nov 23 18:18:09 2001 +++ kernel-acme/net/irda/af_irda.c Fri Dec 21 02:12:16 2001 @@ -56,6 +56,7 @@ #include #include +#include #include #include @@ -728,7 +729,7 @@ { struct sockaddr_irda saddr; struct sock *sk = sock->sk; - struct irda_sock *self = sk->protinfo.irda; + struct irda_sock *self = IRDA_SK(sk); if (peer) { if (sk->state != TCP_ESTABLISHED) @@ -792,7 +793,7 @@ struct irda_sock *self; int err; - self = sk->protinfo.irda; + self = IRDA_SK(sk); ASSERT(self != NULL, return -1;); IRDA_DEBUG(2, __FUNCTION__ "(%p)\n", self); @@ -853,7 +854,7 @@ IRDA_DEBUG(2, __FUNCTION__ "()\n"); - self = sk->protinfo.irda; + self = IRDA_SK(sk); ASSERT(self != NULL, return -1;); err = irda_create(newsock, sk->protocol); @@ -891,7 +892,7 @@ newsk = newsock->sk; newsk->state = TCP_ESTABLISHED; - new = newsk->protinfo.irda; + new = IRDA_SK(newsk); ASSERT(new != NULL, return -1;); /* Now attach up the new socket */ @@ -957,7 +958,7 @@ struct irda_sock *self; int err; - self = sk->protinfo.irda; + self = IRDA_SK(sk); IRDA_DEBUG(2, __FUNCTION__ "(%p)\n", self); @@ -1079,7 +1080,7 @@ } /* Allocate networking socket */ - if ((sk = sk_alloc(PF_IRDA, GFP_ATOMIC, 1)) == NULL) + if ((sk = sk_alloc(PF_IRDA, GFP_ATOMIC, 1, NULL)) == NULL) return -ENOMEM; /* Allocate IrDA socket */ @@ -1099,7 +1100,7 @@ sk->family = PF_IRDA; sk->protocol = protocol; /* Link networking socket and IrDA socket structs together */ - sk->protinfo.irda = self; + IRDA_SK(sk) = self; self->sk = sk; switch (sock->type) { @@ -1209,9 +1210,9 @@ sk->state_change(sk); /* Destroy IrDA socket */ - irda_destroy_socket(sk->protinfo.irda); + irda_destroy_socket(IRDA_SK(sk)); /* Prevent sock_def_destruct() to create havoc */ - sk->protinfo.irda = NULL; + IRDA_SK(sk) = NULL; sock_orphan(sk); sock->sk = NULL; @@ -1282,7 +1283,7 @@ if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; - self = sk->protinfo.irda; + self = IRDA_SK(sk); ASSERT(self != NULL, return -1;); /* Check if IrTTP is wants us to slow down */ @@ -1342,7 +1343,7 @@ IRDA_DEBUG(4, __FUNCTION__ "()\n"); - self = sk->protinfo.irda; + self = IRDA_SK(sk); ASSERT(self != NULL, return -1;); skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, @@ -1413,7 +1414,7 @@ IRDA_DEBUG(3, __FUNCTION__ "()\n"); - self = sk->protinfo.irda; + self = IRDA_SK(sk); ASSERT(self != NULL, return -1;); if (sock->flags & __SO_ACCEPTCON) @@ -1532,7 +1533,7 @@ if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; - self = sk->protinfo.irda; + self = IRDA_SK(sk); ASSERT(self != NULL, return -1;); /* @@ -1595,7 +1596,7 @@ return -EPIPE; } - self = sk->protinfo.irda; + self = IRDA_SK(sk); ASSERT(self != NULL, return -1;); /* @@ -1640,7 +1641,7 @@ struct irda_sock *self; struct sock *sk = sock->sk; - self = sk->protinfo.irda; + self = IRDA_SK(sk); ASSERT(self != NULL, return -1;); IRDA_DEBUG(1, __FUNCTION__ "(%p)\n", self); @@ -1683,7 +1684,7 @@ IRDA_DEBUG(4, __FUNCTION__ "()\n"); - self = sk->protinfo.irda; + self = IRDA_SK(sk); poll_wait(file, sk->sleep, wait); mask = 0; @@ -1815,7 +1816,7 @@ struct ias_attrib * ias_attr; /* Attribute in IAS object */ int opt; - self = sk->protinfo.irda; + self = IRDA_SK(sk); ASSERT(self != NULL, return -1;); IRDA_DEBUG(2, __FUNCTION__ "(%p)\n", self); @@ -2084,7 +2085,7 @@ int err; int offset, total; - self = sk->protinfo.irda; + self = IRDA_SK(sk); IRDA_DEBUG(2, __FUNCTION__ "(%p)\n", self); @@ -2367,10 +2368,9 @@ return 0; } -static struct net_proto_family irda_family_ops = -{ - PF_IRDA, - irda_create +static struct net_proto_family irda_family_ops = { + family: PF_IRDA, + create: irda_create, }; static struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = { Index: kernel-acme/net/khttpd/accept.c diff -u kernel-acme/net/khttpd/accept.c:1.1.1.1 kernel-acme/net/khttpd/accept.c:1.1.1.1.12.1 --- kernel-acme/net/khttpd/accept.c:1.1.1.1 Tue Jun 26 17:29:37 2001 +++ kernel-acme/net/khttpd/accept.c Tue Dec 18 04:23:43 2001 @@ -63,7 +63,7 @@ the allocation of a new socket. (Which doesn't seem to be used anyway) */ - if (Socket->sk->tp_pinfo.af_tcp.accept_queue==NULL) + if (TCP_PINFO(Socket->sk)->accept_queue==NULL) { return 0; } Index: kernel-acme/net/khttpd/datasending.c diff -u kernel-acme/net/khttpd/datasending.c:1.1.1.3 kernel-acme/net/khttpd/datasending.c:1.1.1.3.8.1 --- kernel-acme/net/khttpd/datasending.c:1.1.1.3 Wed Sep 26 22:00:32 2001 +++ kernel-acme/net/khttpd/datasending.c Tue Dec 18 04:23:43 2001 @@ -171,8 +171,8 @@ if (CurrentRequest->sock->sk->state == TCP_ESTABLISHED || CurrentRequest->sock->sk->state == TCP_CLOSE_WAIT) { - CurrentRequest->sock->sk->tp_pinfo.af_tcp.nonagle = 0; - tcp_push_pending_frames(CurrentRequest->sock->sk,&(CurrentRequest->sock->sk->tp_pinfo.af_tcp)); + TCP_PINFO(CurrentRequest->sock->sk)->nonagle = 0; + tcp_push_pending_frames(CurrentRequest->sock->sk,TCP_PINFO(CurrentRequest->sock->sk)); } release_sock(CurrentRequest->sock->sk); Index: kernel-acme/net/khttpd/prototypes.h diff -u kernel-acme/net/khttpd/prototypes.h:1.1.1.2 kernel-acme/net/khttpd/prototypes.h:1.1.1.2.10.1 --- kernel-acme/net/khttpd/prototypes.h:1.1.1.2 Thu Aug 16 22:20:10 2001 +++ kernel-acme/net/khttpd/prototypes.h Tue Dec 18 04:23:43 2001 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "structure.h" Index: kernel-acme/net/khttpd/waitheaders.c diff -u kernel-acme/net/khttpd/waitheaders.c:1.1.1.3 kernel-acme/net/khttpd/waitheaders.c:1.1.1.3.8.1 --- kernel-acme/net/khttpd/waitheaders.c:1.1.1.3 Wed Sep 26 22:00:32 2001 +++ kernel-acme/net/khttpd/waitheaders.c Tue Dec 18 04:23:43 2001 @@ -255,7 +255,7 @@ } else /* Normal Case */ { - Request->sock->sk->tp_pinfo.af_tcp.nonagle = 2; /* this is TCP_CORK */ + TCP_PINFO(Request->sock->sk)->nonagle = 2; /* this is TCP_CORK */ if (Request->HTTPVER!=9) /* HTTP/0.9 doesn't allow a header */ SendHTTPHeader(Request); } Index: kernel-acme/net/llc/Makefile diff -u /dev/null kernel-acme/net/llc/Makefile:1.1.6.1 --- /dev/null Sat Dec 22 02:21:12 2001 +++ kernel-acme/net/llc/Makefile Thu Nov 29 20:36:55 2001 @@ -0,0 +1,38 @@ +########################################################################### +# Makefile for the Linux 802.2 LLC (fully-functional) layer. +# +# Note 1! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definition is now in the main makefile... +# +# Copyright (c) 1997 by Procom Technology,Inc. +# 2001 by Arnaldo Carvalho de Melo +# +# This program can be redistributed or modified under the terms of the +# GNU General Public License as published by the Free Software Foundation. +# This program is distributed without any warranty or implied warranty +# of merchantability or fitness for a particular purpose. +# +# See the GNU General Public License for more details. +########################################################################### + +O_TARGET := llc.o + +obj-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_mac.o llc_sap.o llc_s_st.o \ + llc_main.o llc_s_ac.o llc_conn.o llc_c_st.o llc_stat.o llc_actn.o \ + llc_s_ev.o llc_evnt.o llc_pdu.o + +ifeq ($(CONFIG_LLC_UI),y) + obj-y += llc_sock.o +endif + +# Objects that export symbols. +export-objs := llc_if.o + +ifeq ($(CONFIG_LLC),m) + obj-m += $(O_TARGET) +endif + +include $(TOPDIR)/Rules.make Index: kernel-acme/net/llc/llc_actn.c diff -u /dev/null kernel-acme/net/llc/llc_actn.c:1.1.6.1 --- /dev/null Sat Dec 22 02:21:12 2001 +++ kernel-acme/net/llc/llc_actn.c Thu Nov 29 20:36:55 2001 @@ -0,0 +1,147 @@ +/* + * llc_actn.c - Implementation of actions of station component of LLC + * + * Description : + * Functions in this module are implementation of station component actions. + * Details of actions can be found in IEEE-802.2 standard document. + * All functions have one station and one event as input argument. All of + * them return 0 On success and 1 otherwise. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include + +static void llc_station_ack_tmr_callback(unsigned long timeout_data); + +int llc_station_ac_start_ack_timer(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + del_timer(&station->ack_timer); + station->ack_timer.expires = jiffies + LLC_ACK_TIME * HZ; + station->ack_timer.data = (unsigned long)station; + station->ack_timer.function = llc_station_ack_tmr_callback; + add_timer(&station->ack_timer); + station->ack_tmr_running = 1; + return 0; +} + +int llc_station_ac_set_retry_cnt_0(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + station->retry_count = 0; + return 0; +} + +int llc_station_ac_inc_retry_cnt_by_1(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + station->retry_count++; + return 0; +} + +int llc_station_ac_set_xid_r_cnt_0(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + station->xid_r_count = 0; + return 0; +} + +int llc_station_ac_inc_xid_r_cnt_by_1(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + station->xid_r_count++; + return 0; +} + +int llc_station_ac_send_null_dsap_xid_c(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (!skb) + goto out; + rc = 0; + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD); + llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 127); + lan_hdrs_init(skb, station->mac_sa, station->mac_sa); + llc_station_send_pdu(station, skb); +out: return rc; +} + +int llc_station_ac_send_xid_r(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + u8 mac_da[ETH_ALEN], dsap; + int rc = 1; + struct sk_buff *ev_skb; + struct sk_buff* skb = llc_alloc_frame(); + + if (!skb) + goto out; + rc = 0; + ev_skb = ev->data.pdu.skb; + skb->dev = ev_skb->dev; + llc_pdu_decode_sa(ev_skb, mac_da); + llc_pdu_decode_ssap(ev_skb, &dsap); + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); + llc_pdu_init_as_xid_rsp(skb, LLC_XID_NULL_CLASS_2, 127); + lan_hdrs_init(skb, station->mac_sa, mac_da); + llc_station_send_pdu(station, skb); +out: return rc; +} + +int llc_station_ac_send_test_r(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + u8 mac_da[ETH_ALEN], dsap; + int rc = 1; + struct sk_buff *ev_skb; + struct sk_buff *skb = llc_alloc_frame(); + + if (!skb) + goto out; + rc = 0; + ev_skb = ev->data.pdu.skb; + skb->dev = ev_skb->dev; + llc_pdu_decode_sa(ev_skb, mac_da); + llc_pdu_decode_ssap(ev_skb, &dsap); + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); + llc_pdu_init_as_test_rsp(skb, ev_skb); + lan_hdrs_init(skb, station->mac_sa, mac_da); + llc_station_send_pdu(station, skb); +out: return rc; +} + +int llc_station_ac_report_status(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + return 0; +} + +static void llc_station_ack_tmr_callback(unsigned long timeout_data) +{ + struct llc_station *station = (struct llc_station *)timeout_data; + struct llc_station_state_ev *ev; + + station->ack_tmr_running = 0; + ev = llc_station_alloc_ev(station); + if (ev) { + ev->type = LLC_STATION_EV_TYPE_ACK_TMR; + ev->data.tmr.timer_specific = NULL; + llc_station_send_ev(station, ev); + } +} Index: kernel-acme/net/llc/llc_c_ac.c diff -u /dev/null kernel-acme/net/llc/llc_c_ac.c:1.1.6.4 --- /dev/null Sat Dec 22 02:21:13 2001 +++ kernel-acme/net/llc/llc_c_ac.c Tue Dec 11 00:26:46 2001 @@ -0,0 +1,1645 @@ +/* + * llc_c_ac.c - actions performed during connection state transition. + * + * Description: + * Functions in this module are implementation of connection component actions + * Details of actions can be found in IEEE-802.2 standard document. + * All functions have one connection and one event as input argument. All of + * them return 0 On success and 1 otherwise. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data); +static void llc_conn_ack_tmr_cb(unsigned long timeout_data); +static void llc_conn_rej_tmr_cb(unsigned long timeout_data); +static void llc_conn_busy_tmr_cb(unsigned long timeout_data); +static int llc_conn_ac_inc_vs_by_1(struct sock *sk, + struct llc_conn_state_ev *ev); +static void llc_process_tmr_ev(struct sock *sk, struct llc_conn_state_ev *ev); +static int llc_conn_ac_data_confirm(struct sock *sk, + struct llc_conn_state_ev *ev); + +#define INCORRECT 0 + +int llc_conn_ac_clear_remote_busy(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + + if (llc->remote_busy_flag) { + u8 nr; + llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + llc->remote_busy_flag = 0; + del_timer(&llc->busy_state_timer.timer); + llc->busy_state_timer.running = 0; + nr = LLC_I_GET_NR(rx_pdu); + llc_conn_resend_i_pdu_as_cmd(sk, nr, 0); + } + return 0; +} + +int llc_conn_ac_conn_ind(struct sock *sk, struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = ev->data.pdu.skb; + union llc_u_prim_data *prim_data = llc_ind_prim.data; + struct llc_prim_if_block *prim = &llc_ind_prim; + struct llc_sap *sap; + struct llc_opt *llc = LLC_SK(sk); + + llc_pdu_decode_dsap(skb, &prim_data->conn.daddr.lsap); + sap = llc_sap_find(prim_data->conn.daddr.lsap); + if (sap) { + llc_pdu_decode_sa(skb, llc->daddr.mac); + llc_pdu_decode_da(skb, llc->laddr.mac); + llc->dev = skb->dev; + prim_data->conn.pri = 0; + prim_data->conn.sk = sk; + prim_data->conn.dev = skb->dev; + memcpy(&prim_data->conn.daddr, &llc->laddr, sizeof(llc->laddr)); + memcpy(&prim_data->conn.saddr, &llc->daddr, sizeof(llc->daddr)); + prim->data = prim_data; + prim->prim = LLC_CONN_PRIM; + prim->sap = llc->sap; + ev->flag = 1; + ev->ind_prim = prim; + rc = 0; + } + return rc; +} + +int llc_conn_ac_conn_confirm(struct sock *sk, struct llc_conn_state_ev *ev) +{ + union llc_u_prim_data *prim_data = llc_cfm_prim.data; + struct sk_buff *skb = ev->data.pdu.skb; + /* FIXME: wtf, this is global, so the whole thing is really non + * reentrant... */ + struct llc_prim_if_block *prim = &llc_cfm_prim; + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + + prim_data->conn.sk = sk; + prim_data->conn.pri = 0; + prim_data->conn.status = ev->status; + prim_data->conn.link = llc->link; + if (skb) + prim_data->conn.dev = skb->dev; + else + printk(KERN_ERR __FUNCTION__ "ev->data.pdu.skb == NULL\n"); + prim->data = prim_data; + prim->prim = LLC_CONN_PRIM; + prim->sap = sap; + ev->flag = 1; + ev->cfm_prim = prim; + return 0; +} + +static int llc_conn_ac_data_confirm(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + struct llc_prim_if_block *prim = &llc_cfm_prim; + union llc_u_prim_data *prim_data = llc_cfm_prim.data; + + prim_data->data.sk = sk; + prim_data->data.pri = 0; + prim_data->data.link = LLC_SK(sk)->link; + prim_data->data.status = LLC_STATUS_RECEIVED; + prim_data->data.skb = NULL; + prim->data = prim_data; + prim->prim = LLC_DATA_PRIM; + prim->sap = LLC_SK(sk)->sap; + ev->flag = 1; + ev->cfm_prim = prim; + return 0; +} + +int llc_conn_ac_data_ind(struct sock *sk, struct llc_conn_state_ev *ev) +{ + llc_conn_rtn_pdu(sk, ev->data.pdu.skb, ev); + return 0; +} + +int llc_conn_ac_disc_ind(struct sock *sk, struct llc_conn_state_ev *ev) +{ + u8 reason = 0; + int rc = 1; + union llc_u_prim_data *prim_data = llc_ind_prim.data; + struct llc_prim_if_block *prim = &llc_ind_prim; + + if (ev->type == LLC_CONN_EV_TYPE_PDU) { + llc_pdu_un_t *rx_pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + if (!LLC_PDU_IS_RSP(rx_pdu) && + !LLC_PDU_TYPE_IS_U(rx_pdu) && + LLC_U_PDU_RSP(rx_pdu) == LLC_2_PDU_RSP_DM) { + reason = LLC_DISC_REASON_RX_DM_RSP_PDU; + rc = 0; + } else if (!LLC_PDU_IS_CMD(rx_pdu) && + !LLC_PDU_TYPE_IS_U(rx_pdu) && + LLC_U_PDU_CMD(rx_pdu) == LLC_2_PDU_CMD_DISC) { + reason = LLC_DISC_REASON_RX_DISC_CMD_PDU; + rc = 0; + } + } else if (ev->type == LLC_CONN_EV_TYPE_ACK_TMR) { + reason = LLC_DISC_REASON_ACK_TMR_EXP; + rc = 0; + } else { + reason = 0; + rc = 1; + } + if (!rc) { + prim_data->disc.sk = sk; + prim_data->disc.reason = reason; + prim_data->disc.link = LLC_SK(sk)->link; + prim->data = prim_data; + prim->prim = LLC_DISC_PRIM; + prim->sap = LLC_SK(sk)->sap; + ev->flag = 1; + ev->ind_prim = prim; + } + return rc; +} + +int llc_conn_ac_disc_confirm(struct sock *sk, struct llc_conn_state_ev *ev) +{ + union llc_u_prim_data *prim_data = llc_cfm_prim.data; + struct llc_prim_if_block *prim = &llc_cfm_prim; + + prim_data->disc.sk = sk; + prim_data->disc.reason = ev->status; + prim_data->disc.link = LLC_SK(sk)->link; + prim->data = prim_data; + prim->prim = LLC_DISC_PRIM; + prim->sap = LLC_SK(sk)->sap; + ev->flag = 1; + ev->cfm_prim = prim; + return 0; +} + +int llc_conn_ac_rst_ind(struct sock *sk, struct llc_conn_state_ev *ev) +{ + u8 reason = 0; + int rc = 1; + llc_pdu_un_t *rx_pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + union llc_u_prim_data *prim_data = llc_ind_prim.data; + struct llc_prim_if_block *prim = &llc_ind_prim; + struct llc_opt *llc = LLC_SK(sk); + + switch (ev->type) { + case LLC_CONN_EV_TYPE_PDU: + if (!LLC_PDU_IS_RSP(rx_pdu) && + !LLC_PDU_TYPE_IS_U(rx_pdu) && + LLC_U_PDU_RSP(rx_pdu) == LLC_2_PDU_RSP_FRMR) { + reason = LLC_RESET_REASON_LOCAL; + rc = 0; + } else if (!LLC_PDU_IS_CMD(rx_pdu) && + !LLC_PDU_TYPE_IS_U(rx_pdu) && + LLC_U_PDU_CMD(rx_pdu) == + LLC_2_PDU_CMD_SABME) { + reason = LLC_RESET_REASON_REMOTE; + rc = 0; + } else { + reason = 0; + rc = 1; + } + break; + case LLC_CONN_EV_TYPE_ACK_TMR: + case LLC_CONN_EV_TYPE_P_TMR: + case LLC_CONN_EV_TYPE_REJ_TMR: + case LLC_CONN_EV_TYPE_BUSY_TMR: + if (llc->retry_count > llc->n2) { + reason = LLC_RESET_REASON_LOCAL; + rc = 0; + } else + rc = 1; + break; + } + if (!rc) { + prim_data->res.sk = sk; + prim_data->res.reason = reason; + prim_data->res.link = llc->link; + prim->data = prim_data; + prim->prim = LLC_RESET_PRIM; + prim->sap = llc->sap; + ev->flag = 1; + ev->ind_prim = prim; + } + return rc; +} + +int llc_conn_ac_rst_confirm(struct sock *sk, struct llc_conn_state_ev *ev) +{ + union llc_u_prim_data *prim_data = llc_cfm_prim.data; + struct llc_prim_if_block *prim = &llc_cfm_prim; + + prim_data->res.sk = sk; + prim_data->res.link = LLC_SK(sk)->link; + prim->data = prim_data; + prim->prim = LLC_RESET_PRIM; + prim->sap = LLC_SK(sk)->sap; + ev->flag = 1; + ev->cfm_prim = prim; + return 0; +} + +int llc_conn_ac_report_status(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return 0; +} + +int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + if (!LLC_PDU_IS_RSP(rx_pdu) && + !LLC_PDU_TYPE_IS_I(rx_pdu) && + !LLC_I_PF_IS_1(rx_pdu) && LLC_SK(sk)->ack_pf) + llc_conn_ac_clear_remote_busy(sk, ev); + return 0; +} + +int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + if (LLC_SK(sk)->data_flag == 2) { + del_timer(&LLC_SK(sk)->rej_sent_timer.timer); + LLC_SK(sk)->rej_sent_timer.running = 0; + } + return 0; +} + +int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + u8 p_bit = 1; + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_CMD); + llc_pdu_init_as_disc_cmd(skb, p_bit); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + llc_conn_ac_set_p_flag_1(sk, ev); + return rc; +} + +int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + struct sk_buff *rx_skb = ev->data.pdu.skb; + u8 f_bit; + + skb->dev = llc->dev; + llc_pdu_decode_pf_bit(rx_skb, &f_bit); + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_dm_rsp(skb, f_bit); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + u8 f_bit = 1; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_dm_rsp(skb, f_bit); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_dm_rsp_f_set_f_flag(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + u8 f_bit = llc->f_flag; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_dm_rsp(skb, f_bit); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u8 f_bit; + int rc = 1; + struct sk_buff *skb, *ev_skb = ev->data.pdu.skb; + llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev_skb->nh.raw; + struct llc_opt *llc = LLC_SK(sk); + + llc->rx_pdu_hdr = (u32)*((u32 *)rx_pdu); + if (!LLC_PDU_IS_CMD(rx_pdu)) + llc_pdu_decode_pf_bit(ev_skb, &f_bit); + else + f_bit = 0; + skb = llc_alloc_frame(); + if (skb) { + struct llc_sap *sap = llc->sap; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_frmr_rsp(skb, rx_pdu, f_bit, llc->vS, + llc->vR, INCORRECT); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + u8 f_bit = 0; + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)&llc->rx_pdu_hdr; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_frmr_rsp(skb, rx_pdu, f_bit, llc->vS, + llc->vR, INCORRECT); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u8 f_bit; + int rc = 1; + struct sk_buff *skb; + + llc_pdu_decode_pf_bit(ev->data.pdu.skb, &f_bit); + skb = llc_alloc_frame(); + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_frmr_rsp(skb, rx_pdu, f_bit, llc->vS, + llc->vR, INCORRECT); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u8 p_bit = 1; + struct sk_buff *skb = ev->data.prim.data->data->data.skb; + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + + llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_CMD); + llc_pdu_init_as_i_cmd(skb, p_bit, llc->vS, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + llc_conn_send_pdu(sk, skb); + llc_conn_ac_inc_vs_by_1(sk, ev); + return 0; +} + +int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u8 p_bit = 0; + struct sk_buff *skb = ev->data.prim.data->data->data.skb; + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + + llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_CMD); + llc_pdu_init_as_i_cmd(skb, p_bit, llc->vS, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + llc_conn_send_pdu(sk, skb); + llc_conn_ac_inc_vs_by_1(sk, ev); + return 0; +} + +int llc_conn_ac_resend_i_cmd_p_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + u8 nr = LLC_I_GET_NR(rx_pdu); + + llc_conn_resend_i_pdu_as_cmd(sk, nr, 1); + return 0; +} + +int llc_conn_ac_resend_i_cmd_p_set_1_or_send_rr(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + u8 nr = LLC_I_GET_NR(rx_pdu); + int rc = llc_conn_ac_send_rr_cmd_p_set_1(sk, ev); + + if (!rc) + llc_conn_resend_i_pdu_as_cmd(sk, nr, 0); + return rc; +} + +int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u8 p_bit = 0; + struct sk_buff *skb = ev->data.prim.data->data->data.skb; + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + + llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_CMD); + llc_pdu_init_as_i_cmd(skb, p_bit, llc->vS, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + llc_conn_send_pdu(sk, skb); + llc_conn_ac_inc_vs_by_1(sk, ev); + return 0; +} + +int llc_conn_ac_resend_i_xxx_x_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + u8 nr = LLC_I_GET_NR(rx_pdu); + + llc_conn_resend_i_pdu_as_cmd(sk, nr, 0); + return 0; +} + +int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u8 nr; + u8 f_bit = 0; + llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_rr_rsp(skb, f_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + if (rc) { + nr = LLC_I_GET_NR(rx_pdu); + rc = 0; + llc_conn_resend_i_pdu_as_cmd(sk, nr, f_bit); + } + return rc; +} + +int llc_conn_ac_resend_i_rsp_f_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + u8 nr = LLC_I_GET_NR(rx_pdu); + + llc_conn_resend_i_pdu_as_rsp(sk, nr, 1); + return 0; +} + +int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + u8 p_bit = 1; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_CMD); + llc_pdu_init_as_rej_cmd(skb, p_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + u8 f_bit = 1; + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_rej_rsp(skb, f_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + u8 f_bit = 0; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_rej_rsp(skb, f_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + u8 p_bit = 1; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_CMD); + llc_pdu_init_as_rnr_cmd(skb, p_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + u8 f_bit = 1; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_rnr_rsp(skb, f_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + u8 f_bit = 0; + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_rnr_rsp(skb, f_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_set_remote_busy(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + + if (!llc->remote_busy_flag) { + llc->remote_busy_flag = 1; + llc->busy_state_timer.timer.expires = jiffies + + llc->busy_state_timer.expire * HZ; + llc->busy_state_timer.timer.data = (unsigned long)sk; + llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb; + add_timer(&llc->busy_state_timer.timer); + llc->busy_state_timer.running = 1; + } + return 0; +} + +int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + u8 f_bit = 0; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_rnr_rsp(skb, f_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + u8 p_bit = 1; + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_CMD); + llc_pdu_init_as_rr_cmd(skb, p_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_ack_cmd_p_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + u8 p_bit = 1; + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_CMD); + llc_pdu_init_as_rr_cmd(skb, p_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + u8 f_bit = 1; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_rr_rsp(skb, f_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + u8 f_bit = 1; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_rr_rsp(skb, f_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + u8 f_bit = 0; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_rr_rsp(skb, f_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + u8 f_bit = 0; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_rr_rsp(skb, f_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + struct llc_opt *llc = LLC_SK(sk); + u8 p_bit = 1; + + if (skb) { + struct llc_sap *sap = llc->sap; + u8 *dmac = llc->daddr.mac; + + if (llc->dev->flags & IFF_LOOPBACK) + dmac = llc->dev->dev_addr; + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_CMD); + llc_pdu_init_as_sabme_cmd(skb, p_bit); + lan_hdrs_init(skb, llc->dev->dev_addr, dmac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + llc->p_flag = p_bit; + return rc; +} + +int llc_conn_ac_send_ua_rsp_f_set_f_flag(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + u8 f_bit = llc->f_flag; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_ua_rsp(skb, f_bit); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u8 f_bit; + int rc = 1; + struct sk_buff *rx_skb = ev->data.pdu.skb; + struct sk_buff *skb; + + llc_pdu_decode_pf_bit(rx_skb, &f_bit); + skb = llc_alloc_frame(); + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_ua_rsp(skb, f_bit); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +int llc_conn_ac_set_s_flag_0(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->s_flag = 0; + return 0; +} + +int llc_conn_ac_set_s_flag_1(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->s_flag = 1; + return 0; +} + +int llc_conn_ac_start_p_timer(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + + llc->p_flag = 1; + del_timer(&llc->pf_cycle_timer.timer); + llc->pf_cycle_timer.timer.expires = jiffies + + llc->pf_cycle_timer.expire * HZ; + llc->pf_cycle_timer.timer.data = (unsigned long)sk; + llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb; + add_timer(&llc->pf_cycle_timer.timer); + llc->pf_cycle_timer.running = 1; + return 0; +} + +/** + * llc_conn_ac_send_ack_if_needed - check if ack is needed + * @sk: current connection structure + * @ev: current event + * + * Checks number of received PDUs which have not been acknowledged, yet, + * If number of them reaches to "npta"(Number of PDUs To Acknowledge) then + * sends an RR response as acknowledgement for them. Returns 0 for + * success, 1 otherwise. + */ +int llc_conn_ac_send_ack_if_needed(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u8 pf_bit; + struct sk_buff *skb = ev->data.pdu.skb; + struct llc_opt *llc = LLC_SK(sk); + + llc_pdu_decode_pf_bit(skb, &pf_bit); + llc->ack_pf |= pf_bit & 1; + if (!llc->ack_must_be_send) { + llc->first_pdu_Ns = llc->vR; + llc->ack_must_be_send = 1; + llc->ack_pf = pf_bit & 1; + } + if (((llc->vR - llc->first_pdu_Ns + 129) % 128) >= llc->npta) { + llc_conn_ac_send_rr_rsp_f_set_ackpf(sk, ev); + llc->ack_must_be_send = 0; + llc->ack_pf = 0; + llc_conn_ac_inc_npta_value(sk, ev); + } + return 0; +} + +/** + * llc_conn_ac_rst_sendack_flag - resets ack_must_be_send flag + * @sk: current connection structure + * @ev: current event + * + * This action resets ack_must_be_send flag of given connection, this flag + * indicates if there is any PDU which has not been acknowledged yet. + * Returns 0 for success, 1 otherwise. + */ +int llc_conn_ac_rst_sendack_flag(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->ack_must_be_send = LLC_SK(sk)->ack_pf = 0; + return 0; +} + +/** + * llc_conn_ac_send_i_rsp_f_set_ackpf - acknowledge received PDUs + * @sk: current connection structure + * @ev: current event + * + * Sends an I response PDU with f-bit set to ack_pf flag as acknowledge to + * all received PDUs which have not been acknowledged, yet. ack_pf flag is + * set to one if one PDU with p-bit set to one is received. Returns 0 for + * success, 1 otherwise. + */ +int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + struct sk_buff *skb = ev->data.prim.data->data->data.skb; + struct llc_opt *llc = LLC_SK(sk); + u8 p_bit = llc->ack_pf; + struct llc_sap *sap = llc->sap; + + llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_i_cmd(skb, p_bit, llc->vS, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + llc_conn_send_pdu(sk, skb); + llc_conn_ac_inc_vs_by_1(sk, ev); + return 0; +} + +/** + * llc_conn_ac_send_i_as_ack - sends an I-format PDU to acknowledge rx PDUs + * @sk: current connection structure. + * @ev: current event. + * + * This action sends an I-format PDU as acknowledge to received PDUs which + * have not been acknowledged, yet, if there is any. By using of this + * action number of acknowledgements decreases, this technic is called + * piggy backing. Returns 0 for success, 1 otherwise. + */ +int llc_conn_ac_send_i_as_ack(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + + if (llc->ack_must_be_send) { + llc_conn_ac_send_i_rsp_f_set_ackpf(sk, ev); + llc->ack_must_be_send = 0 ; + llc->ack_pf = 0; + } else + llc_conn_ac_send_i_cmd_p_set_0(sk, ev); + return 0; +} + +/** + * llc_conn_ac_send_rr_rsp_f_set_ackpf - ack all rx PDUs not yet acked + * @sk: current connection structure. + * @ev: current event. + * + * This action sends an RR response with f-bit set to ack_pf flag as + * acknowledge to all received PDUs which have not been acknowledged, yet, + * if there is any. ack_pf flag indicates if a PDU has been received with + * p-bit set to one. Returns 0 for success, 1 otherwise. + */ +int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct sk_buff *skb = llc_alloc_frame(); + + if (skb) { + struct llc_opt *llc = LLC_SK(sk); + struct llc_sap *sap = llc->sap; + u8 f_bit = llc->ack_pf; + + skb->dev = llc->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap, + llc->daddr.lsap, LLC_PDU_RSP); + llc_pdu_init_as_rr_rsp(skb, f_bit, llc->vR); + lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); + rc = 0; + llc_conn_send_pdu(sk, skb); + } + return rc; +} + +/** + * llc_conn_ac_inc_npta_value - tries to make value of npta greater + * @sk: current connection structure. + * @ev: current event. + * + * After "inc_cntr" times calling of this action, "npta" increase by one. + * this action tries to make vale of "npta" greater as possible; number of + * acknowledgements decreases by increasing of "npta". Returns 0 for + * success, 1 otherwise. + */ +int llc_conn_ac_inc_npta_value(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + + if (!llc->inc_cntr) { + llc->dec_step = 0; + llc->dec_cntr = llc->inc_cntr = 2; + ++llc->npta; + if (llc->npta > 127) + llc->npta = 127 ; + } else + --llc->inc_cntr; + return 0; +} + +/** + * llc_conn_ac_adjust_npta_by_rr - decreases "npta" by one + * @sk: current connection structure. + * @ev: current event. + * + * After receiving "dec_cntr" times RR command, this action decreases + * "npta" by one. Returns 0 for success, 1 otherwise. + */ +int llc_conn_ac_adjust_npta_by_rr(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + + if (!llc->connect_step && !llc->remote_busy_flag) { + if (!llc->dec_step) { + if (!llc->dec_cntr) { + llc->inc_cntr = llc->dec_cntr = 2; + if (llc->npta > 0) + llc->npta = llc->npta - 1; + } else + llc->dec_cntr -=1; + } + } else + llc->connect_step = 0 ; + return 0; +} + +/** + * llc_conn_ac_adjust_npta_by_rnr - decreases "npta" by one + * @sk: current connection structure. + * @ev: current event. + * + * After receiving "dec_cntr" times RNR command, this action decreases + * "npta" by one. Returns 0 for success, 1 otherwise. + */ +int llc_conn_ac_adjust_npta_by_rnr(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + + if (llc->remote_busy_flag) + if (!llc->dec_step) { + if (!llc->dec_cntr) { + llc->inc_cntr = llc->dec_cntr = 2; + if (llc->npta > 0) + --llc->npta; + } else + --llc->dec_cntr; + } + return 0; +} + +/** + * llc_conn_ac_dec_tx_win_size - decreases tx window size + * @sk: current connection structure. + * @ev: current event. + * + * After receiving of a REJ command or response, transmit window size is + * decreased by number of PDUs which are outstanding yet. Returns 0 for + * success, 1 otherwise. + */ +int llc_conn_ac_dec_tx_win_size(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + u8 unacked_pdu = skb_queue_len(&llc->pdu_unack_q); + + llc->k -= unacked_pdu; + if (llc->k < 2) + llc->k = 2; + return 0; +} + +/** + * llc_conn_ac_inc_tx_win_size - tx window size is inc by 1 + * @sk: current connection structure. + * @ev: current event. + * + * After receiving an RR response with f-bit set to one, transmit window + * size is increased by one. Returns 0 for success, 1 otherwise. + */ +int llc_conn_ac_inc_tx_win_size(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + + llc->k += 1; + if (llc->k > 128) + llc->k = 128 ; + return 0; +} + +int llc_conn_ac_stop_all_timers(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + + del_timer(&llc->pf_cycle_timer.timer); + llc->pf_cycle_timer.running = 0; + del_timer(&llc->ack_timer.timer); + llc->ack_timer.running = 0; + del_timer(&llc->rej_sent_timer.timer); + llc->rej_sent_timer.running = 0; + del_timer(&llc->busy_state_timer.timer); + llc->busy_state_timer.running = 0; + llc->ack_must_be_send = 0; + llc->ack_pf = 0; + return 0; +} + +int llc_conn_ac_stop_other_timers(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + + del_timer(&llc->rej_sent_timer.timer); + llc->rej_sent_timer.running = 0; + del_timer(&llc->pf_cycle_timer.timer); + llc->pf_cycle_timer.running = 0; + del_timer(&llc->busy_state_timer.timer); + llc->busy_state_timer.running = 0; + llc->ack_must_be_send = 0; + llc->ack_pf = 0; + return 0; +} + +int llc_conn_ac_start_ack_timer(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + + del_timer(&llc->ack_timer.timer); + llc->ack_timer.timer.expires = jiffies + llc->ack_timer.expire * HZ; + llc->ack_timer.timer.data = (unsigned long)sk; + llc->ack_timer.timer.function = llc_conn_ack_tmr_cb; + add_timer(&llc->ack_timer.timer); + llc->ack_timer.running = 1; + return 0; +} + +int llc_conn_ac_start_rej_timer(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + + del_timer(&llc->rej_sent_timer.timer); + llc->rej_sent_timer.timer.expires = jiffies + + llc->rej_sent_timer.expire * HZ; + llc->rej_sent_timer.timer.data = (unsigned long)sk; + llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb; + add_timer(&llc->rej_sent_timer.timer); + llc->rej_sent_timer.running = 1; + return 0; +} + +int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + + if (!llc->ack_timer.running) { + llc->ack_timer.timer.expires = jiffies + + llc->ack_timer.expire * HZ; + llc->ack_timer.timer.data = (unsigned long)sk; + llc->ack_timer.timer.function = llc_conn_ack_tmr_cb; + add_timer(&llc->ack_timer.timer); + llc->ack_timer.running = 1; + } + return 0; +} + +int llc_conn_ac_stop_ack_timer(struct sock *sk, struct llc_conn_state_ev *ev) +{ + del_timer(&LLC_SK(sk)->ack_timer.timer); + LLC_SK(sk)->ack_timer.running = 0; + return 0; +} + +int llc_conn_ac_stop_p_timer(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct llc_opt *llc = LLC_SK(sk); + + del_timer(&llc->pf_cycle_timer.timer); + llc->pf_cycle_timer.running = 0; + llc->p_flag = 0; + return 0; +} + +int llc_conn_ac_stop_rej_timer(struct sock *sk, struct llc_conn_state_ev *ev) +{ + del_timer(&LLC_SK(sk)->rej_sent_timer.timer); + LLC_SK(sk)->rej_sent_timer.running = 0; + return 0; +} + +int llc_conn_ac_upd_nr_received(struct sock *sk, struct llc_conn_state_ev *ev) +{ + int acked; + u16 unacked = 0; + u8 fbit; + struct sk_buff *skb = ev->data.pdu.skb; + llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)skb->nh.raw; + struct llc_opt *llc = LLC_SK(sk); + + llc->last_nr = PDU_SUPV_GET_Nr(rx_pdu); + acked = llc_conn_remove_acked_pdus(sk, llc->last_nr, &unacked); + /* On loopback we don't queue I frames in unack_pdu_q queue. */ + if (acked > 0 || (llc->dev->flags & IFF_LOOPBACK)) { + llc->retry_count = 0; + del_timer(&llc->ack_timer.timer); + llc->ack_timer.running = 0; + if (llc->failed_data_req) { + /* already, we did not accept data from upper + * layer(tx_window full or unacceptable state). now, we + * can send data and must inform to upper layer. */ + llc->failed_data_req = 0; + llc_conn_ac_data_confirm(sk, ev); + } + if (unacked) { + llc->ack_timer.timer.expires = jiffies + + llc->ack_timer.expire * HZ; + llc->ack_timer.timer.data = (unsigned long)sk; + llc->ack_timer.timer.function = llc_conn_ack_tmr_cb; + add_timer(&llc->ack_timer.timer); + llc->ack_timer.running = 1; + } + } else if (llc->failed_data_req) { + llc_pdu_decode_pf_bit(skb, &fbit); + if (fbit == 1) { + llc->failed_data_req = 0; + llc_conn_ac_data_confirm(sk, ev); + } + } + return 0; +} + +int llc_conn_ac_upd_p_flag(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct sk_buff *skb = ev->data.pdu.skb; + llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)skb->nh.raw; + u8 f_bit; + + if (!LLC_PDU_IS_RSP(rx_pdu) && + !llc_pdu_decode_pf_bit(skb, &f_bit) && f_bit) { + LLC_SK(sk)->p_flag = 0; + llc_conn_ac_stop_p_timer(sk, ev); + } + return 0; +} + +int llc_conn_ac_set_data_flag_2(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->data_flag = 2; + return 0; +} + +int llc_conn_ac_set_data_flag_0(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->data_flag = 0; + return 0; +} + +int llc_conn_ac_set_data_flag_1(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->data_flag = 1; + return 0; +} + +int llc_conn_ac_set_data_flag_1_if_data_flag_eq_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + if (!LLC_SK(sk)->data_flag) + LLC_SK(sk)->data_flag = 1; + return 0; +} + +int llc_conn_ac_set_p_flag_0(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->p_flag = 0; + return 0; +} + +int llc_conn_ac_set_p_flag_1(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->p_flag = 1; + return 0; +} + +int llc_conn_ac_set_remote_busy_0(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->remote_busy_flag = 0; + return 0; +} + +int llc_conn_ac_set_cause_flag_0(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->cause_flag = 0; + return 0; +} + +int llc_conn_ac_set_cause_flag_1(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->cause_flag = 1; + return 0; +} + +int llc_conn_ac_set_retry_cnt_0(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->retry_count = 0; + return 0; +} + +int llc_conn_ac_inc_retry_cnt_by_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->retry_count++; + return 0; +} + +int llc_conn_ac_set_vr_0(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->vR = 0; + return 0; +} + +int llc_conn_ac_inc_vr_by_1(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->vR = PDU_GET_NEXT_Vr(LLC_SK(sk)->vR); + return 0; +} + +int llc_conn_ac_set_vs_0(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->vS = 0; + return 0; +} + +int llc_conn_ac_set_vs_nr(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->vS = LLC_SK(sk)->last_nr; + return 0; +} + +int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->vS = (LLC_SK(sk)->vS + 1) % 128; + return 0; +} + +int llc_conn_ac_set_f_flag_p(struct sock *sk, struct llc_conn_state_ev *ev) +{ + llc_pdu_decode_pf_bit(ev->data.pdu.skb, &LLC_SK(sk)->f_flag); + return 0; +} + +void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data) +{ + struct sock *sk = (struct sock *)timeout_data; + struct llc_conn_state_ev *ev; + + LLC_SK(sk)->pf_cycle_timer.running = 0; + ev = llc_conn_alloc_ev(sk); + if (ev) { + ev->type = LLC_CONN_EV_TYPE_P_TMR; + ev->data.tmr.timer_specific = NULL; + llc_process_tmr_ev(sk, ev); + } +} + +static void llc_conn_busy_tmr_cb(unsigned long timeout_data) +{ + struct sock *sk = (struct sock *)timeout_data; + struct llc_conn_state_ev *ev; + + LLC_SK(sk)->busy_state_timer.running = 0; + ev = llc_conn_alloc_ev(sk); + if (ev) { + ev->type = LLC_CONN_EV_TYPE_BUSY_TMR; + ev->data.tmr.timer_specific = NULL; + llc_process_tmr_ev(sk, ev); + } +} + +void llc_conn_ack_tmr_cb(unsigned long timeout_data) +{ + struct sock* sk = (struct sock *)timeout_data; + struct llc_conn_state_ev *ev; + + LLC_SK(sk)->ack_timer.running = 0; + ev = llc_conn_alloc_ev(sk); + if (ev) { + ev->type = LLC_CONN_EV_TYPE_ACK_TMR; + ev->data.tmr.timer_specific = NULL; + llc_process_tmr_ev(sk, ev); + } +} + +static void llc_conn_rej_tmr_cb(unsigned long timeout_data) +{ + struct sock *sk = (struct sock *)timeout_data; + struct llc_conn_state_ev *ev; + + LLC_SK(sk)->rej_sent_timer.running = 0; + ev = llc_conn_alloc_ev(sk); + if (ev) { + ev->type = LLC_CONN_EV_TYPE_REJ_TMR; + ev->data.tmr.timer_specific = NULL; + llc_process_tmr_ev(sk, ev); + } +} + +int llc_conn_ac_rst_vs(struct sock *sk, struct llc_conn_state_ev *ev) +{ + LLC_SK(sk)->X = LLC_SK(sk)->vS; + llc_conn_ac_set_vs_nr(sk, ev); + return 0; +} + +int llc_conn_ac_upd_vs(struct sock *sk, struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + u8 nr = PDU_SUPV_GET_Nr(rx_pdu); + + if (llc_circular_between(LLC_SK(sk)->vS, nr, LLC_SK(sk)->X)) + llc_conn_ac_set_vs_nr(sk, ev); + return 0; +} + +/* + * Non-standard actions; these not contained in IEEE specification; for + * our own usage + */ +/** + * llc_conn_disc - removes connection from SAP list and frees it + * @sk: closed connection + * @ev: occurred event + * + * Returns 2, to indicate the state machine that the connection was freed. + */ +int llc_conn_disc(struct sock *sk, struct llc_conn_state_ev *ev) +{ + llc_sap_unassign_sock(LLC_SK(sk)->sap, sk); + llc_sock_free(sk); + return 2; +} + +/** + * llc_conn_reset - resets connection + * @sk : reseting connection. + * @ev: occurred event. + * + * Stop all timers, empty all queues and reset all flags. + */ +int llc_conn_reset(struct sock *sk, struct llc_conn_state_ev *ev) +{ + llc_sock_reset(sk); + return 0; +} + +/** + * llc_circular_between - designates that b is between a and c or not + * @a: lower bound + * @b: element to see if is between a and b + * @c: upper bound + * + * This function designates that b is between a and c or not (for example, + * 0 is between 127 and 1). Returns 1 if b is between a and c, 0 + * otherwise. + */ +u8 llc_circular_between(u8 a, u8 b, u8 c) +{ + b = b - a; + c = c - a; + return b <= c; +} + +/** + * llc_process_tmr_ev - timer backend + * @sk: active connection + * @ev: occurred event + * + * This function is called from timer callback functions. When connection + * is busy (during sending a data frame) timer expiration event must be + * queued. Otherwise this event can be sent to connection state machine. + * Queued events will process by process_rxframes_events function after + * sending data frame. Returns 0 for success, 1 otherwise. + */ +static void llc_process_tmr_ev(struct sock *sk, struct llc_conn_state_ev *ev) +{ + bh_lock_sock(sk); + if (LLC_SK(sk)->state == LLC_CONN_OUT_OF_SVC) { + printk(KERN_WARNING "timer called on closed connection\n"); + llc_conn_free_ev(ev); + goto out; + } + if (!sk->lock.users) + llc_conn_send_ev(sk, ev); + else { + struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC); + + if (skb) { + skb->cb[0] = LLC_EVENT; + skb->data = (void *)ev; + sk_add_backlog(sk, skb); + } else + llc_conn_free_ev(ev); + } +out: bh_unlock_sock(sk); +} Index: kernel-acme/net/llc/llc_c_ev.c diff -u /dev/null kernel-acme/net/llc/llc_c_ev.c:1.1.6.3 --- /dev/null Sat Dec 22 02:21:13 2001 +++ kernel-acme/net/llc/llc_c_ev.c Tue Dec 11 00:26:46 2001 @@ -0,0 +1,872 @@ +/* + * llc_c_ev.c - Connection component state transition event qualifiers + * + * A 'state' consists of a number of possible event matching functions, + * the actions associated with each being executed when that event is + * matched; a 'state machine' accepts events in a serial fashion from an + * event queue. Each event is passed to each successive event matching + * function until a match is made (the event matching function returns + * success, or '0') or the list of event matching functions is exhausted. + * If a match is made, the actions associated with the event are executed + * and the state is changed to that event's transition state. Before some + * events are recognized, even after a match has been made, a certain + * number of 'event qualifier' functions must also be executed. If these + * all execute successfully, then the event is finally executed. + * + * These event functions must return 0 for success, to show a matched + * event, of 1 if the event does not match. Event qualifier functions + * must return a 0 for success or a non-zero for failure. Each function + * is simply responsible for verifying one single thing and returning + * either a success or failure. + * + * All of followed event functions are described in 802.2 LLC Protocol + * standard document except two functions that we added that will explain + * in their comments, at below. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include + +#if 0 +#define dprintk(args...) printk(KERN_DEBUG args) +#else +#define dprintk(args...) +#endif + +extern u16 llc_circular_between(u8 a, u8 b, u8 c); + +/** + * llc_util_ns_inside_rx_window - check if sequence number is in rx window + * @ns: sequence number of received pdu. + * @vr: sequence number which receiver expects to receive. + * @rw: receive window size of receiver. + * + * Checks if sequence number of received PDU is in range of receive + * window. Returns 0 for success, 1 otherwise + */ +static u16 llc_util_ns_inside_rx_window(u8 ns, u8 vr, u8 rw) +{ + return !llc_circular_between(vr, ns, + (vr + rw - 1) % LLC_2_SEQ_NBR_MODULO); +} + +/** + * llc_util_nr_inside_tx_window - check if sequence number is in tx window + * @sk: current connection. + * @nr: N(R) of received PDU. + * + * This routine checks if N(R) of received PDU is in range of transmit + * window; on the other hand checks if received PDU acknowledges some + * outstanding PDUs that are in transmit window. Returns 0 for success, 1 + * otherwise. + */ +static u16 llc_util_nr_inside_tx_window(struct sock *sk, u8 nr) +{ + u8 nr1, nr2; + struct sk_buff *skb; + llc_pdu_sn_t *pdu; + struct llc_opt *llc = LLC_SK(sk); + int rc = 0; + + if (llc->dev->flags & IFF_LOOPBACK) + goto out; + rc = 1; + if (!skb_queue_len(&llc->pdu_unack_q)) + goto out; + skb = skb_peek(&llc->pdu_unack_q); + pdu = (llc_pdu_sn_t *)skb->nh.raw; + nr1 = LLC_I_GET_NS(pdu); + skb = skb_peek_tail(&llc->pdu_unack_q); + pdu = (llc_pdu_sn_t *)skb->nh.raw; + nr2 = LLC_I_GET_NS(pdu); + rc = !llc_circular_between(nr1, nr, (nr2 + 1) % LLC_2_SEQ_NBR_MODULO); +out: return rc; +} + +int llc_conn_ev_conn_req(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return ev->data.prim.prim == LLC_CONN_PRIM && + ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; +} + +int llc_conn_ev_conn_resp(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return ev->data.prim.prim == LLC_CONN_PRIM && + ev->data.prim.type == LLC_PRIM_TYPE_RESP ? 0 : 1; +} + +int llc_conn_ev_data_req(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return ev->data.prim.prim == LLC_DATA_PRIM && + ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; +} + +int llc_conn_ev_disc_req(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return ev->data.prim.prim == LLC_DISC_PRIM && + ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; +} + +int llc_conn_ev_rst_req(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return ev->data.prim.prim == LLC_RESET_PRIM && + ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; +} + +int llc_conn_ev_rst_resp(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return ev->data.prim.prim == LLC_RESET_PRIM && + ev->data.prim.type == LLC_PRIM_TYPE_RESP ? 0 : 1; +} + +int llc_conn_ev_local_busy_detected(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return ev->type == LLC_CONN_EV_TYPE_SIMPLE && + ev->data.a.ev == LLC_CONN_EV_LOCAL_BUSY_DETECTED ? 0 : 1; +} + +int llc_conn_ev_local_busy_cleared(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return ev->type == LLC_CONN_EV_TYPE_SIMPLE && + ev->data.a.ev == LLC_CONN_EV_LOCAL_BUSY_CLEARED ? 0 : 1; +} + +int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return 1; +} + +int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_U(pdu) && + LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_DISC ? 0 : 1; +} + +int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_U(pdu) && + LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_DM ? 0 : 1; +} + +int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_U(pdu) && + LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_FRMR ? 0 : 1; +} + +int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && + !LLC_I_PF_IS_0(pdu) && + LLC_I_GET_NS(pdu) == LLC_SK(sk)->vR ? 0 : 1; +} + +int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && + !LLC_I_PF_IS_1(pdu) && + LLC_I_GET_NS(pdu) == LLC_SK(sk)->vR ? 0 : 1; +} + +int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + u8 vr = LLC_SK(sk)->vR; + u8 ns = LLC_I_GET_NS(pdu); + + return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && + !LLC_I_PF_IS_0(pdu) && ns != vr && + !llc_util_ns_inside_rx_window(ns, vr, LLC_SK(sk)->rw) ? 0 : 1; +} + +int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + u8 vr = LLC_SK(sk)->vR; + u8 ns = LLC_I_GET_NS(pdu); + + return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && + !LLC_I_PF_IS_1(pdu) && ns != vr && + !llc_util_ns_inside_rx_window(ns, vr, LLC_SK(sk)->rw) ? 0 : 1; +} + +int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t * pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + u8 vr = LLC_SK(sk)->vR; + u8 ns = LLC_I_GET_NS(pdu); + u16 rc = !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && ns != vr && + llc_util_ns_inside_rx_window(ns, vr, LLC_SK(sk)->rw) ? 0 : 1; + if (!rc) + dprintk(KERN_WARNING "rx_i_cmd_p_bit_set_x_inval_ns matched," + "state = %d, ns = %d, vr = %d\n", + LLC_SK(sk)->state, ns, vr); + return rc; +} + +int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && + !LLC_I_PF_IS_0(pdu) && + LLC_I_GET_NS(pdu) == LLC_SK(sk)->vR ? 0 : 1; +} + +int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && + !LLC_I_PF_IS_1(pdu) && + LLC_I_GET_NS(pdu) == LLC_SK(sk)->vR ? 0 : 1; +} + +int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && + LLC_I_GET_NS(pdu) == LLC_SK(sk)->vR ? 0 : 1; +} + +int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + u8 vr = LLC_SK(sk)->vR; + u8 ns = LLC_I_GET_NS(pdu); + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && + !LLC_I_PF_IS_0(pdu) && ns != vr && + !llc_util_ns_inside_rx_window(ns, vr, LLC_SK(sk)->rw) ? 0 : 1; +} + +int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + u8 vr = LLC_SK(sk)->vR; + u8 ns = LLC_I_GET_NS(pdu); + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && + !LLC_I_PF_IS_1(pdu) && ns != vr && + !llc_util_ns_inside_rx_window(ns, vr, LLC_SK(sk)->rw) ? 0 : 1; +} + +int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + u8 vr = LLC_SK(sk)->vR; + u8 ns = LLC_I_GET_NS(pdu); + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && ns != vr && + !llc_util_ns_inside_rx_window(ns, vr, LLC_SK(sk)->rw) ? 0 : 1; +} + +int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + u8 vr = LLC_SK(sk)->vR; + u8 ns = LLC_I_GET_NS(pdu); + u16 rc = !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && ns != vr && + llc_util_ns_inside_rx_window(ns, vr, LLC_SK(sk)->rw) ? 0 : 1; + if (!rc) + dprintk(KERN_WARNING "conn_ev_rx_i_rsp_fbit_set_x_inval_ns " + "matched : state = %d, ns = %d, vr = %d\n", + LLC_SK(sk)->state, ns, vr); + return rc; +} + +int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_S(pdu) && + !LLC_S_PF_IS_0(pdu) && + LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_REJ ? 0 : 1; +} + +int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_S(pdu) && + !LLC_S_PF_IS_1(pdu) && + LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_REJ ? 0 : 1; +} + +int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) && + !LLC_S_PF_IS_0(pdu) && + LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1; +} + +int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) && + !LLC_S_PF_IS_1(pdu) && + LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1; +} + +int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) && + LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1; +} + +int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_S(pdu) && + !LLC_S_PF_IS_0(pdu) && + LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RNR ? 0 : 1; +} + +int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_S(pdu) && + !LLC_S_PF_IS_1(pdu) && + LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RNR ? 0 : 1; +} + +int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) && + !LLC_S_PF_IS_0(pdu) && + LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RNR ? 0 : 1; +} + +int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) && + !LLC_S_PF_IS_1(pdu) && + LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RNR ? 0 : 1; +} + +int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_S(pdu) && + !LLC_S_PF_IS_0(pdu) && + LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RR ? 0 : 1; +} + +int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_S(pdu) && + !LLC_S_PF_IS_1(pdu) && + LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RR ? 0 : 1; +} + +int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) && + !LLC_S_PF_IS_0(pdu) && + LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RR ? 0 : 1; +} + +int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) && + !LLC_S_PF_IS_1(pdu) && + LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RR ? 0 : 1; +} + +int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_U(pdu) && + LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_SABME ? 0 : 1; +} + +int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_U(pdu) && + LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_UA ? 0 : 1; +} + +int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u16 rc = 1; + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + if (!LLC_PDU_IS_CMD(pdu)) { + if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) { + if (!LLC_I_PF_IS_1(pdu)) + rc = 0; + } else if (!LLC_PDU_TYPE_IS_U(pdu) && !LLC_U_PF_IS_1(pdu)) + rc = 0; + } + return rc; +} + +int llc_conn_ev_rx_xxx_cmd_pbit_set_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u16 rc = 1; + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + if (!LLC_PDU_IS_CMD(pdu)) { + if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) { + if (!LLC_I_PF_IS_0(pdu)) + rc = 0; + } else if (!LLC_PDU_TYPE_IS_U(pdu)) + switch (LLC_U_PDU_CMD(pdu)) { + case LLC_2_PDU_CMD_SABME: + case LLC_2_PDU_CMD_DISC: + if (!LLC_U_PF_IS_0(pdu)) + rc = 0; + break; + } + } + return rc; +} + +int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u16 rc = 1; + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + if (!LLC_PDU_IS_CMD(pdu)) { + if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) + rc = 0; + else if (!LLC_PDU_TYPE_IS_U(pdu)) + switch (LLC_U_PDU_CMD(pdu)) { + case LLC_2_PDU_CMD_SABME: + case LLC_2_PDU_CMD_DISC: + rc = 0; + break; + } + } + return rc; +} + +int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u16 rc = 1; + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + if (!LLC_PDU_IS_RSP(pdu)) { + if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) { + if (!LLC_I_PF_IS_1(pdu)) + rc = 0; + } else if (!LLC_PDU_TYPE_IS_U(pdu)) + switch (LLC_U_PDU_RSP(pdu)) { + case LLC_2_PDU_RSP_UA: + case LLC_2_PDU_RSP_DM: + case LLC_2_PDU_RSP_FRMR: + if (!LLC_U_PF_IS_1(pdu)) + rc = 0; + break; + } + } + return rc; +} + +int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u16 rc = 1; + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + if (!LLC_PDU_IS_RSP(pdu)) { + if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) + rc = 0; + else if (!LLC_PDU_TYPE_IS_U(pdu)) + switch (LLC_U_PDU_RSP(pdu)) { + case LLC_2_PDU_RSP_UA: + case LLC_2_PDU_RSP_DM: + case LLC_2_PDU_RSP_FRMR: + rc = 0; + break; + } + } + + return rc; +} + +int llc_conn_ev_rx_xxx_yyy(struct sock *sk, struct llc_conn_state_ev *ev) +{ + u16 rc = 1; + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) + rc = 0; + else if (!LLC_PDU_TYPE_IS_U(pdu)) + switch (LLC_U_PDU_CMD(pdu)) { + case LLC_2_PDU_CMD_SABME: + case LLC_2_PDU_CMD_DISC: + case LLC_2_PDU_RSP_UA: + case LLC_2_PDU_RSP_DM: + case LLC_2_PDU_RSP_FRMR: + rc = 0; + break; + } + return rc; +} + +int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u16 rc = 1; + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + u8 vs = LLC_SK(sk)->vS; + u8 nr = LLC_I_GET_NR(pdu); + + if (!LLC_PDU_IS_CMD(pdu)) { + if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) { + if (nr != vs && + llc_util_nr_inside_tx_window(sk, nr)) { + dprintk(KERN_ERR "conn_ev_rx_zzz_cmd_inv_nr " + "matched, state = %d, vs = %d, " + "nr = %d\n", LLC_SK(sk)->state, vs, nr); + rc = 0; + } + } + } + return rc; +} + +int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + u16 rc = 1; + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + u8 vs = LLC_SK(sk)->vS; + u8 nr = LLC_I_GET_NR(pdu); + + if (!LLC_PDU_IS_RSP(pdu)) { + if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) { + if (nr != vs && + llc_util_nr_inside_tx_window(sk, nr)) { + rc = 0; + dprintk(KERN_ERR "conn_ev_rx_zzz_fbit_set" + "_x_inval_nr matched, state = %d, " + "vs = %d, nr = %d\n", + LLC_SK(sk)->state, vs, nr); + } + } + } + return rc; +} + +int llc_conn_ev_rx_any_frame(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return 0; +} + +int llc_conn_ev_p_tmr_exp(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return ev->type != LLC_CONN_EV_TYPE_P_TMR; +} + +int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return ev->type != LLC_CONN_EV_TYPE_ACK_TMR; +} + +int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return ev->type != LLC_CONN_EV_TYPE_REJ_TMR; +} + +int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return ev->type != LLC_CONN_EV_TYPE_BUSY_TMR; +} + +int llc_conn_ev_any_tmr_exp(struct sock *sk, struct llc_conn_state_ev *ev) +{ + + return ev->type == LLC_CONN_EV_TYPE_P_TMR || + ev->type == LLC_CONN_EV_TYPE_ACK_TMR || + ev->type == LLC_CONN_EV_TYPE_REJ_TMR || + ev->type == LLC_CONN_EV_TYPE_BUSY_TMR ? 0 : 1; +} + +int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return 1; +} + +int llc_conn_ev_tx_buffer_full(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return ev->type == LLC_CONN_EV_TYPE_SIMPLE && + ev->data.a.ev == LLC_CONN_EV_TX_BUFF_FULL ? 0 : 1; +} + +/* --------------------- EVENT QUALIFIER FUNCTIONS ----------------------- * + * these functions simply verify the value of a state flag associated with + * the connection and return either a 0 for success or a non-zero value + * for not-success; verify the event is the type we expect + * ----------------------------------------------------------------------- */ + +int llc_conn_ev_qlfy_data_flag_eq_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return LLC_SK(sk)->data_flag != 1; +} + +int llc_conn_ev_qlfy_data_flag_eq_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return LLC_SK(sk)->data_flag; +} + +int llc_conn_ev_qlfy_data_flag_eq_2(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return LLC_SK(sk)->data_flag != 2; +} + +int llc_conn_ev_qlfy_p_flag_eq_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return LLC_SK(sk)->p_flag != 1; +} + +/** + * conn_ev_qlfy_last_frame_eq_1 - checks if frame is last in tx window + * @sk: current connection structure. + * @ev: current event. + * + * This function determines when frame which is sent, is last frame of + * transmit window, if it is then this function return zero else return + * one. This function is used for sending last frame of transmit window + * as I-format command with p-bit set to one. Returns 0 if frame is last + * frame, 1 otherwise. + */ +int llc_conn_ev_qlfy_last_frame_eq_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return !(skb_queue_len(&LLC_SK(sk)->pdu_unack_q) + 1 == LLC_SK(sk)->k); +} + +/** + * conn_ev_qlfy_last_frame_eq_0 - checks if frame isn't last in tx window + * @sk: current connection structure. + * @ev: current event. + * + * This function determines when frame which is sent, isn't last frame of + * transmit window, if it isn't then this function return zero else return + * one. Returns 0 if frame isn't last frame, 1 otherwise. + */ +int llc_conn_ev_qlfy_last_frame_eq_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return skb_queue_len(&LLC_SK(sk)->pdu_unack_q) + 1 == LLC_SK(sk)->k; +} + +int llc_conn_ev_qlfy_p_flag_eq_0(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return LLC_SK(sk)->p_flag; +} + +int llc_conn_ev_qlfy_p_flag_eq_f(struct sock *sk, struct llc_conn_state_ev *ev) +{ + u8 f_bit; + struct sk_buff *skb; + + if (ev->type == LLC_CONN_EV_TYPE_PDU) + skb = ev->data.pdu.skb; + else + skb = ev->data.prim.data->data->conn.skb; + llc_pdu_decode_pf_bit(skb, &f_bit); + return LLC_SK(sk)->p_flag == f_bit ? 0 : 1; +} + +int llc_conn_ev_qlfy_remote_busy_eq_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return LLC_SK(sk)->remote_busy_flag; +} + +int llc_conn_ev_qlfy_remote_busy_eq_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return !LLC_SK(sk)->remote_busy_flag; +} + +int llc_conn_ev_qlfy_retry_cnt_lt_n2(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return !(LLC_SK(sk)->retry_count < LLC_SK(sk)->n2); +} + +int llc_conn_ev_qlfy_retry_cnt_gte_n2(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return !(LLC_SK(sk)->retry_count >= LLC_SK(sk)->n2); +} + +int llc_conn_ev_qlfy_s_flag_eq_1(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return !LLC_SK(sk)->s_flag; +} + +int llc_conn_ev_qlfy_s_flag_eq_0(struct sock *sk, struct llc_conn_state_ev *ev) +{ + return LLC_SK(sk)->s_flag; +} + +int llc_conn_ev_qlfy_cause_flag_eq_1(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return !LLC_SK(sk)->cause_flag; +} + +int llc_conn_ev_qlfy_cause_flag_eq_0(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return LLC_SK(sk)->cause_flag; +} + +int llc_conn_ev_qlfy_init_p_f_cycle(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + return 0; +} + +int llc_conn_ev_qlfy_set_status_conn(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + ev->status = LLC_STATUS_CONN; + return 0; +} + +int llc_conn_ev_qlfy_set_status_disc(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + ev->status = LLC_STATUS_DISC; + return 0; +} + +int llc_conn_ev_qlfy_set_status_impossible(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + ev->status = LLC_STATUS_IMPOSSIBLE; + return 0; +} + +int llc_conn_ev_qlfy_set_status_failed(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + ev->status = LLC_STATUS_FAILED; + return 0; +} + +int llc_conn_ev_qlfy_set_status_remote_busy(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + ev->status = LLC_STATUS_REMOTE_BUSY; + return 0; +} + +int llc_conn_ev_qlfy_set_status_received(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + ev->status = LLC_STATUS_RECEIVED; + return 0; +} + +int llc_conn_ev_qlfy_set_status_refuse(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + ev->status = LLC_STATUS_REFUSE; + return 0; +} + +int llc_conn_ev_qlfy_set_status_conflict(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + ev->status = LLC_STATUS_CONFLICT; + return 0; +} + +int llc_conn_ev_qlfy_set_status_rst_done(struct sock *sk, + struct llc_conn_state_ev *ev) +{ + ev->status = LLC_STATUS_RESET_DONE; + return 0; +} Index: kernel-acme/net/llc/llc_c_st.c diff -u /dev/null kernel-acme/net/llc/llc_c_st.c:1.1.6.2 --- /dev/null Sat Dec 22 02:21:13 2001 +++ kernel-acme/net/llc/llc_c_st.c Tue Dec 11 00:26:46 2001 @@ -0,0 +1,4897 @@ +/* + * llc_c_st.c - This module contains state transition of connection component. + * + * Description of event functions and actions there is in 802.2 LLC standard, + * or in "llc_c_ac.c" and "llc_c_ev.c" modules. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include + +#define LLC_NO_EVENT_QUALIFIERS NULL +#define LLC_NO_TRANSITION_ACTIONS NULL + +/* ----------------- COMMON CONNECTION STATE transitions ----------------- * + * Common transitions for + * LLC_CONN_STATE_NORMAL, + * LLC_CONN_STATE_BUSY, + * LLC_CONN_STATE_REJ, + * LLC_CONN_STATE_AWAIT, + * LLC_CONN_STATE_AWAIT_BUSY and + * LLC_CONN_STATE_AWAIT_REJ states + */ +/* State transitions for LLC_CONN_EV_DISC_REQ event */ +static llc_conn_action_t llc_common_actions_1[] = { + llc_conn_ac_send_disc_cmd_p_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_stop_other_timers, + llc_conn_ac_set_retry_cnt_0, + llc_conn_ac_set_cause_flag_1, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_1 = { + llc_conn_ev_disc_req, + LLC_CONN_STATE_D_CONN, + LLC_NO_EVENT_QUALIFIERS, + llc_common_actions_1 +}; + +/* State transitions for LLC_CONN_EV_RESET_REQ event */ +static llc_conn_action_t llc_common_actions_2[] = { + llc_conn_ac_send_sabme_cmd_p_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_stop_other_timers, + llc_conn_ac_set_retry_cnt_0, + llc_conn_ac_set_cause_flag_1, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_2 = { + llc_conn_ev_rst_req, + LLC_CONN_STATE_RESET, + LLC_NO_EVENT_QUALIFIERS, + llc_common_actions_2 +}; + +/* State transitions for LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X event */ +static llc_conn_action_t llc_common_actions_3[] = { + llc_conn_ac_stop_all_timers, + llc_conn_ac_set_vs_0, + llc_conn_ac_set_vr_0, + llc_conn_ac_send_ua_rsp_f_set_p, + llc_conn_ac_rst_ind, + llc_conn_ac_set_p_flag_0, + llc_conn_ac_set_remote_busy_0, + llc_conn_reset, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_3 = { + llc_conn_ev_rx_sabme_cmd_pbit_set_x, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_common_actions_3 +}; + +/* State transitions for LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X event */ +static llc_conn_action_t llc_common_actions_4[] = { + llc_conn_ac_stop_all_timers, + llc_conn_ac_send_ua_rsp_f_set_p, + llc_conn_ac_disc_ind, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_4 = { + llc_conn_ev_rx_disc_cmd_pbit_set_x, + LLC_CONN_STATE_ADM, + LLC_NO_EVENT_QUALIFIERS, + llc_common_actions_4 +}; + +/* State transitions for LLC_CONN_EV_RX_FRMR_RSP_Fbit_SET_X event */ +static llc_conn_action_t llc_common_actions_5[] = { + llc_conn_ac_send_sabme_cmd_p_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_stop_other_timers, + llc_conn_ac_set_retry_cnt_0, + llc_conn_ac_rst_ind, + llc_conn_ac_set_cause_flag_0, + llc_conn_reset, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_5 = { + llc_conn_ev_rx_frmr_rsp_fbit_set_x, + LLC_CONN_STATE_RESET, + LLC_NO_EVENT_QUALIFIERS, + llc_common_actions_5 +}; + +/* State transitions for LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X event */ +static llc_conn_action_t llc_common_actions_6[] = { + llc_conn_ac_disc_ind, + llc_conn_ac_stop_all_timers, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_6 = { + llc_conn_ev_rx_dm_rsp_fbit_set_x, + LLC_CONN_STATE_ADM, + LLC_NO_EVENT_QUALIFIERS, + llc_common_actions_6 +}; + +/* State transitions for LLC_CONN_EV_RX_ZZZ_CMD_Pbit_SET_X_INVAL_Nr event */ +static llc_conn_action_t llc_common_actions_7a[] = { + llc_conn_ac_send_frmr_rsp_f_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_stop_other_timers, + llc_conn_ac_set_retry_cnt_0, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_7a = { + llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr, + LLC_CONN_STATE_ERROR, + LLC_NO_EVENT_QUALIFIERS, + llc_common_actions_7a +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_X_INVAL_Ns event */ +static llc_conn_action_t llc_common_actions_7b[] = { + llc_conn_ac_send_frmr_rsp_f_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_stop_other_timers, + llc_conn_ac_set_retry_cnt_0, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_7b = { + llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns, + LLC_CONN_STATE_ERROR, + LLC_NO_EVENT_QUALIFIERS, + llc_common_actions_7b +}; + +/* State transitions for LLC_CONN_EV_RX_ZZZ_RSP_Fbit_SET_X_INVAL_Nr event */ +static llc_conn_action_t llc_common_actions_8a[] = { + llc_conn_ac_send_frmr_rsp_f_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_stop_other_timers, + llc_conn_ac_set_retry_cnt_0, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_8a = { + llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr, + LLC_CONN_STATE_ERROR, + LLC_NO_EVENT_QUALIFIERS, + llc_common_actions_8a +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_X_INVAL_Ns event */ +static llc_conn_action_t llc_common_actions_8b[] = { + llc_conn_ac_send_frmr_rsp_f_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_stop_other_timers, + llc_conn_ac_set_retry_cnt_0, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_8b = { + llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns, + LLC_CONN_STATE_ERROR, + LLC_NO_EVENT_QUALIFIERS, + llc_common_actions_8b +}; + +/* State transitions for LLC_CONN_EV_RX_BAD_PDU event */ +static llc_conn_action_t llc_common_actions_8c[] = { + llc_conn_ac_send_frmr_rsp_f_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_stop_other_timers, + llc_conn_ac_set_retry_cnt_0, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_8c = { + llc_conn_ev_rx_bad_pdu, + LLC_CONN_STATE_ERROR, + LLC_NO_EVENT_QUALIFIERS, + llc_common_actions_8c +}; + +/* State transitions for LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X event */ +static llc_conn_action_t llc_common_actions_9[] = { + llc_conn_ac_send_frmr_rsp_f_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_stop_other_timers, + llc_conn_ac_set_retry_cnt_0, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_9 = { + llc_conn_ev_rx_ua_rsp_fbit_set_x, + LLC_CONN_STATE_ERROR, + LLC_NO_EVENT_QUALIFIERS, + llc_common_actions_9 +}; + +/* State transitions for LLC_CONN_EV_RX_XXX_RSP_Fbit_SET_1 event */ +#if 0 +static llc_conn_ev_qfyr_t llc_common_ev_qfyrs_10[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_common_actions_10[] = { + llc_conn_ac_send_frmr_rsp_f_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_stop_other_timers, + llc_conn_ac_set_retry_cnt_0, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_10 = { + llc_conn_ev_rx_xxx_rsp_fbit_set_1, + LLC_CONN_STATE_ERROR, + llc_common_ev_qfyrs_10, + llc_common_actions_10 +}; +#endif + +/* State transitions for LLC_CONN_EV_P_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_common_ev_qfyrs_11a[] = { + llc_conn_ev_qlfy_retry_cnt_gte_n2, + NULL +}; + +static llc_conn_action_t llc_common_actions_11a[] = { + llc_conn_ac_send_sabme_cmd_p_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_stop_other_timers, + llc_conn_ac_set_retry_cnt_0, + llc_conn_ac_set_cause_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_11a = { + llc_conn_ev_p_tmr_exp, + LLC_CONN_STATE_RESET, + llc_common_ev_qfyrs_11a, + llc_common_actions_11a +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_common_ev_qfyrs_11b[] = { + llc_conn_ev_qlfy_retry_cnt_gte_n2, + NULL +}; + +static llc_conn_action_t llc_common_actions_11b[] = { + llc_conn_ac_send_sabme_cmd_p_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_stop_other_timers, + llc_conn_ac_set_retry_cnt_0, + llc_conn_ac_set_cause_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_11b = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_RESET, + llc_common_ev_qfyrs_11b, + llc_common_actions_11b +}; + +/* State transitions for LLC_CONN_EV_REJ_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_common_ev_qfyrs_11c[] = { + llc_conn_ev_qlfy_retry_cnt_gte_n2, + NULL +}; + +static llc_conn_action_t llc_common_actions_11c[] = { + llc_conn_ac_send_sabme_cmd_p_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_stop_other_timers, + llc_conn_ac_set_retry_cnt_0, + llc_conn_ac_set_cause_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_11c = { + llc_conn_ev_rej_tmr_exp, + LLC_CONN_STATE_RESET, + llc_common_ev_qfyrs_11c, + llc_common_actions_11c +}; + +/* State transitions for LLC_CONN_EV_BUSY_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_common_ev_qfyrs_11d[] = { + llc_conn_ev_qlfy_retry_cnt_gte_n2, + NULL +}; + +static llc_conn_action_t llc_common_actions_11d[] = { + llc_conn_ac_send_sabme_cmd_p_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_stop_other_timers, + llc_conn_ac_set_retry_cnt_0, + llc_conn_ac_set_cause_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_common_state_trans_11d = { + llc_conn_ev_busy_tmr_exp, + LLC_CONN_STATE_RESET, + llc_common_ev_qfyrs_11d, + llc_common_actions_11d +}; + +/* + * Common dummy state transition; must be last entry for all state + * transition groups - it'll be on .bss, so will be zeroed. + */ +static struct llc_conn_state_trans llc_common_state_trans_n; + +/* --------------------- LLC_CONN_STATE_ADM transitions -------------------- */ +/* State transitions for LLC_CONN_EV_CONN_REQ event */ +static llc_conn_action_t llc_adm_actions_1[] = { + llc_conn_ac_send_sabme_cmd_p_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_set_retry_cnt_0, + llc_conn_ac_set_s_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_adm_state_trans_1 = { + llc_conn_ev_conn_req, + LLC_CONN_STATE_SETUP, + LLC_NO_EVENT_QUALIFIERS, + llc_adm_actions_1 +}; + +/* State transitions for LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X event */ +static llc_conn_action_t llc_adm_actions_2[] = { + llc_conn_ac_send_ua_rsp_f_set_p, + llc_conn_ac_set_vs_0, + llc_conn_ac_set_vr_0, + llc_conn_ac_set_retry_cnt_0, + llc_conn_ac_set_p_flag_0, + llc_conn_ac_set_remote_busy_0, + llc_conn_ac_conn_ind, + NULL +}; + +static struct llc_conn_state_trans llc_adm_state_trans_2 = { + llc_conn_ev_rx_sabme_cmd_pbit_set_x, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_adm_actions_2 +}; + +/* State transitions for LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X event */ +static llc_conn_action_t llc_adm_actions_3[] = { + llc_conn_ac_send_dm_rsp_f_set_p, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_adm_state_trans_3 = { + llc_conn_ev_rx_disc_cmd_pbit_set_x, + LLC_CONN_STATE_ADM, + LLC_NO_EVENT_QUALIFIERS, + llc_adm_actions_3 +}; + +/* State transitions for LLC_CONN_EV_RX_XXX_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_adm_actions_4[] = { + llc_conn_ac_send_dm_rsp_f_set_1, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_adm_state_trans_4 = { + llc_conn_ev_rx_xxx_cmd_pbit_set_1, + LLC_CONN_STATE_ADM, + LLC_NO_EVENT_QUALIFIERS, + llc_adm_actions_4 +}; + +/* State transitions for LLC_CONN_EV_RX_XXX_YYY event */ +static llc_conn_action_t llc_adm_actions_5[] = { + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_adm_state_trans_5 = { + llc_conn_ev_rx_any_frame, + LLC_CONN_OUT_OF_SVC, + LLC_NO_EVENT_QUALIFIERS, + llc_adm_actions_5 +}; + +/* + * Array of pointers; + * one to each transition + */ +static struct llc_conn_state_trans *llc_adm_state_transitions[] = { + &llc_adm_state_trans_1, /* Request */ + &llc_common_state_trans_n, + &llc_common_state_trans_n, /* local_busy */ + &llc_common_state_trans_n, /* init_pf_cycle */ + &llc_common_state_trans_n, /* timer */ + &llc_adm_state_trans_2, /* Receive frame */ + &llc_adm_state_trans_3, + &llc_adm_state_trans_4, + &llc_adm_state_trans_5, + &llc_common_state_trans_n +}; + +/* --------------------- LLC_CONN_STATE_SETUP transitions ----------------- */ +/* State transitions for LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X event */ +static llc_conn_action_t llc_setup_actions_1[] = { + llc_conn_ac_send_ua_rsp_f_set_p, + llc_conn_ac_set_vs_0, + llc_conn_ac_set_vr_0, + llc_conn_ac_set_s_flag_1, + NULL +}; + +static struct llc_conn_state_trans llc_setup_state_trans_1 = { + llc_conn_ev_rx_sabme_cmd_pbit_set_x, + LLC_CONN_STATE_SETUP, + LLC_NO_EVENT_QUALIFIERS, + llc_setup_actions_1 +}; + +/* State transitions for LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X event */ +static llc_conn_ev_qfyr_t llc_setup_ev_qfyrs_2[] = { + llc_conn_ev_qlfy_p_flag_eq_f, + llc_conn_ev_qlfy_set_status_conn, + NULL +}; + +static llc_conn_action_t llc_setup_actions_2[] = { + llc_conn_ac_stop_ack_timer, + llc_conn_ac_set_vs_0, + llc_conn_ac_set_vr_0, + llc_conn_ac_upd_p_flag, + llc_conn_ac_set_remote_busy_0, + llc_conn_ac_conn_confirm, + NULL +}; + +static struct llc_conn_state_trans llc_setup_state_trans_2 = { + llc_conn_ev_rx_ua_rsp_fbit_set_x, + LLC_CONN_STATE_NORMAL, + llc_setup_ev_qfyrs_2, + llc_setup_actions_2 +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_setup_ev_qfyrs_3[] = { + llc_conn_ev_qlfy_s_flag_eq_1, + llc_conn_ev_qlfy_set_status_conn, + NULL +}; + +static llc_conn_action_t llc_setup_actions_3[] = { + llc_conn_ac_set_p_flag_0, + llc_conn_ac_set_remote_busy_0, + llc_conn_ac_conn_confirm, + NULL +}; + +static struct llc_conn_state_trans llc_setup_state_trans_3 = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_NORMAL, + llc_setup_ev_qfyrs_3, + llc_setup_actions_3 +}; + +/* State transitions for LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X event */ +static llc_conn_ev_qfyr_t llc_setup_ev_qfyrs_4[] = { + llc_conn_ev_qlfy_set_status_disc, + NULL +}; + +static llc_conn_action_t llc_setup_actions_4[] = { + llc_conn_ac_send_dm_rsp_f_set_p, + llc_conn_ac_stop_ack_timer, + llc_conn_ac_conn_confirm, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_setup_state_trans_4 = { + llc_conn_ev_rx_disc_cmd_pbit_set_x, + LLC_CONN_STATE_ADM, + llc_setup_ev_qfyrs_4, + llc_setup_actions_4 +}; + +/* State transitions for LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X event */ +static llc_conn_ev_qfyr_t llc_setup_ev_qfyrs_5[] = { + llc_conn_ev_qlfy_set_status_disc, + NULL +}; + +static llc_conn_action_t llc_setup_actions_5[] = { + llc_conn_ac_stop_ack_timer, + llc_conn_ac_conn_confirm, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_setup_state_trans_5 = { + llc_conn_ev_rx_dm_rsp_fbit_set_x, + LLC_CONN_STATE_ADM, + llc_setup_ev_qfyrs_5, + llc_setup_actions_5 +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_setup_ev_qfyrs_7[] = { + llc_conn_ev_qlfy_retry_cnt_lt_n2, + llc_conn_ev_qlfy_s_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_setup_actions_7[] = { + llc_conn_ac_send_sabme_cmd_p_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_inc_retry_cnt_by_1, + NULL +}; + +static struct llc_conn_state_trans llc_setup_state_trans_7 = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_SETUP, + llc_setup_ev_qfyrs_7, + llc_setup_actions_7 +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_setup_ev_qfyrs_8[] = { + llc_conn_ev_qlfy_retry_cnt_gte_n2, + llc_conn_ev_qlfy_s_flag_eq_0, + llc_conn_ev_qlfy_set_status_failed, + NULL +}; + +static llc_conn_action_t llc_setup_actions_8[] = { + llc_conn_ac_conn_confirm, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_setup_state_trans_8 = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_ADM, + llc_setup_ev_qfyrs_8, + llc_setup_actions_8 +}; + +/* + * Array of pointers; + * one to each transition + */ +static struct llc_conn_state_trans *llc_setup_state_transitions[] = { + &llc_common_state_trans_n, /* Request */ + &llc_common_state_trans_n, /* local busy */ + &llc_common_state_trans_n, /* init_pf_cycle */ + &llc_setup_state_trans_3, /* Timer */ + &llc_setup_state_trans_7, + &llc_setup_state_trans_8, + &llc_common_state_trans_n, + &llc_setup_state_trans_1, /* Receive frame */ + &llc_setup_state_trans_2, + &llc_setup_state_trans_4, + &llc_setup_state_trans_5, + &llc_common_state_trans_n +}; + +/* -------------------- LLC_CONN_STATE_NORMAL transitions ------------------ */ +/* State transitions for LLC_CONN_EV_DATA_REQ event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_1[] = { + llc_conn_ev_qlfy_remote_busy_eq_0, + llc_conn_ev_qlfy_p_flag_eq_0, + llc_conn_ev_qlfy_last_frame_eq_0, + NULL +}; + +static llc_conn_action_t llc_normal_actions_1[] = { + llc_conn_ac_send_i_as_ack, + llc_conn_ac_start_ack_tmr_if_not_running, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_1 = { + llc_conn_ev_data_req, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_1, + llc_normal_actions_1 +}; + +/* State transitions for LLC_CONN_EV_DATA_REQ event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_2[] = { + llc_conn_ev_qlfy_remote_busy_eq_0, + llc_conn_ev_qlfy_p_flag_eq_0, + llc_conn_ev_qlfy_last_frame_eq_1, + NULL +}; + +static llc_conn_action_t llc_normal_actions_2[] = { + llc_conn_ac_send_i_cmd_p_set_1, + llc_conn_ac_start_p_timer, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_2 = { + llc_conn_ev_data_req, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_2, + llc_normal_actions_2 +}; + +/* State transitions for LLC_CONN_EV_DATA_REQ event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_2_1[] = { + llc_conn_ev_qlfy_remote_busy_eq_1, + llc_conn_ev_qlfy_set_status_remote_busy, + NULL +}; + +/* just one member, NULL, .bss zeroes it */ +static llc_conn_action_t llc_normal_actions_2_1[1]; + +static struct llc_conn_state_trans llc_normal_state_trans_2_1 = { + llc_conn_ev_data_req, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_2_1, + llc_normal_actions_2_1 +}; + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_DETECTED event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_3[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_normal_actions_3[] = { + llc_conn_ac_rst_sendack_flag, + llc_conn_ac_send_rnr_xxx_x_set_0, + llc_conn_ac_set_data_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_3 = { + llc_conn_ev_local_busy_detected, + LLC_CONN_STATE_BUSY, + llc_normal_ev_qfyrs_3, + llc_normal_actions_3 +}; + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_DETECTED event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_4[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_normal_actions_4[] = { + llc_conn_ac_rst_sendack_flag, + llc_conn_ac_send_rnr_xxx_x_set_0, + llc_conn_ac_set_data_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_4 = { + llc_conn_ev_local_busy_detected, + LLC_CONN_STATE_BUSY, + llc_normal_ev_qfyrs_4, + llc_normal_actions_4 +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_5a[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_normal_actions_5a[] = { + llc_conn_ac_rst_sendack_flag, + llc_conn_ac_send_rej_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_p_flag, + llc_conn_ac_start_rej_timer, + llc_conn_ac_clear_remote_busy_if_f_eq_1, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_5a = { + llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns, + LLC_CONN_STATE_REJ, + llc_normal_ev_qfyrs_5a, + llc_normal_actions_5a +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_5b[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_normal_actions_5b[] = { + llc_conn_ac_rst_sendack_flag, + llc_conn_ac_send_rej_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_p_flag, + llc_conn_ac_start_rej_timer, + llc_conn_ac_clear_remote_busy_if_f_eq_1, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_5b = { + llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns, + LLC_CONN_STATE_REJ, + llc_normal_ev_qfyrs_5b, + llc_normal_actions_5b +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1_UNEXPD_Ns event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_5c[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_normal_actions_5c[] = { + llc_conn_ac_rst_sendack_flag, + llc_conn_ac_send_rej_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_p_flag, + llc_conn_ac_start_rej_timer, + llc_conn_ac_clear_remote_busy_if_f_eq_1, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_5c = { + llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns, + LLC_CONN_STATE_REJ, + llc_normal_ev_qfyrs_5c, + llc_normal_actions_5c +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_6a[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_normal_actions_6a[] = { + llc_conn_ac_rst_sendack_flag, + llc_conn_ac_send_rej_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_start_rej_timer, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_6a = { + llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns, + LLC_CONN_STATE_REJ, + llc_normal_ev_qfyrs_6a, + llc_normal_actions_6a +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_6b[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_normal_actions_6b[] = { + llc_conn_ac_rst_sendack_flag, + llc_conn_ac_send_rej_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_start_rej_timer, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_6b = { + llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns, + LLC_CONN_STATE_REJ, + llc_normal_ev_qfyrs_6b, + llc_normal_actions_6b +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns event */ +static llc_conn_action_t llc_normal_actions_7[] = { + llc_conn_ac_rst_sendack_flag, + llc_conn_ac_send_rej_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_start_rej_timer, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_7 = { + llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_normal_actions_7 +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_X event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_8a[] = { + llc_conn_ev_qlfy_p_flag_eq_f, + NULL +}; + +static llc_conn_action_t llc_normal_actions_8[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_clear_remote_busy_if_f_eq_1, + llc_conn_ac_send_ack_if_needed, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_8a = { + llc_conn_ev_rx_i_rsp_fbit_set_x, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_8a, + llc_normal_actions_8 +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_8b[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_8b = { + llc_conn_ev_rx_i_cmd_pbit_set_0, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_8b, + llc_normal_actions_8 +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_9a[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_normal_actions_9a[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_data_ind, + llc_conn_ac_send_ack_if_needed, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_9a = { + llc_conn_ev_rx_i_rsp_fbit_set_0, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_9a, + llc_normal_actions_9a +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_9b[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_normal_actions_9b[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_data_ind, + llc_conn_ac_send_ack_if_needed, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_9b = { + llc_conn_ev_rx_i_cmd_pbit_set_0, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_9b, + llc_normal_actions_9b +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_normal_actions_10[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_send_ack_rsp_f_set_1, + llc_conn_ac_rst_sendack_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_data_ind, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_10 = { + llc_conn_ev_rx_i_cmd_pbit_set_1, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_normal_actions_10 +}; + +/* State transitions for * LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_normal_actions_11a[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_11a = { + llc_conn_ev_rx_rr_cmd_pbit_set_0, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_normal_actions_11a +}; + +/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_normal_actions_11b[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_11b = { + llc_conn_ev_rx_rr_rsp_fbit_set_0, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_normal_actions_11b +}; + +/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_11c[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_normal_actions_11c[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_inc_tx_win_size, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_11c = { + llc_conn_ev_rx_rr_rsp_fbit_set_1, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_11c, + llc_normal_actions_11c +}; + +/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_normal_actions_12[] = { + llc_conn_ac_send_ack_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_adjust_npta_by_rr, + llc_conn_ac_rst_sendack_flag, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_12 = { + llc_conn_ev_rx_rr_cmd_pbit_set_1, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_normal_actions_12 +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_normal_actions_13a[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_13a = { + llc_conn_ev_rx_rnr_cmd_pbit_set_0, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_normal_actions_13a +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_normal_actions_13b[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_13b = { + llc_conn_ev_rx_rnr_rsp_fbit_set_0, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_normal_actions_13b +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_13c[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_normal_actions_13c[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_13c = { + llc_conn_ev_rx_rnr_rsp_fbit_set_1, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_13c, + llc_normal_actions_13c +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_normal_actions_14[] = { + llc_conn_ac_send_rr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_adjust_npta_by_rnr, + llc_conn_ac_rst_sendack_flag, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_14 = { + llc_conn_ev_rx_rnr_cmd_pbit_set_1, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_normal_actions_14 +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_15a[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_normal_actions_15a[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_p_flag, + llc_conn_ac_dec_tx_win_size, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_15a = { + llc_conn_ev_rx_rej_cmd_pbit_set_0, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_15a, + llc_normal_actions_15a +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_X event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_15b[] = { + llc_conn_ev_qlfy_p_flag_eq_f, + NULL +}; + +static llc_conn_action_t llc_normal_actions_15b[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_p_flag, + llc_conn_ac_dec_tx_win_size, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_15b = { + llc_conn_ev_rx_rej_rsp_fbit_set_x, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_15b, + llc_normal_actions_15b +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_16a[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_normal_actions_16a[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_dec_tx_win_size, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_16a = { + llc_conn_ev_rx_rej_cmd_pbit_set_0, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_16a, + llc_normal_actions_16a +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_16b[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_normal_actions_16b[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_dec_tx_win_size, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_16b = { + llc_conn_ev_rx_rej_rsp_fbit_set_0, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_16b, + llc_normal_actions_16b +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_normal_actions_17[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_dec_tx_win_size, + llc_conn_ac_resend_i_rsp_f_set_1, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_17 = { + llc_conn_ev_rx_rej_cmd_pbit_set_1, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_normal_actions_17 +}; + +/* State transitions for LLC_CONN_EV_INIT_P_F_CYCLE event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_18[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_normal_actions_18[] = { + llc_conn_ac_send_rr_cmd_p_set_1, + llc_conn_ac_start_p_timer, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_18 = { + llc_conn_ev_init_p_f_cycle, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_18, + llc_normal_actions_18 +}; + +/* State transitions for LLC_CONN_EV_P_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_19[] = { + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_normal_actions_19[] = { + llc_conn_ac_rst_sendack_flag, + llc_conn_ac_send_rr_cmd_p_set_1, + llc_conn_ac_rst_vs, + llc_conn_ac_start_p_timer, + llc_conn_ac_inc_retry_cnt_by_1, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_19 = { + llc_conn_ev_p_tmr_exp, + LLC_CONN_STATE_AWAIT, + llc_normal_ev_qfyrs_19, + llc_normal_actions_19 +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_20a[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_normal_actions_20a[] = { + llc_conn_ac_rst_sendack_flag, + llc_conn_ac_send_rr_cmd_p_set_1, + llc_conn_ac_rst_vs, + llc_conn_ac_start_p_timer, + llc_conn_ac_inc_retry_cnt_by_1, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_20a = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_AWAIT, + llc_normal_ev_qfyrs_20a, + llc_normal_actions_20a +}; + +/* State transitions for LLC_CONN_EV_BUSY_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_20b[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_normal_actions_20b[] = { + llc_conn_ac_rst_sendack_flag, + llc_conn_ac_send_rr_cmd_p_set_1, + llc_conn_ac_rst_vs, + llc_conn_ac_start_p_timer, + llc_conn_ac_inc_retry_cnt_by_1, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_20b = { + llc_conn_ev_busy_tmr_exp, + LLC_CONN_STATE_AWAIT, + llc_normal_ev_qfyrs_20b, + llc_normal_actions_20b +}; + +/* State transitions for LLC_CONN_EV_TX_BUFF_FULL event */ +static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_21[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_normal_actions_21[] = { + llc_conn_ac_send_rr_cmd_p_set_1, + llc_conn_ac_start_p_timer, + NULL +}; + +static struct llc_conn_state_trans llc_normal_state_trans_21 = { + llc_conn_ev_tx_buffer_full, + LLC_CONN_STATE_NORMAL, + llc_normal_ev_qfyrs_21, + llc_normal_actions_21 +}; + +/* + * Array of pointers; + * one to each transition + */ +static struct llc_conn_state_trans *llc_normal_state_transitions[] = { + &llc_normal_state_trans_1, /* Requests */ + &llc_normal_state_trans_2, + &llc_normal_state_trans_2_1, + &llc_common_state_trans_1, + &llc_common_state_trans_2, + &llc_common_state_trans_n, + &llc_normal_state_trans_21, + &llc_normal_state_trans_3, /* Local busy */ + &llc_normal_state_trans_4, + &llc_common_state_trans_n, + &llc_normal_state_trans_18, /* Init pf cycle */ + &llc_common_state_trans_n, + &llc_common_state_trans_11a, /* Timers */ + &llc_common_state_trans_11b, + &llc_common_state_trans_11c, + &llc_common_state_trans_11d, + &llc_normal_state_trans_19, + &llc_normal_state_trans_20a, + &llc_normal_state_trans_20b, + &llc_common_state_trans_n, + &llc_normal_state_trans_8b, /* Receive frames */ + &llc_normal_state_trans_9b, + &llc_normal_state_trans_10, + &llc_normal_state_trans_11b, + &llc_normal_state_trans_11c, + &llc_normal_state_trans_5a, + &llc_normal_state_trans_5b, + &llc_normal_state_trans_5c, + &llc_normal_state_trans_6a, + &llc_normal_state_trans_6b, + &llc_normal_state_trans_7, + &llc_normal_state_trans_8a, + &llc_normal_state_trans_9a, + &llc_normal_state_trans_11a, + &llc_normal_state_trans_12, + &llc_normal_state_trans_13a, + &llc_normal_state_trans_13b, + &llc_normal_state_trans_13c, + &llc_normal_state_trans_14, + &llc_normal_state_trans_15a, + &llc_normal_state_trans_15b, + &llc_normal_state_trans_16a, + &llc_normal_state_trans_16b, + &llc_normal_state_trans_17, + &llc_common_state_trans_3, + &llc_common_state_trans_4, + &llc_common_state_trans_5, + &llc_common_state_trans_6, + &llc_common_state_trans_7a, + &llc_common_state_trans_7b, + &llc_common_state_trans_8a, + &llc_common_state_trans_8b, + &llc_common_state_trans_8c, + &llc_common_state_trans_9, + /*&llc_common_state_trans_10, */ + &llc_common_state_trans_n +}; + +/* --------------------- LLC_CONN_STATE_BUSY transitions ------------------- */ +/* State transitions for LLC_CONN_EV_DATA_REQ event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_1[] = { + llc_conn_ev_qlfy_remote_busy_eq_0, + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_busy_actions_1[] = { + llc_conn_ac_send_i_xxx_x_set_0, + llc_conn_ac_start_ack_tmr_if_not_running, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_1 = { + llc_conn_ev_data_req, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_1, + llc_busy_actions_1 +}; + +/* State transitions for LLC_CONN_EV_DATA_REQ event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_2[] = { + llc_conn_ev_qlfy_remote_busy_eq_0, + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_busy_actions_2[] = { + llc_conn_ac_send_i_xxx_x_set_0, + llc_conn_ac_start_ack_tmr_if_not_running, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_2 = { + llc_conn_ev_data_req, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_2, + llc_busy_actions_2 +}; + +/* State transitions for LLC_CONN_EV_DATA_REQ event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_2_1[] = { + llc_conn_ev_qlfy_remote_busy_eq_1, + llc_conn_ev_qlfy_set_status_remote_busy, + NULL +}; + +/* just one member, NULL, .bss zeroes it */ +static llc_conn_action_t llc_busy_actions_2_1[1]; + +static struct llc_conn_state_trans llc_busy_state_trans_2_1 = { + llc_conn_ev_data_req, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_2_1, + llc_busy_actions_2_1 +}; + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_3[] = { + llc_conn_ev_qlfy_data_flag_eq_1, + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_busy_actions_3[] = { + llc_conn_ac_send_rej_xxx_x_set_0, + llc_conn_ac_start_rej_timer, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_3 = { + llc_conn_ev_local_busy_cleared, + LLC_CONN_STATE_REJ, + llc_busy_ev_qfyrs_3, + llc_busy_actions_3 +}; + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_4[] = { + llc_conn_ev_qlfy_data_flag_eq_1, + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_busy_actions_4[] = { + llc_conn_ac_send_rej_xxx_x_set_0, + llc_conn_ac_start_rej_timer, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_4 = { + llc_conn_ev_local_busy_cleared, + LLC_CONN_STATE_REJ, + llc_busy_ev_qfyrs_4, + llc_busy_actions_4 +}; + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_5[] = { + llc_conn_ev_qlfy_data_flag_eq_0, + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_busy_actions_5[] = { + llc_conn_ac_send_rr_xxx_x_set_0, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_5 = { + llc_conn_ev_local_busy_cleared, + LLC_CONN_STATE_NORMAL, + llc_busy_ev_qfyrs_5, + llc_busy_actions_5 +}; + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_6[] = { + llc_conn_ev_qlfy_data_flag_eq_0, + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_busy_actions_6[] = { + llc_conn_ac_send_rr_xxx_x_set_0, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_6 = { + llc_conn_ev_local_busy_cleared, + LLC_CONN_STATE_NORMAL, + llc_busy_ev_qfyrs_6, + llc_busy_actions_6 +}; + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_7[] = { + llc_conn_ev_qlfy_data_flag_eq_2, + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_busy_actions_7[] = { + llc_conn_ac_send_rr_xxx_x_set_0, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_7 = { + llc_conn_ev_local_busy_cleared, + LLC_CONN_STATE_REJ, + llc_busy_ev_qfyrs_7, + llc_busy_actions_7 +}; + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_8[] = { + llc_conn_ev_qlfy_data_flag_eq_2, + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_busy_actions_8[] = { + llc_conn_ac_send_rr_xxx_x_set_0, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_8 = { + llc_conn_ev_local_busy_cleared, + LLC_CONN_STATE_REJ, + llc_busy_ev_qfyrs_8, + llc_busy_actions_8 +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_X_UNEXPD_Ns event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_9a[] = { + llc_conn_ev_qlfy_p_flag_eq_f, + NULL +}; + +static llc_conn_action_t llc_busy_actions_9a[] = { + llc_conn_ac_opt_send_rnr_xxx_x_set_0, + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_data_flag_1_if_data_flag_eq_0, + llc_conn_ac_clear_remote_busy_if_f_eq_1, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_9a = { + llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_9a, + llc_busy_actions_9a +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_9b[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_busy_actions_9b[] = { + llc_conn_ac_opt_send_rnr_xxx_x_set_0, + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_data_flag_1_if_data_flag_eq_0, + llc_conn_ac_clear_remote_busy_if_f_eq_1, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_9b = { + llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_9b, + llc_busy_actions_9b +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_10a[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_busy_actions_10a[] = { + llc_conn_ac_opt_send_rnr_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_data_flag_1_if_data_flag_eq_0, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_10a = { + llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_10a, + llc_busy_actions_10a +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_10b[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_busy_actions_10b[] = { + llc_conn_ac_opt_send_rnr_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_data_flag_1_if_data_flag_eq_0, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_10b = { + llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_10b, + llc_busy_actions_10b +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns event */ +static llc_conn_action_t llc_busy_actions_11[] = { + llc_conn_ac_send_rnr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_data_flag_1_if_data_flag_eq_0, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_11 = { + llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns, + LLC_CONN_STATE_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_busy_actions_11 +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_busy_actions_12[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_send_rnr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2, + llc_conn_ac_set_data_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_12 = { + llc_conn_ev_rx_i_cmd_pbit_set_1, + LLC_CONN_STATE_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_busy_actions_12 +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_X event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_13a[] = { + llc_conn_ev_qlfy_p_flag_eq_f, + NULL +}; + +static llc_conn_action_t llc_busy_actions_13a[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_upd_p_flag, + llc_conn_ac_opt_send_rnr_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2, + llc_conn_ac_set_data_flag_0, + llc_conn_ac_clear_remote_busy_if_f_eq_1, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_13a = { + llc_conn_ev_rx_i_rsp_fbit_set_x, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_13a, + llc_busy_actions_13a +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_13b[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_busy_actions_13b[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_upd_p_flag, + llc_conn_ac_opt_send_rnr_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2, + llc_conn_ac_set_data_flag_0, + llc_conn_ac_clear_remote_busy_if_f_eq_1, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_13b = { + llc_conn_ev_rx_i_cmd_pbit_set_0, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_13b, + llc_busy_actions_13b +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_14a[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_busy_actions_14a[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_opt_send_rnr_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2, + llc_conn_ac_set_data_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_14a = { + llc_conn_ev_rx_i_rsp_fbit_set_0, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_14a, + llc_busy_actions_14a +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_14b[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_busy_actions_14b[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_opt_send_rnr_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2, + llc_conn_ac_set_data_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_14b = { + llc_conn_ev_rx_i_cmd_pbit_set_0, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_14b, + llc_busy_actions_14b +}; + +/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_busy_actions_15a[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_15a = { + llc_conn_ev_rx_rr_cmd_pbit_set_0, + LLC_CONN_STATE_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_busy_actions_15a +}; + +/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_busy_actions_15b[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_15b = { + llc_conn_ev_rx_rr_rsp_fbit_set_0, + LLC_CONN_STATE_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_busy_actions_15b +}; + +/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_15c[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_busy_actions_15c[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_15c = { + llc_conn_ev_rx_rr_rsp_fbit_set_1, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_15c, + llc_busy_actions_15c +}; + +/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_busy_actions_16[] = { + llc_conn_ac_send_rnr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_16 = { + llc_conn_ev_rx_rr_cmd_pbit_set_1, + LLC_CONN_STATE_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_busy_actions_16 +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_busy_actions_17a[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_17a = { + llc_conn_ev_rx_rnr_cmd_pbit_set_0, + LLC_CONN_STATE_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_busy_actions_17a +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_busy_actions_17b[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_17b = { + llc_conn_ev_rx_rnr_rsp_fbit_set_0, + LLC_CONN_STATE_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_busy_actions_17b +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_17c[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_busy_actions_17c[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_17c = { + llc_conn_ev_rx_rnr_rsp_fbit_set_1, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_17c, + llc_busy_actions_17c +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_busy_actions_18[] = { + llc_conn_ac_send_rnr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_18 = { + llc_conn_ev_rx_rnr_cmd_pbit_set_1, + LLC_CONN_STATE_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_busy_actions_18 +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_19a[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_busy_actions_19a[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_p_flag, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_19a = { + llc_conn_ev_rx_rej_cmd_pbit_set_0, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_19a, + llc_busy_actions_19a +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_X event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_19b[] = { + llc_conn_ev_qlfy_p_flag_eq_f, + NULL +}; + +static llc_conn_action_t llc_busy_actions_19b[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_p_flag, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_19b = { + llc_conn_ev_rx_rej_rsp_fbit_set_x, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_19b, + llc_busy_actions_19b +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_20a[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_busy_actions_20a[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_20a = { + llc_conn_ev_rx_rej_cmd_pbit_set_0, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_20a, + llc_busy_actions_20a +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_20b[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_busy_actions_20b[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_20b = { + llc_conn_ev_rx_rej_rsp_fbit_set_0, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_20b, + llc_busy_actions_20b +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_busy_actions_21[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_send_rnr_rsp_f_set_1, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_21 = { + llc_conn_ev_rx_rej_cmd_pbit_set_1, + LLC_CONN_STATE_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_busy_actions_21 +}; + +/* State transitions for LLC_CONN_EV_INIT_P_F_CYCLE event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_22[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_busy_actions_22[] = { + llc_conn_ac_send_rnr_cmd_p_set_1, + llc_conn_ac_start_p_timer, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_22 = { + llc_conn_ev_init_p_f_cycle, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_22, + llc_busy_actions_22 +}; + +/* State transitions for LLC_CONN_EV_P_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_23[] = { + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_busy_actions_23[] = { + llc_conn_ac_send_rnr_cmd_p_set_1, + llc_conn_ac_rst_vs, + llc_conn_ac_start_p_timer, + llc_conn_ac_inc_retry_cnt_by_1, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_23 = { + llc_conn_ev_p_tmr_exp, + LLC_CONN_STATE_AWAIT_BUSY, + llc_busy_ev_qfyrs_23, + llc_busy_actions_23 +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_24a[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_busy_actions_24a[] = { + llc_conn_ac_send_rnr_cmd_p_set_1, + llc_conn_ac_start_p_timer, + llc_conn_ac_inc_retry_cnt_by_1, + llc_conn_ac_rst_vs, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_24a = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_AWAIT_BUSY, + llc_busy_ev_qfyrs_24a, + llc_busy_actions_24a +}; + +/* State transitions for LLC_CONN_EV_BUSY_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_24b[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_busy_actions_24b[] = { + llc_conn_ac_send_rnr_cmd_p_set_1, + llc_conn_ac_start_p_timer, + llc_conn_ac_inc_retry_cnt_by_1, + llc_conn_ac_rst_vs, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_24b = { + llc_conn_ev_busy_tmr_exp, + LLC_CONN_STATE_AWAIT_BUSY, + llc_busy_ev_qfyrs_24b, + llc_busy_actions_24b +}; + +/* State transitions for LLC_CONN_EV_REJ_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_25[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_busy_actions_25[] = { + llc_conn_ac_send_rnr_cmd_p_set_1, + llc_conn_ac_start_p_timer, + llc_conn_ac_inc_retry_cnt_by_1, + llc_conn_ac_rst_vs, + llc_conn_ac_set_data_flag_1, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_25 = { + llc_conn_ev_rej_tmr_exp, + LLC_CONN_STATE_AWAIT_BUSY, + llc_busy_ev_qfyrs_25, + llc_busy_actions_25 +}; + +/* State transitions for LLC_CONN_EV_REJ_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_26[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_busy_actions_26[] = { + llc_conn_ac_set_data_flag_1, + NULL +}; + +static struct llc_conn_state_trans llc_busy_state_trans_26 = { + llc_conn_ev_rej_tmr_exp, + LLC_CONN_STATE_BUSY, + llc_busy_ev_qfyrs_26, + llc_busy_actions_26 +}; + +/* + * Array of pointers; + * one to each transition + */ +static struct llc_conn_state_trans *llc_busy_state_transitions[] = { + &llc_common_state_trans_1, /* Request */ + &llc_common_state_trans_2, + &llc_busy_state_trans_1, + &llc_busy_state_trans_2, + &llc_busy_state_trans_2_1, + &llc_common_state_trans_n, + &llc_busy_state_trans_3, /* Local busy */ + &llc_busy_state_trans_4, + &llc_busy_state_trans_5, + &llc_busy_state_trans_6, + &llc_busy_state_trans_7, + &llc_busy_state_trans_8, + &llc_common_state_trans_n, + &llc_busy_state_trans_22, /* Initiate PF cycle */ + &llc_common_state_trans_n, + &llc_common_state_trans_11a, /* Timer */ + &llc_common_state_trans_11b, + &llc_common_state_trans_11c, + &llc_common_state_trans_11d, + &llc_busy_state_trans_23, + &llc_busy_state_trans_24a, + &llc_busy_state_trans_24b, + &llc_busy_state_trans_25, + &llc_busy_state_trans_26, + &llc_common_state_trans_n, + &llc_busy_state_trans_9a, /* Receive frame */ + &llc_busy_state_trans_9b, + &llc_busy_state_trans_10a, + &llc_busy_state_trans_10b, + &llc_busy_state_trans_11, + &llc_busy_state_trans_12, + &llc_busy_state_trans_13a, + &llc_busy_state_trans_13b, + &llc_busy_state_trans_14a, + &llc_busy_state_trans_14b, + &llc_busy_state_trans_15a, + &llc_busy_state_trans_15b, + &llc_busy_state_trans_15c, + &llc_busy_state_trans_16, + &llc_busy_state_trans_17a, + &llc_busy_state_trans_17b, + &llc_busy_state_trans_17c, + &llc_busy_state_trans_18, + &llc_busy_state_trans_19a, + &llc_busy_state_trans_19b, + &llc_busy_state_trans_20a, + &llc_busy_state_trans_20b, + &llc_busy_state_trans_21, + &llc_common_state_trans_3, + &llc_common_state_trans_4, + &llc_common_state_trans_5, + &llc_common_state_trans_6, + &llc_common_state_trans_7a, + &llc_common_state_trans_7b, + &llc_common_state_trans_8a, + &llc_common_state_trans_8b, + &llc_common_state_trans_8c, + &llc_common_state_trans_9, + /* &llc_common_state_trans_10, */ + &llc_common_state_trans_n +}; + +/* -------------------- LLC_CONN_STATE_REJ transitions ------------------ */ +/* State transitions for LLC_CONN_EV_DATA_REQ event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_1[] = { + llc_conn_ev_qlfy_remote_busy_eq_0, + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_reject_actions_1[] = { + llc_conn_ac_send_i_xxx_x_set_0, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_1 = { + llc_conn_ev_data_req, + LLC_CONN_STATE_REJ, + llc_reject_ev_qfyrs_1, + llc_reject_actions_1 +}; + +/* State transitions for LLC_CONN_EV_DATA_REQ event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_2[] = { + llc_conn_ev_qlfy_remote_busy_eq_0, + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_reject_actions_2[] = { + llc_conn_ac_send_i_xxx_x_set_0, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_2 = { + llc_conn_ev_data_req, + LLC_CONN_STATE_REJ, + llc_reject_ev_qfyrs_2, + llc_reject_actions_2 +}; + +/* State transitions for LLC_CONN_EV_DATA_REQ event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_2_1[] = { + llc_conn_ev_qlfy_remote_busy_eq_1, + llc_conn_ev_qlfy_set_status_remote_busy, + NULL +}; + +/* just one member, NULL, .bss zeroes it */ +static llc_conn_action_t llc_reject_actions_2_1[1]; + +static struct llc_conn_state_trans llc_reject_state_trans_2_1 = { + llc_conn_ev_data_req, + LLC_CONN_STATE_REJ, + llc_reject_ev_qfyrs_2_1, + llc_reject_actions_2_1 +}; + + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_DETECTED event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_3[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_reject_actions_3[] = { + llc_conn_ac_send_rnr_xxx_x_set_0, + llc_conn_ac_set_data_flag_2, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_3 = { + llc_conn_ev_local_busy_detected, + LLC_CONN_STATE_BUSY, + llc_reject_ev_qfyrs_3, + llc_reject_actions_3 +}; + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_DETECTED event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_4[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_reject_actions_4[] = { + llc_conn_ac_send_rnr_xxx_x_set_0, + llc_conn_ac_set_data_flag_2, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_4 = { + llc_conn_ev_local_busy_detected, + LLC_CONN_STATE_BUSY, + llc_reject_ev_qfyrs_4, + llc_reject_actions_4 +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */ +static llc_conn_action_t llc_reject_actions_5a[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_p_flag, + llc_conn_ac_clear_remote_busy_if_f_eq_1, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_5a = { + llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_reject_actions_5a +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns event */ +static llc_conn_action_t llc_reject_actions_5b[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_p_flag, + llc_conn_ac_clear_remote_busy_if_f_eq_1, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_5b = { + llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_reject_actions_5b +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1_UNEXPD_Ns event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_5c[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_reject_actions_5c[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_p_flag, + llc_conn_ac_clear_remote_busy_if_f_eq_1, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_5c = { + llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns, + LLC_CONN_STATE_REJ, + llc_reject_ev_qfyrs_5c, + llc_reject_actions_5c +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns event */ +static llc_conn_action_t llc_reject_actions_6[] = { + llc_conn_ac_send_rr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_6 = { + llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_reject_actions_6 +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_X event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_7a[] = { + llc_conn_ev_qlfy_p_flag_eq_f, + NULL +}; + +static llc_conn_action_t llc_reject_actions_7a[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_upd_p_flag, + llc_conn_ac_send_ack_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_clear_remote_busy_if_f_eq_1, + llc_conn_ac_stop_rej_timer, + NULL + +}; + +static struct llc_conn_state_trans llc_reject_state_trans_7a = { + llc_conn_ev_rx_i_rsp_fbit_set_x, + LLC_CONN_STATE_NORMAL, + llc_reject_ev_qfyrs_7a, + llc_reject_actions_7a +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_7b[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_reject_actions_7b[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_upd_p_flag, + llc_conn_ac_send_ack_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_clear_remote_busy_if_f_eq_1, + llc_conn_ac_stop_rej_timer, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_7b = { + llc_conn_ev_rx_i_cmd_pbit_set_0, + LLC_CONN_STATE_NORMAL, + llc_reject_ev_qfyrs_7b, + llc_reject_actions_7b +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_8a[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_reject_actions_8a[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_send_ack_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_stop_rej_timer, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_8a = { + llc_conn_ev_rx_i_rsp_fbit_set_0, + LLC_CONN_STATE_NORMAL, + llc_reject_ev_qfyrs_8a, + llc_reject_actions_8a +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_8b[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_reject_actions_8b[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_send_ack_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_stop_rej_timer, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_8b = { + llc_conn_ev_rx_i_cmd_pbit_set_0, + LLC_CONN_STATE_NORMAL, + llc_reject_ev_qfyrs_8b, + llc_reject_actions_8b +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_reject_actions_9[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_send_ack_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_stop_rej_timer, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_9 = { + llc_conn_ev_rx_i_cmd_pbit_set_1, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_reject_actions_9 +}; + +/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_reject_actions_10a[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_10a = { + llc_conn_ev_rx_rr_cmd_pbit_set_0, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_reject_actions_10a +}; + +/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_reject_actions_10b[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_10b = { + llc_conn_ev_rx_rr_rsp_fbit_set_0, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_reject_actions_10b +}; + +/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_10c[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_reject_actions_10c[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_10c = { + llc_conn_ev_rx_rr_rsp_fbit_set_1, + LLC_CONN_STATE_REJ, + llc_reject_ev_qfyrs_10c, + llc_reject_actions_10c +}; + +/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_reject_actions_11[] = { + llc_conn_ac_send_ack_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_11 = { + llc_conn_ev_rx_rr_cmd_pbit_set_1, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_reject_actions_11 +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_reject_actions_12a[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_12a = { + llc_conn_ev_rx_rnr_cmd_pbit_set_0, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_reject_actions_12a +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_reject_actions_12b[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_12b = { + llc_conn_ev_rx_rnr_rsp_fbit_set_0, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_reject_actions_12b +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_12c[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_reject_actions_12c[] = { + llc_conn_ac_upd_p_flag, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_12c = { + llc_conn_ev_rx_rnr_rsp_fbit_set_1, + LLC_CONN_STATE_REJ, + llc_reject_ev_qfyrs_12c, + llc_reject_actions_12c +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_reject_actions_13[] = { + llc_conn_ac_send_rr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_13 = { + llc_conn_ev_rx_rnr_cmd_pbit_set_1, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_reject_actions_13 +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_14a[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_reject_actions_14a[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_p_flag, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_14a = { + llc_conn_ev_rx_rej_cmd_pbit_set_0, + LLC_CONN_STATE_REJ, + llc_reject_ev_qfyrs_14a, + llc_reject_actions_14a +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_X event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_14b[] = { + llc_conn_ev_qlfy_p_flag_eq_f, + NULL +}; + +static llc_conn_action_t llc_reject_actions_14b[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_p_flag, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_14b = { + llc_conn_ev_rx_rej_rsp_fbit_set_x, + LLC_CONN_STATE_REJ, + llc_reject_ev_qfyrs_14b, + llc_reject_actions_14b +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_15a[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_reject_actions_15a[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_15a = { + llc_conn_ev_rx_rej_cmd_pbit_set_0, + LLC_CONN_STATE_REJ, + llc_reject_ev_qfyrs_15a, + llc_reject_actions_15a +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_15b[] = { + llc_conn_ev_qlfy_p_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_reject_actions_15b[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_15b = { + llc_conn_ev_rx_rej_rsp_fbit_set_0, + LLC_CONN_STATE_REJ, + llc_reject_ev_qfyrs_15b, + llc_reject_actions_15b +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_reject_actions_16[] = { + llc_conn_ac_set_vs_nr, + llc_conn_ac_upd_nr_received, + llc_conn_ac_resend_i_rsp_f_set_1, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_16 = { + llc_conn_ev_rx_rej_cmd_pbit_set_1, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_reject_actions_16 +}; + +/* State transitions for LLC_CONN_EV_INIT_P_F_CYCLE event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_17[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_reject_actions_17[] = { + llc_conn_ac_send_rr_cmd_p_set_1, + llc_conn_ac_start_p_timer, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_17 = { + llc_conn_ev_init_p_f_cycle, + LLC_CONN_STATE_REJ, + llc_reject_ev_qfyrs_17, + llc_reject_actions_17 +}; + +/* State transitions for LLC_CONN_EV_REJ_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_18[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_reject_actions_18[] = { + llc_conn_ac_send_rej_cmd_p_set_1, + llc_conn_ac_start_p_timer, + llc_conn_ac_start_rej_timer, + llc_conn_ac_inc_retry_cnt_by_1, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_18 = { + llc_conn_ev_rej_tmr_exp, + LLC_CONN_STATE_REJ, + llc_reject_ev_qfyrs_18, + llc_reject_actions_18 +}; + +/* State transitions for LLC_CONN_EV_P_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_19[] = { + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_reject_actions_19[] = { + llc_conn_ac_send_rr_cmd_p_set_1, + llc_conn_ac_start_p_timer, + llc_conn_ac_start_rej_timer, + llc_conn_ac_inc_retry_cnt_by_1, + llc_conn_ac_rst_vs, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_19 = { + llc_conn_ev_p_tmr_exp, + LLC_CONN_STATE_AWAIT_REJ, + llc_reject_ev_qfyrs_19, + llc_reject_actions_19 +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_20a[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_reject_actions_20a[] = { + llc_conn_ac_send_rr_cmd_p_set_1, + llc_conn_ac_start_p_timer, + llc_conn_ac_start_rej_timer, + llc_conn_ac_inc_retry_cnt_by_1, + llc_conn_ac_rst_vs, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_20a = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_AWAIT_REJ, + llc_reject_ev_qfyrs_20a, + llc_reject_actions_20a +}; + +/* State transitions for LLC_CONN_EV_BUSY_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_20b[] = { + llc_conn_ev_qlfy_p_flag_eq_0, + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_reject_actions_20b[] = { + llc_conn_ac_send_rr_cmd_p_set_1, + llc_conn_ac_start_p_timer, + llc_conn_ac_start_rej_timer, + llc_conn_ac_inc_retry_cnt_by_1, + llc_conn_ac_rst_vs, + NULL +}; + +static struct llc_conn_state_trans llc_reject_state_trans_20b = { + llc_conn_ev_busy_tmr_exp, + LLC_CONN_STATE_AWAIT_REJ, + llc_reject_ev_qfyrs_20b, + llc_reject_actions_20b +}; + +/* + * Array of pointers; + * one to each transition + */ +static struct llc_conn_state_trans *llc_reject_state_transitions[] = { + &llc_common_state_trans_1, /* Request */ + &llc_common_state_trans_2, + &llc_common_state_trans_n, + &llc_reject_state_trans_1, + &llc_reject_state_trans_2, + &llc_reject_state_trans_2_1, + &llc_reject_state_trans_3, /* Local busy */ + &llc_reject_state_trans_4, + &llc_common_state_trans_n, + &llc_reject_state_trans_17, /* Initiate PF cycle */ + &llc_common_state_trans_n, + &llc_common_state_trans_11a, /* Timer */ + &llc_common_state_trans_11b, + &llc_common_state_trans_11c, + &llc_common_state_trans_11d, + &llc_reject_state_trans_18, + &llc_reject_state_trans_19, + &llc_reject_state_trans_20a, + &llc_reject_state_trans_20b, + &llc_common_state_trans_n, + &llc_common_state_trans_3, /* Receive frame */ + &llc_common_state_trans_4, + &llc_common_state_trans_5, + &llc_common_state_trans_6, + &llc_common_state_trans_7a, + &llc_common_state_trans_7b, + &llc_common_state_trans_8a, + &llc_common_state_trans_8b, + &llc_common_state_trans_8c, + &llc_common_state_trans_9, + /* &llc_common_state_trans_10, */ + &llc_reject_state_trans_5a, + &llc_reject_state_trans_5b, + &llc_reject_state_trans_5c, + &llc_reject_state_trans_6, + &llc_reject_state_trans_7a, + &llc_reject_state_trans_7b, + &llc_reject_state_trans_8a, + &llc_reject_state_trans_8b, + &llc_reject_state_trans_9, + &llc_reject_state_trans_10a, + &llc_reject_state_trans_10b, + &llc_reject_state_trans_10c, + &llc_reject_state_trans_11, + &llc_reject_state_trans_12a, + &llc_reject_state_trans_12b, + &llc_reject_state_trans_12c, + &llc_reject_state_trans_13, + &llc_reject_state_trans_14a, + &llc_reject_state_trans_14b, + &llc_reject_state_trans_15a, + &llc_reject_state_trans_15b, + &llc_reject_state_trans_16, + &llc_common_state_trans_n +}; + +/* -------------------- LLC_CONN_STATE_AWAIT transitions ------------------- */ +/* State transitions for LLC_CONN_EV_DATA_REQ event */ +static llc_conn_ev_qfyr_t llc_await_ev_qfyrs_1_0[] = { + llc_conn_ev_qlfy_set_status_refuse, + NULL +}; + +/* just one member, NULL, .bss zeroes it */ +static llc_conn_action_t llc_await_actions_1_0[1]; + +static struct llc_conn_state_trans llc_await_state_trans_1_0 = { + llc_conn_ev_data_req, + LLC_CONN_STATE_AWAIT, + llc_await_ev_qfyrs_1_0, + llc_await_actions_1_0 +}; + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_DETECTED event */ +static llc_conn_action_t llc_await_actions_1[] = { + llc_conn_ac_send_rnr_xxx_x_set_0, + llc_conn_ac_set_data_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_1 = { + llc_conn_ev_local_busy_detected, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_1 +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1_UNEXPD_Ns event */ +static llc_conn_action_t llc_await_actions_2[] = { + llc_conn_ac_send_rej_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_stop_p_timer, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_start_rej_timer, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_2 = { + llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_2 +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */ +static llc_conn_action_t llc_await_actions_3a[] = { + llc_conn_ac_send_rej_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_start_rej_timer, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_3a = { + llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_3a +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns event */ +static llc_conn_action_t llc_await_actions_3b[] = { + llc_conn_ac_send_rej_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_start_rej_timer, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_3b = { + llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_3b +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns event */ +static llc_conn_action_t llc_await_actions_4[] = { + llc_conn_ac_send_rej_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_start_rej_timer, + llc_conn_ac_start_p_timer, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_4 = { + llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_4 +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1 event */ +static llc_conn_action_t llc_await_actions_5[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_stop_p_timer, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_5 = { + llc_conn_ev_rx_i_rsp_fbit_set_1, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_5 +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_await_actions_6a[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_send_rr_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_6a = { + llc_conn_ev_rx_i_rsp_fbit_set_0, + LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_6a +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_await_actions_6b[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_send_rr_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_6b = { + llc_conn_ev_rx_i_cmd_pbit_set_0, + LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_6b +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_await_actions_7[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_send_rr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_7 = { + llc_conn_ev_rx_i_cmd_pbit_set_1, + LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_7 +}; + +/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 event */ +static llc_conn_action_t llc_await_actions_8a[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_stop_p_timer, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_8a = { + llc_conn_ev_rx_rr_rsp_fbit_set_1, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_8a +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_1 event */ +static llc_conn_action_t llc_await_actions_8b[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_stop_p_timer, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_8b = { + llc_conn_ev_rx_rej_rsp_fbit_set_1, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_8b +}; + +/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_await_actions_9a[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_9a = { + llc_conn_ev_rx_rr_cmd_pbit_set_0, + LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_9a +}; + +/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_await_actions_9b[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_9b = { + llc_conn_ev_rx_rr_rsp_fbit_set_0, + LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_9b +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_await_actions_9c[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_9c = { + llc_conn_ev_rx_rej_cmd_pbit_set_0, + LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_9c +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_await_actions_9d[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_9d = { + llc_conn_ev_rx_rej_rsp_fbit_set_0, + LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_9d +}; + +/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_await_actions_10a[] = { + llc_conn_ac_send_rr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_10a = { + llc_conn_ev_rx_rr_cmd_pbit_set_1, + LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_10a +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_await_actions_10b[] = { + llc_conn_ac_send_rr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_10b = { + llc_conn_ev_rx_rej_cmd_pbit_set_1, + LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_10b +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 event */ +static llc_conn_action_t llc_await_actions_11[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_stop_p_timer, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_11 = { + llc_conn_ev_rx_rnr_rsp_fbit_set_1, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_11 +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_await_actions_12a[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_12a = { + llc_conn_ev_rx_rnr_cmd_pbit_set_0, + LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_12a +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_await_actions_12b[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_12b = { + llc_conn_ev_rx_rnr_rsp_fbit_set_0, + LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_12b +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_await_actions_13[] = { + llc_conn_ac_send_rr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_13 = { + llc_conn_ev_rx_rnr_cmd_pbit_set_1, + LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, + llc_await_actions_13 +}; + +/* State transitions for LLC_CONN_EV_P_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_await_ev_qfyrs_14[] = { + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_await_actions_14[] = { + llc_conn_ac_send_rr_cmd_p_set_1, + llc_conn_ac_start_p_timer, + llc_conn_ac_inc_retry_cnt_by_1, + NULL +}; + +static struct llc_conn_state_trans llc_await_state_trans_14 = { + llc_conn_ev_p_tmr_exp, + LLC_CONN_STATE_AWAIT, + llc_await_ev_qfyrs_14, + llc_await_actions_14 +}; + +/* + * Array of pointers; + * one to each transition + */ +static struct llc_conn_state_trans *llc_await_state_transitions[] = { + &llc_common_state_trans_1, /* Request */ + &llc_common_state_trans_2, + &llc_await_state_trans_1_0, + &llc_common_state_trans_n, + &llc_await_state_trans_1, /* Local busy */ + &llc_common_state_trans_n, + &llc_common_state_trans_n, /* Initiate PF Cycle */ + &llc_common_state_trans_11a, /* Timer */ + &llc_common_state_trans_11b, + &llc_common_state_trans_11c, + &llc_common_state_trans_11d, + &llc_await_state_trans_14, + &llc_common_state_trans_n, + &llc_common_state_trans_3, /* Receive frame */ + &llc_common_state_trans_4, + &llc_common_state_trans_5, + &llc_common_state_trans_6, + &llc_common_state_trans_7a, + &llc_common_state_trans_7b, + &llc_common_state_trans_8a, + &llc_common_state_trans_8b, + &llc_common_state_trans_8c, + &llc_common_state_trans_9, + /* &llc_common_state_trans_10, */ + &llc_await_state_trans_2, + &llc_await_state_trans_3a, + &llc_await_state_trans_3b, + &llc_await_state_trans_4, + &llc_await_state_trans_5, + &llc_await_state_trans_6a, + &llc_await_state_trans_6b, + &llc_await_state_trans_7, + &llc_await_state_trans_8a, + &llc_await_state_trans_8b, + &llc_await_state_trans_9a, + &llc_await_state_trans_9b, + &llc_await_state_trans_9c, + &llc_await_state_trans_9d, + &llc_await_state_trans_10a, + &llc_await_state_trans_10b, + &llc_await_state_trans_11, + &llc_await_state_trans_12a, + &llc_await_state_trans_12b, + &llc_await_state_trans_13, + &llc_common_state_trans_n +}; + +/* ------------------ LLC_CONN_STATE_AWAIT_BUSY transitions ---------------- */ +/* State transitions for LLC_CONN_EV_DATA_CONN_REQ event */ +static llc_conn_ev_qfyr_t llc_await_busy_ev_qfyrs_1_0[] = { + llc_conn_ev_qlfy_set_status_refuse, + NULL +}; + +/* just one member, NULL, .bss zeroes it */ +static llc_conn_action_t llc_await_busy_actions_1_0[1]; + +static struct llc_conn_state_trans llc_await_busy_state_trans_1_0 = { + llc_conn_ev_data_req, + LLC_CONN_STATE_AWAIT_BUSY, + llc_await_busy_ev_qfyrs_1_0, + llc_await_busy_actions_1_0 +}; + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */ +static llc_conn_ev_qfyr_t llc_await_busy_ev_qfyrs_1[] = { + llc_conn_ev_qlfy_data_flag_eq_1, + NULL +}; + +static llc_conn_action_t llc_await_busy_actions_1[] = { + llc_conn_ac_send_rej_xxx_x_set_0, + llc_conn_ac_start_rej_timer, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_1 = { + llc_conn_ev_local_busy_cleared, + LLC_CONN_STATE_AWAIT_REJ, + llc_await_busy_ev_qfyrs_1, + llc_await_busy_actions_1 +}; + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */ +static llc_conn_ev_qfyr_t llc_await_busy_ev_qfyrs_2[] = { + llc_conn_ev_qlfy_data_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_await_busy_actions_2[] = { + llc_conn_ac_send_rr_xxx_x_set_0, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_2 = { + llc_conn_ev_local_busy_cleared, + LLC_CONN_STATE_AWAIT, + llc_await_busy_ev_qfyrs_2, + llc_await_busy_actions_2 +}; + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */ +static llc_conn_ev_qfyr_t llc_await_busy_ev_qfyrs_3[] = { + llc_conn_ev_qlfy_data_flag_eq_2, + NULL +}; + +static llc_conn_action_t llc_await_busy_actions_3[] = { + llc_conn_ac_send_rr_xxx_x_set_0, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_3 = { + llc_conn_ev_local_busy_cleared, + LLC_CONN_STATE_AWAIT_REJ, + llc_await_busy_ev_qfyrs_3, + llc_await_busy_actions_3 +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1_UNEXPD_Ns event */ +static llc_conn_action_t llc_await_busy_actions_4[] = { + llc_conn_ac_opt_send_rnr_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_stop_p_timer, + llc_conn_ac_set_data_flag_1, + llc_conn_ac_clear_remote_busy, + llc_conn_ac_resend_i_xxx_x_set_0, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_4 = { + llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns, + LLC_CONN_STATE_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_4 +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */ +static llc_conn_action_t llc_await_busy_actions_5a[] = { + llc_conn_ac_opt_send_rnr_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_data_flag_1, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_5a = { + llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_5a +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns event */ +static llc_conn_action_t llc_await_busy_actions_5b[] = { + llc_conn_ac_opt_send_rnr_xxx_x_set_0, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_data_flag_1, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_5b = { + llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_5b +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns event */ +static llc_conn_action_t llc_await_busy_actions_6[] = { + llc_conn_ac_send_rnr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_data_flag_1, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_6 = { + llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_6 +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1 event */ +static llc_conn_action_t llc_await_busy_actions_7[] = { + llc_conn_ac_opt_send_rnr_xxx_x_set_0, + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_stop_p_timer, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_data_flag_0, + llc_conn_ac_clear_remote_busy, + llc_conn_ac_resend_i_xxx_x_set_0, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_7 = { + llc_conn_ev_rx_i_rsp_fbit_set_1, + LLC_CONN_STATE_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_7 +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_await_busy_actions_8a[] = { + llc_conn_ac_opt_send_rnr_xxx_x_set_0, + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_data_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_8a = { + llc_conn_ev_rx_i_rsp_fbit_set_0, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_8a +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_await_busy_actions_8b[] = { + llc_conn_ac_opt_send_rnr_xxx_x_set_0, + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_data_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_8b = { + llc_conn_ev_rx_i_cmd_pbit_set_0, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_8b +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_await_busy_actions_9[] = { + llc_conn_ac_send_rnr_rsp_f_set_1, + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_data_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_9 = { + llc_conn_ev_rx_i_cmd_pbit_set_1, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_9 +}; + +/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 event */ +static llc_conn_action_t llc_await_busy_actions_10a[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_stop_p_timer, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_10a = { + llc_conn_ev_rx_rr_rsp_fbit_set_1, + LLC_CONN_STATE_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_10a +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_1 event */ +static llc_conn_action_t llc_await_busy_actions_10b[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_stop_p_timer, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_10b = { + llc_conn_ev_rx_rej_rsp_fbit_set_1, + LLC_CONN_STATE_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_10b +}; + +/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_await_busy_actions_11a[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_11a = { + llc_conn_ev_rx_rr_cmd_pbit_set_0, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_11a +}; + +/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_await_busy_actions_11b[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_11b = { + llc_conn_ev_rx_rr_rsp_fbit_set_0, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_11b +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_await_busy_actions_11c[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_11c = { + llc_conn_ev_rx_rej_cmd_pbit_set_0, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_11c +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_await_busy_actions_11d[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_11d = { + llc_conn_ev_rx_rej_rsp_fbit_set_0, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_11d +}; + +/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_await_busy_actions_12a[] = { + llc_conn_ac_send_rnr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_12a = { + llc_conn_ev_rx_rr_cmd_pbit_set_1, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_12a +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_await_busy_actions_12b[] = { + llc_conn_ac_send_rnr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_12b = { + llc_conn_ev_rx_rej_cmd_pbit_set_1, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_12b +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 event */ +static llc_conn_action_t llc_await_busy_actions_13[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_stop_p_timer, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_13 = { + llc_conn_ev_rx_rnr_rsp_fbit_set_1, + LLC_CONN_STATE_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_13 +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_await_busy_actions_14a[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_14a = { + llc_conn_ev_rx_rnr_cmd_pbit_set_0, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_14a +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_await_busy_actions_14b[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_14b = { + llc_conn_ev_rx_rnr_rsp_fbit_set_0, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_14b +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_await_busy_actions_15[] = { + llc_conn_ac_send_rnr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_15 = { + llc_conn_ev_rx_rnr_cmd_pbit_set_1, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_busy_actions_15 +}; + +/* State transitions for LLC_CONN_EV_P_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_await_busy_ev_qfyrs_16[] = { + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_await_busy_actions_16[] = { + llc_conn_ac_send_rnr_cmd_p_set_1, + llc_conn_ac_start_p_timer, + llc_conn_ac_inc_retry_cnt_by_1, + NULL +}; + +static struct llc_conn_state_trans llc_await_busy_state_trans_16 = { + llc_conn_ev_p_tmr_exp, + LLC_CONN_STATE_AWAIT_BUSY, + llc_await_busy_ev_qfyrs_16, + llc_await_busy_actions_16 +}; + +/* + * Array of pointers; + * one to each transition + */ +static struct llc_conn_state_trans *llc_await_busy_state_transitions[] = { + &llc_common_state_trans_1, /* Request */ + &llc_common_state_trans_2, + &llc_await_busy_state_trans_1_0, + &llc_common_state_trans_n, + &llc_await_busy_state_trans_1, /* Local busy */ + &llc_await_busy_state_trans_2, + &llc_await_busy_state_trans_3, + &llc_common_state_trans_n, + &llc_common_state_trans_n, /* Initiate PF cycle */ + &llc_common_state_trans_11a, /* Timer */ + &llc_common_state_trans_11b, + &llc_common_state_trans_11c, + &llc_common_state_trans_11d, + &llc_await_busy_state_trans_16, + &llc_common_state_trans_n, + &llc_await_busy_state_trans_4, /* Receive frame */ + &llc_await_busy_state_trans_5a, + &llc_await_busy_state_trans_5b, + &llc_await_busy_state_trans_6, + &llc_await_busy_state_trans_7, + &llc_await_busy_state_trans_8a, + &llc_await_busy_state_trans_8b, + &llc_await_busy_state_trans_9, + &llc_await_busy_state_trans_10a, + &llc_await_busy_state_trans_10b, + &llc_await_busy_state_trans_11a, + &llc_await_busy_state_trans_11b, + &llc_await_busy_state_trans_11c, + &llc_await_busy_state_trans_11d, + &llc_await_busy_state_trans_12a, + &llc_await_busy_state_trans_12b, + &llc_await_busy_state_trans_13, + &llc_await_busy_state_trans_14a, + &llc_await_busy_state_trans_14b, + &llc_await_busy_state_trans_15, + &llc_common_state_trans_3, + &llc_common_state_trans_4, + &llc_common_state_trans_5, + &llc_common_state_trans_6, + &llc_common_state_trans_7a, + &llc_common_state_trans_7b, + &llc_common_state_trans_8a, + &llc_common_state_trans_8b, + &llc_common_state_trans_8c, + &llc_common_state_trans_9, + /* &llc_common_state_trans_10, */ + &llc_common_state_trans_n +}; + +/* ----------------- LLC_CONN_STATE_AWAIT_REJ transitions --------------- */ +/* State transitions for LLC_CONN_EV_DATA_CONN_REQ event */ +static llc_conn_ev_qfyr_t llc_await_reject_ev_qfyrs_1_0[] = { + llc_conn_ev_qlfy_set_status_refuse, + NULL +}; + +/* just one member, NULL, .bss zeroes it */ +static llc_conn_action_t llc_await_reject_actions_1_0[1]; + +static struct llc_conn_state_trans llc_await_reject_state_trans_1_0 = { + llc_conn_ev_data_req, + LLC_CONN_STATE_AWAIT_REJ, + llc_await_reject_ev_qfyrs_1_0, + llc_await_reject_actions_1_0 +}; + +/* State transitions for LLC_CONN_EV_LOCAL_BUSY_DETECTED event */ +static llc_conn_action_t llc_await_rejct_actions_1[] = { + llc_conn_ac_send_rnr_xxx_x_set_0, + llc_conn_ac_set_data_flag_2, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_1 = { + llc_conn_ev_local_busy_detected, + LLC_CONN_STATE_AWAIT_BUSY, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_1 +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */ +static llc_conn_action_t llc_await_rejct_actions_2a[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_2a = { + llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_2a +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns event */ +static llc_conn_action_t llc_await_rejct_actions_2b[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_2b = { + llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_2b +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns event */ +static llc_conn_action_t llc_await_rejct_actions_3[] = { + llc_conn_ac_send_rr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_3 = { + llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_3 +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1 event */ +static llc_conn_action_t llc_await_rejct_actions_4[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_stop_p_timer, + llc_conn_ac_stop_rej_timer, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_4 = { + llc_conn_ev_rx_i_rsp_fbit_set_1, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_4 +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_await_rejct_actions_5a[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_send_rr_xxx_x_set_0, + llc_conn_ac_stop_rej_timer, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_5a = { + llc_conn_ev_rx_i_rsp_fbit_set_0, + LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_5a +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_await_rejct_actions_5b[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_send_rr_xxx_x_set_0, + llc_conn_ac_stop_rej_timer, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_5b = { + llc_conn_ev_rx_i_cmd_pbit_set_0, LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, llc_await_rejct_actions_5b +}; + +/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_await_rejct_actions_6[] = { + llc_conn_ac_inc_vr_by_1, + llc_conn_ac_data_ind, + llc_conn_ac_send_rr_rsp_f_set_1, + llc_conn_ac_stop_rej_timer, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_6 = { + llc_conn_ev_rx_i_cmd_pbit_set_1, + LLC_CONN_STATE_AWAIT, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_6 +}; + +/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 event */ +static llc_conn_action_t llc_await_rejct_actions_7a[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_stop_p_timer, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_7a = { + llc_conn_ev_rx_rr_rsp_fbit_set_1, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_7a +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_1 event */ +static llc_conn_action_t llc_await_rejct_actions_7b[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_stop_p_timer, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_7b = { + llc_conn_ev_rx_rej_rsp_fbit_set_1, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_7b +}; + +/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1_UNEXPD_Ns event */ +static llc_conn_action_t llc_await_rejct_actions_7c[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_stop_p_timer, + llc_conn_ac_resend_i_xxx_x_set_0, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_7c = { + llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_7c +}; + +/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_await_rejct_actions_8a[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_8a = { + llc_conn_ev_rx_rr_cmd_pbit_set_0, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_8a +}; + +/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_await_rejct_actions_8b[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_8b = { + llc_conn_ev_rx_rr_rsp_fbit_set_0, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_8b +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_await_rejct_actions_8c[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_8c = { + llc_conn_ev_rx_rej_cmd_pbit_set_0, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_8c +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_await_rejct_actions_8d[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_8d = { + llc_conn_ev_rx_rej_rsp_fbit_set_0, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_8d +}; + +/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_await_rejct_actions_9a[] = { + llc_conn_ac_send_rr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_9a = { + llc_conn_ev_rx_rr_cmd_pbit_set_1, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_9a +}; + +/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_await_rejct_actions_9b[] = { + llc_conn_ac_send_rr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_clear_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_9b = { + llc_conn_ev_rx_rej_cmd_pbit_set_1, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_9b +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 event */ +static llc_conn_action_t llc_await_rejct_actions_10[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_stop_p_timer, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_10 = { + llc_conn_ev_rx_rnr_rsp_fbit_set_1, + LLC_CONN_STATE_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_10 +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 event */ +static llc_conn_action_t llc_await_rejct_actions_11a[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_11a = { + llc_conn_ev_rx_rnr_cmd_pbit_set_0, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_11a +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 event */ +static llc_conn_action_t llc_await_rejct_actions_11b[] = { + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_11b = { + llc_conn_ev_rx_rnr_rsp_fbit_set_0, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_11b +}; + +/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 event */ +static llc_conn_action_t llc_await_rejct_actions_12[] = { + llc_conn_ac_send_rr_rsp_f_set_1, + llc_conn_ac_upd_nr_received, + llc_conn_ac_upd_vs, + llc_conn_ac_set_remote_busy, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_12 = { + llc_conn_ev_rx_rnr_cmd_pbit_set_1, + LLC_CONN_STATE_AWAIT_REJ, + LLC_NO_EVENT_QUALIFIERS, + llc_await_rejct_actions_12 +}; + +/* State transitions for LLC_CONN_EV_P_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_await_rejct_ev_qfyrs_13[] = { + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_await_rejct_actions_13[] = { + llc_conn_ac_send_rej_cmd_p_set_1, + llc_conn_ac_stop_p_timer, + llc_conn_ac_inc_retry_cnt_by_1, + NULL +}; + +static struct llc_conn_state_trans llc_await_rejct_state_trans_13 = { + llc_conn_ev_p_tmr_exp, + LLC_CONN_STATE_AWAIT_REJ, + llc_await_rejct_ev_qfyrs_13, + llc_await_rejct_actions_13 +}; + +/* + * Array of pointers; + * one to each transition + */ +static struct llc_conn_state_trans *llc_await_rejct_state_transitions[] = { + &llc_await_reject_state_trans_1_0, + &llc_common_state_trans_1, /* requests */ + &llc_common_state_trans_2, + &llc_common_state_trans_n, + &llc_await_rejct_state_trans_1, /* local busy */ + &llc_common_state_trans_n, + &llc_common_state_trans_n, /* Initiate PF cycle */ + &llc_await_rejct_state_trans_13, /* timers */ + &llc_common_state_trans_11a, + &llc_common_state_trans_11b, + &llc_common_state_trans_11c, + &llc_common_state_trans_11d, + &llc_common_state_trans_n, + &llc_await_rejct_state_trans_2a, /* receive frames */ + &llc_await_rejct_state_trans_2b, + &llc_await_rejct_state_trans_3, + &llc_await_rejct_state_trans_4, + &llc_await_rejct_state_trans_5a, + &llc_await_rejct_state_trans_5b, + &llc_await_rejct_state_trans_6, + &llc_await_rejct_state_trans_7a, + &llc_await_rejct_state_trans_7b, + &llc_await_rejct_state_trans_7c, + &llc_await_rejct_state_trans_8a, + &llc_await_rejct_state_trans_8b, + &llc_await_rejct_state_trans_8c, + &llc_await_rejct_state_trans_8d, + &llc_await_rejct_state_trans_9a, + &llc_await_rejct_state_trans_9b, + &llc_await_rejct_state_trans_10, + &llc_await_rejct_state_trans_11a, + &llc_await_rejct_state_trans_11b, + &llc_await_rejct_state_trans_12, + &llc_common_state_trans_3, + &llc_common_state_trans_4, + &llc_common_state_trans_5, + &llc_common_state_trans_6, + &llc_common_state_trans_7a, + &llc_common_state_trans_7b, + &llc_common_state_trans_8a, + &llc_common_state_trans_8b, + &llc_common_state_trans_8c, + &llc_common_state_trans_9, + /* &llc_common_state_trans_10, */ + &llc_common_state_trans_n +}; + +/* -------------------- LLC_CONN_STATE_D_CONN transitions ------------------ */ +/* State transitions for LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X event, + * cause_flag = 1 */ +static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_1[] = { + llc_conn_ev_qlfy_cause_flag_eq_1, + llc_conn_ev_qlfy_set_status_conflict, + NULL +}; + +static llc_conn_action_t llc_d_conn_actions_1[] = { + llc_conn_ac_send_dm_rsp_f_set_p, + llc_conn_ac_stop_ack_timer, + llc_conn_ac_disc_confirm, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_d_conn_state_trans_1 = { + llc_conn_ev_rx_sabme_cmd_pbit_set_x, + LLC_CONN_STATE_ADM, + llc_d_conn_ev_qfyrs_1, + llc_d_conn_actions_1 +}; + +/* State transitions for LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X event, + * cause_flag = 0 + */ +static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_1_1[] = { + llc_conn_ev_qlfy_cause_flag_eq_0, + llc_conn_ev_qlfy_set_status_conflict, + NULL +}; + +static llc_conn_action_t llc_d_conn_actions_1_1[] = { + llc_conn_ac_send_dm_rsp_f_set_p, + llc_conn_ac_stop_ack_timer, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_d_conn_state_trans_1_1 = { + llc_conn_ev_rx_sabme_cmd_pbit_set_x, + LLC_CONN_STATE_ADM, + llc_d_conn_ev_qfyrs_1_1, + llc_d_conn_actions_1_1 +}; + +/* State transitions for LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X event, + * cause_flag = 1 */ +static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_2[] = { + llc_conn_ev_qlfy_p_flag_eq_f, + llc_conn_ev_qlfy_cause_flag_eq_1, + llc_conn_ev_qlfy_set_status_disc, + NULL +}; + +static llc_conn_action_t llc_d_conn_actions_2[] = { + llc_conn_ac_stop_ack_timer, + llc_conn_ac_disc_confirm, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_d_conn_state_trans_2 = { + llc_conn_ev_rx_ua_rsp_fbit_set_x, + LLC_CONN_STATE_ADM, + llc_d_conn_ev_qfyrs_2, + llc_d_conn_actions_2 +}; + +/* State transitions for LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X event, + * cause_flag = 0 */ +static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_2_1[] = { + llc_conn_ev_qlfy_p_flag_eq_f, + llc_conn_ev_qlfy_cause_flag_eq_0, + llc_conn_ev_qlfy_set_status_disc, + NULL +}; + +static llc_conn_action_t llc_d_conn_actions_2_1[] = { + llc_conn_ac_stop_ack_timer, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_d_conn_state_trans_2_1 = { + llc_conn_ev_rx_ua_rsp_fbit_set_x, + LLC_CONN_STATE_ADM, + llc_d_conn_ev_qfyrs_2_1, + llc_d_conn_actions_2_1 +}; + +/* State transitions for LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X event */ +static llc_conn_action_t llc_d_conn_actions_3[] = { + llc_conn_ac_send_ua_rsp_f_set_p, + NULL +}; + +static struct llc_conn_state_trans llc_d_conn_state_trans_3 = { + llc_conn_ev_rx_disc_cmd_pbit_set_x, + LLC_CONN_STATE_D_CONN, + LLC_NO_EVENT_QUALIFIERS, + llc_d_conn_actions_3 +}; + +/* State transitions for LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X event, + * cause_flag = 1 */ +static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_4[] = { + llc_conn_ev_qlfy_cause_flag_eq_1, + llc_conn_ev_qlfy_set_status_disc, + NULL +}; + +static llc_conn_action_t llc_d_conn_actions_4[] = { + llc_conn_ac_stop_ack_timer, + llc_conn_ac_disc_confirm, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_d_conn_state_trans_4 = { + llc_conn_ev_rx_dm_rsp_fbit_set_x, + LLC_CONN_STATE_ADM, + llc_d_conn_ev_qfyrs_4, + llc_d_conn_actions_4 +}; + +/* State transitions for LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X event, + * cause_flag = 0 */ +static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_4_1[] = { + llc_conn_ev_qlfy_cause_flag_eq_0, + llc_conn_ev_qlfy_set_status_disc, + NULL +}; + +static llc_conn_action_t llc_d_conn_actions_4_1[] = { + llc_conn_ac_stop_ack_timer, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_d_conn_state_trans_4_1 = { + llc_conn_ev_rx_dm_rsp_fbit_set_x, + LLC_CONN_STATE_ADM, + llc_d_conn_ev_qfyrs_4_1, + llc_d_conn_actions_4_1 +}; + +/* + * State transition for + * LLC_CONN_EV_DATA_CONN_REQ event + */ +static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_5[] = { + llc_conn_ev_qlfy_set_status_refuse, + NULL +}; + +/* just one member, NULL, .bss zeroes it */ +static llc_conn_action_t llc_d_conn_actions_5[1]; + +static struct llc_conn_state_trans llc_d_conn_state_trans_5 = { + llc_conn_ev_data_req, LLC_CONN_STATE_D_CONN, + llc_d_conn_ev_qfyrs_5, llc_d_conn_actions_5 +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_6[] = { + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_d_conn_actions_6[] = { + llc_conn_ac_send_disc_cmd_p_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_inc_retry_cnt_by_1, + NULL +}; + +static struct llc_conn_state_trans llc_d_conn_state_trans_6 = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_D_CONN, + llc_d_conn_ev_qfyrs_6, + llc_d_conn_actions_6 +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event, cause_flag = 1 */ +static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_7[] = { + llc_conn_ev_qlfy_retry_cnt_gte_n2, + llc_conn_ev_qlfy_cause_flag_eq_1, + llc_conn_ev_qlfy_set_status_failed, + NULL +}; + +static llc_conn_action_t llc_d_conn_actions_7[] = { + llc_conn_ac_disc_confirm, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_d_conn_state_trans_7 = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_ADM, + llc_d_conn_ev_qfyrs_7, + llc_d_conn_actions_7 +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event, cause_flag = 0 */ +static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_8[] = { + llc_conn_ev_qlfy_retry_cnt_gte_n2, + llc_conn_ev_qlfy_cause_flag_eq_0, + llc_conn_ev_qlfy_set_status_failed, + NULL +}; + +static llc_conn_action_t llc_d_conn_actions_8[] = { + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_d_conn_state_trans_8 = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_ADM, + llc_d_conn_ev_qfyrs_8, + llc_d_conn_actions_8 +}; + +/* + * Array of pointers; + * one to each transition + */ +static struct llc_conn_state_trans *llc_d_conn_state_transitions[] = { + &llc_d_conn_state_trans_5, /* Request */ + &llc_common_state_trans_n, + &llc_common_state_trans_n, /* Local busy */ + &llc_common_state_trans_n, /* Initiate PF cycle */ + &llc_d_conn_state_trans_6, /* Timer */ + &llc_d_conn_state_trans_7, + &llc_d_conn_state_trans_8, + &llc_common_state_trans_n, + &llc_d_conn_state_trans_1, /* Receive frame */ + &llc_d_conn_state_trans_1_1, + &llc_d_conn_state_trans_2, + &llc_d_conn_state_trans_2_1, + &llc_d_conn_state_trans_3, + &llc_d_conn_state_trans_4, + &llc_d_conn_state_trans_4_1, + &llc_common_state_trans_n +}; + +/* -------------------- LLC_CONN_STATE_RESET transitions ------------------- */ +/* State transitions for LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X event */ +static llc_conn_action_t llc_rst_actions_1[] = { + llc_conn_ac_set_vs_0, + llc_conn_ac_set_vr_0, + llc_conn_ac_set_s_flag_1, + llc_conn_ac_send_ua_rsp_f_set_p, + NULL +}; + +static struct llc_conn_state_trans llc_rst_state_trans_1 = { + llc_conn_ev_rx_sabme_cmd_pbit_set_x, + LLC_CONN_STATE_RESET, + LLC_NO_EVENT_QUALIFIERS, + llc_rst_actions_1 +}; + +/* State transitions for LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X event, + * cause_flag = 1 */ +static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_2[] = { + llc_conn_ev_qlfy_p_flag_eq_f, + llc_conn_ev_qlfy_cause_flag_eq_1, + llc_conn_ev_qlfy_set_status_conn, + NULL +}; + +static llc_conn_action_t llc_rst_actions_2[] = { + llc_conn_ac_stop_ack_timer, + llc_conn_ac_set_vs_0, + llc_conn_ac_set_vr_0, + llc_conn_ac_upd_p_flag, + llc_conn_ac_rst_confirm, + llc_conn_ac_set_remote_busy_0, + llc_conn_reset, + NULL +}; + +static struct llc_conn_state_trans llc_rst_state_trans_2 = { + llc_conn_ev_rx_ua_rsp_fbit_set_x, + LLC_CONN_STATE_NORMAL, + llc_rst_ev_qfyrs_2, + llc_rst_actions_2 +}; + +/* State transitions for LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X event, + * cause_flag = 0 */ +static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_2_1[] = { + llc_conn_ev_qlfy_p_flag_eq_f, + llc_conn_ev_qlfy_cause_flag_eq_0, + llc_conn_ev_qlfy_set_status_rst_done, + NULL +}; + +static llc_conn_action_t llc_rst_actions_2_1[] = { + llc_conn_ac_stop_ack_timer, + llc_conn_ac_set_vs_0, + llc_conn_ac_set_vr_0, + llc_conn_ac_upd_p_flag, + llc_conn_ac_rst_confirm, + llc_conn_ac_set_remote_busy_0, + llc_conn_reset, + NULL +}; + +static struct llc_conn_state_trans llc_rst_state_trans_2_1 = { + llc_conn_ev_rx_ua_rsp_fbit_set_x, + LLC_CONN_STATE_NORMAL, + llc_rst_ev_qfyrs_2_1, + llc_rst_actions_2_1 +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_3[] = { + llc_conn_ev_qlfy_s_flag_eq_1, + llc_conn_ev_qlfy_set_status_rst_done, + NULL +}; + +static llc_conn_action_t llc_rst_actions_3[] = { + llc_conn_ac_set_p_flag_0, + llc_conn_ac_set_remote_busy_0, + NULL +}; + +static struct llc_conn_state_trans llc_rst_state_trans_3 = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_NORMAL, + llc_rst_ev_qfyrs_3, + llc_rst_actions_3 +}; + +/* State transitions for LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X event, + * cause_flag = 1 */ +static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_4[] = { + llc_conn_ev_qlfy_cause_flag_eq_1, + llc_conn_ev_qlfy_set_status_disc, + NULL +}; +static llc_conn_action_t llc_rst_actions_4[] = { + llc_conn_ac_send_dm_rsp_f_set_p, + llc_conn_ac_disc_ind, + llc_conn_ac_stop_ack_timer, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_rst_state_trans_4 = { + llc_conn_ev_rx_disc_cmd_pbit_set_x, + LLC_CONN_STATE_ADM, + llc_rst_ev_qfyrs_4, + llc_rst_actions_4 +}; + +/* State transitions for LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X event, + * cause_flag = 0 */ +static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_4_1[] = { + llc_conn_ev_qlfy_cause_flag_eq_0, + llc_conn_ev_qlfy_set_status_refuse, + NULL +}; + +static llc_conn_action_t llc_rst_actions_4_1[] = { + llc_conn_ac_send_dm_rsp_f_set_p, + llc_conn_ac_stop_ack_timer, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_rst_state_trans_4_1 = { + llc_conn_ev_rx_disc_cmd_pbit_set_x, + LLC_CONN_STATE_ADM, + llc_rst_ev_qfyrs_4_1, + llc_rst_actions_4_1 +}; + +/* State transitions for LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X event, + * cause_flag = 1 */ +static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_5[] = { + llc_conn_ev_qlfy_cause_flag_eq_1, + llc_conn_ev_qlfy_set_status_disc, + NULL +}; + +static llc_conn_action_t llc_rst_actions_5[] = { + llc_conn_ac_disc_ind, + llc_conn_ac_stop_ack_timer, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_rst_state_trans_5 = { + llc_conn_ev_rx_dm_rsp_fbit_set_x, + LLC_CONN_STATE_ADM, + llc_rst_ev_qfyrs_5, + llc_rst_actions_5 +}; + +/* State transitions for LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X event, + * cause_flag = 0 */ +static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_5_1[] = { + llc_conn_ev_qlfy_cause_flag_eq_0, + llc_conn_ev_qlfy_set_status_refuse, + NULL +}; + +static llc_conn_action_t llc_rst_actions_5_1[] = { + llc_conn_ac_stop_ack_timer, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_rst_state_trans_5_1 = { + llc_conn_ev_rx_dm_rsp_fbit_set_x, + LLC_CONN_STATE_ADM, + llc_rst_ev_qfyrs_5_1, + llc_rst_actions_5_1 +}; + +/* State transitions for DATA_CONN_REQ event */ +static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_6[] = { + llc_conn_ev_qlfy_set_status_refuse, + NULL +}; + +/* just one member, NULL, .bss zeroes it */ +static llc_conn_action_t llc_rst_actions_6[1]; + +static struct llc_conn_state_trans llc_rst_state_trans_6 = { + llc_conn_ev_data_req, + LLC_CONN_STATE_RESET, + llc_rst_ev_qfyrs_6, + llc_rst_actions_6 +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_7[] = { + llc_conn_ev_qlfy_retry_cnt_lt_n2, + llc_conn_ev_qlfy_s_flag_eq_0, + NULL +}; + +static llc_conn_action_t llc_rst_actions_7[] = { + llc_conn_ac_send_sabme_cmd_p_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_inc_retry_cnt_by_1, + NULL +}; + +static struct llc_conn_state_trans llc_rst_state_trans_7 = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_RESET, + llc_rst_ev_qfyrs_7, + llc_rst_actions_7 +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_8[] = { + llc_conn_ev_qlfy_retry_cnt_gte_n2, + llc_conn_ev_qlfy_s_flag_eq_0, + llc_conn_ev_qlfy_cause_flag_eq_1, + llc_conn_ev_qlfy_set_status_failed, + NULL +}; +static llc_conn_action_t llc_rst_actions_8[] = { + llc_conn_ac_disc_ind, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_rst_state_trans_8 = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_ADM, + llc_rst_ev_qfyrs_8, + llc_rst_actions_8 +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_8_1[] = { + llc_conn_ev_qlfy_retry_cnt_gte_n2, + llc_conn_ev_qlfy_s_flag_eq_0, + llc_conn_ev_qlfy_cause_flag_eq_0, + llc_conn_ev_qlfy_set_status_failed, + NULL +}; +static llc_conn_action_t llc_rst_actions_8_1[] = { + llc_conn_ac_disc_ind, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_rst_state_trans_8_1 = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_ADM, + llc_rst_ev_qfyrs_8_1, + llc_rst_actions_8_1 +}; + +/* + * Array of pointers; + * one to each transition + */ +static struct llc_conn_state_trans *llc_rst_state_transitions[] = { + &llc_rst_state_trans_6, /* Request */ + &llc_common_state_trans_n, + &llc_common_state_trans_n, /* Local busy */ + &llc_common_state_trans_n, /* Initiate PF cycle */ + &llc_rst_state_trans_3, /* Timer */ + &llc_rst_state_trans_7, + &llc_rst_state_trans_8, + &llc_rst_state_trans_8_1, + &llc_common_state_trans_n, + &llc_rst_state_trans_1, /* Receive frame */ + &llc_rst_state_trans_2, + &llc_rst_state_trans_2_1, + &llc_rst_state_trans_4, + &llc_rst_state_trans_4_1, + &llc_rst_state_trans_5, + &llc_rst_state_trans_5_1, + &llc_common_state_trans_n +}; + +/* -------------------- LLC_CONN_STATE_ERROR transitions ------------------- */ +/* State transitions for LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X event */ +static llc_conn_action_t llc_error_actions_1[] = { + llc_conn_ac_set_vs_0, + llc_conn_ac_set_vr_0, + llc_conn_ac_send_ua_rsp_f_set_p, + llc_conn_ac_rst_ind, + llc_conn_ac_set_p_flag_0, + llc_conn_ac_set_remote_busy_0, + llc_conn_ac_stop_ack_timer, + llc_conn_reset, + NULL +}; + +static struct llc_conn_state_trans llc_error_state_trans_1 = { + llc_conn_ev_rx_sabme_cmd_pbit_set_x, + LLC_CONN_STATE_NORMAL, + LLC_NO_EVENT_QUALIFIERS, + llc_error_actions_1 +}; + +/* State transitions for LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X event */ +static llc_conn_action_t llc_error_actions_2[] = { + llc_conn_ac_send_ua_rsp_f_set_p, + llc_conn_ac_disc_ind, + llc_conn_ac_stop_ack_timer, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_error_state_trans_2 = { + llc_conn_ev_rx_disc_cmd_pbit_set_x, + LLC_CONN_STATE_ADM, + LLC_NO_EVENT_QUALIFIERS, + llc_error_actions_2 +}; + +/* State transitions for LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X event */ +static llc_conn_action_t llc_error_actions_3[] = { + llc_conn_ac_disc_ind, + llc_conn_ac_stop_ack_timer, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_error_state_trans_3 = { + llc_conn_ev_rx_dm_rsp_fbit_set_x, + LLC_CONN_STATE_ADM, + LLC_NO_EVENT_QUALIFIERS, + llc_error_actions_3 +}; + +/* State transitions for LLC_CONN_EV_RX_FRMR_RSP_Fbit_SET_X event */ +static llc_conn_action_t llc_error_actions_4[] = { + llc_conn_ac_send_sabme_cmd_p_set_x, + llc_conn_ac_start_ack_timer, + llc_conn_ac_set_retry_cnt_0, + llc_conn_ac_set_cause_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_error_state_trans_4 = { + llc_conn_ev_rx_frmr_rsp_fbit_set_x, + LLC_CONN_STATE_RESET, + LLC_NO_EVENT_QUALIFIERS, + llc_error_actions_4 +}; + +/* State transitions for LLC_CONN_EV_RX_XXX_CMD_Pbit_SET_X event */ +static llc_conn_action_t llc_error_actions_5[] = { + llc_conn_ac_resend_frmr_rsp_f_set_p, + NULL +}; + +static struct llc_conn_state_trans llc_error_state_trans_5 = { + llc_conn_ev_rx_xxx_cmd_pbit_set_x, + LLC_CONN_STATE_ERROR, + LLC_NO_EVENT_QUALIFIERS, + llc_error_actions_5 +}; + +/* State transitions for LLC_CONN_EV_RX_XXX_RSP_Fbit_SET_X event */ +static struct llc_conn_state_trans llc_error_state_trans_6 = { + llc_conn_ev_rx_xxx_rsp_fbit_set_x, + LLC_CONN_STATE_ERROR, + LLC_NO_EVENT_QUALIFIERS, + LLC_NO_TRANSITION_ACTIONS +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_error_ev_qfyrs_7[] = { + llc_conn_ev_qlfy_retry_cnt_lt_n2, + NULL +}; + +static llc_conn_action_t llc_error_actions_7[] = { + llc_conn_ac_resend_frmr_rsp_f_set_0, + llc_conn_ac_start_ack_timer, + llc_conn_ac_inc_retry_cnt_by_1, + NULL +}; + +static struct llc_conn_state_trans llc_error_state_trans_7 = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_ERROR, + llc_error_ev_qfyrs_7, + llc_error_actions_7 +}; + +/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */ +static llc_conn_ev_qfyr_t llc_error_ev_qfyrs_8[] = { + llc_conn_ev_qlfy_retry_cnt_gte_n2, + NULL +}; + +static llc_conn_action_t llc_error_actions_8[] = { + llc_conn_ac_send_sabme_cmd_p_set_x, + llc_conn_ac_set_s_flag_0, + llc_conn_ac_start_ack_timer, + llc_conn_ac_set_retry_cnt_0, + llc_conn_ac_set_cause_flag_0, + NULL +}; + +static struct llc_conn_state_trans llc_error_state_trans_8 = { + llc_conn_ev_ack_tmr_exp, + LLC_CONN_STATE_RESET, + llc_error_ev_qfyrs_8, + llc_error_actions_8 +}; + +/* State transitions for LLC_CONN_EV_DATA_CONN_REQ event */ +static llc_conn_ev_qfyr_t llc_error_ev_qfyrs_9[] = { + llc_conn_ev_qlfy_set_status_refuse, + NULL +}; + +/* just one member, NULL, .bss zeroes it */ +static llc_conn_action_t llc_error_actions_9[1]; + +static struct llc_conn_state_trans llc_error_state_trans_9 = { + llc_conn_ev_data_req, + LLC_CONN_STATE_ERROR, + llc_error_ev_qfyrs_9, + llc_error_actions_9 +}; + +/* + * Array of pointers; + * one to each transition + */ +static struct llc_conn_state_trans *llc_error_state_transitions[] = { + &llc_error_state_trans_9, /* Request */ + &llc_common_state_trans_n, + &llc_common_state_trans_n, /* Local busy */ + &llc_common_state_trans_n, /* Initiate PF cycle */ + &llc_error_state_trans_7, /* Timer */ + &llc_error_state_trans_8, + &llc_common_state_trans_n, + &llc_error_state_trans_1, /* Receive frame */ + &llc_error_state_trans_2, + &llc_error_state_trans_3, + &llc_error_state_trans_4, + &llc_error_state_trans_5, + &llc_error_state_trans_6, + &llc_common_state_trans_n +}; + +/* ------------------- LLC_CONN_STATE_TEMP transitions ----------------- */ +/* State transitions for LLC_CONN_EV_DISC_REQ event */ +static llc_conn_action_t llc_temp_actions_1[] = { + llc_conn_ac_stop_all_timers, + llc_conn_ac_send_disc_cmd_p_set_x, + llc_conn_disc, + NULL +}; + +static struct llc_conn_state_trans llc_temp_state_trans_1 = { + llc_conn_ev_disc_req, + LLC_CONN_STATE_ADM, + LLC_NO_EVENT_QUALIFIERS, + llc_temp_actions_1 +}; + +/* + * Array of pointers; + * one to each transition + */ +static struct llc_conn_state_trans *llc_temp_state_transitions[] = { + &llc_temp_state_trans_1, /* requests */ + &llc_common_state_trans_n, + &llc_common_state_trans_n, /* local busy */ + &llc_common_state_trans_n, /* init_pf_cycle */ + &llc_common_state_trans_n, /* timer */ + &llc_common_state_trans_n /* recieve */ +}; + +/* Connection State Transition Table */ +struct llc_conn_state llc_conn_state_table[] = { + { LLC_CONN_STATE_ADM, llc_adm_state_transitions }, + { LLC_CONN_STATE_SETUP, llc_setup_state_transitions }, + { LLC_CONN_STATE_NORMAL, llc_normal_state_transitions }, + { LLC_CONN_STATE_BUSY, llc_busy_state_transitions }, + { LLC_CONN_STATE_REJ, llc_reject_state_transitions }, + { LLC_CONN_STATE_AWAIT, llc_await_state_transitions }, + { LLC_CONN_STATE_AWAIT_BUSY, llc_await_busy_state_transitions }, + { LLC_CONN_STATE_AWAIT_REJ, llc_await_rejct_state_transitions }, + { LLC_CONN_STATE_D_CONN, llc_d_conn_state_transitions }, + { LLC_CONN_STATE_RESET, llc_rst_state_transitions }, + { LLC_CONN_STATE_ERROR, llc_error_state_transitions }, + { LLC_CONN_STATE_TEMP, llc_temp_state_transitions } +}; Index: kernel-acme/net/llc/llc_conn.c diff -u /dev/null kernel-acme/net/llc/llc_conn.c:1.1.6.3 --- /dev/null Sat Dec 22 02:21:13 2001 +++ kernel-acme/net/llc/llc_conn.c Fri Dec 7 15:49:02 2001 @@ -0,0 +1,520 @@ +/* + * llc_conn.c - Driver routines for connection component. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int llc_find_offset(int state, int ev_type); +static void llc_conn_send_pdus(struct sock *sk); +static int llc_conn_service(struct sock *sk, struct llc_conn_state_ev *ev); +static int llc_exec_conn_trans_actions(struct sock *sk, + struct llc_conn_state_trans *trans, + struct llc_conn_state_ev *ev); +static struct llc_conn_state_trans * + llc_qualify_conn_ev(struct sock *sk, struct llc_conn_state_ev *ev); + +/* Offset table on connection states transition diagram */ +static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV]; + +/** + * llc_conn_alloc_event: allocates an event + * @sk: socket that event is associated + * + * Returns pointer to allocated connection on success, %NULL on failure. + */ +struct llc_conn_state_ev *llc_conn_alloc_ev(struct sock *sk) +{ + struct llc_conn_state_ev *ev = NULL; + + /* verify connection is valid, active and open */ + if (LLC_SK(sk)->state != LLC_CONN_OUT_OF_SVC) { + /* get event structure to build a station event */ + ev = kmalloc(sizeof(*ev), GFP_ATOMIC); + if (ev) + memset(ev, 0, sizeof(*ev)); + } + return ev; +} + +/** + * llc_conn_send_event - sends event to connection state machine + * @sk: connection + * @ev: occurred event + * + * Sends an event to connection state machine. after processing event + * (executing it's actions and changing state), upper layer will be + * indicated or confirmed, if needed. Returns 0 for success, 1 for + * failure. The socket lock has to be held before calling this function. + */ +int llc_conn_send_ev(struct sock *sk, struct llc_conn_state_ev *ev) +{ + /* sending event to state machine */ + int rc = llc_conn_service(sk, ev); + struct llc_opt *llc = LLC_SK(sk); + u8 flag = ev->flag; + struct llc_prim_if_block *ind_prim = ev->ind_prim; + struct llc_prim_if_block *cfm_prim = ev->cfm_prim; + + llc_conn_free_ev(ev); +#ifdef THIS_BREAKS_DISCONNECT_NOTIFICATION_BADLY + /* check if the connection was freed by the state machine by + * means of llc_conn_disc */ + if (rc == 2) { + printk(KERN_INFO __FUNCTION__ ": rc == 2\n"); + rc = -ECONNABORTED; + goto out; + } +#endif /* THIS_BREAKS_DISCONNECT_NOTIFICATION_BADLY */ + if (!flag) /* indicate or confirm not required */ + goto out; + rc = 0; + if (ind_prim) /* indication required */ + llc->sap->ind(ind_prim); + if (!cfm_prim) /* confirmation not required */ + goto out; + /* data confirm has preconditions */ + if (cfm_prim->prim != LLC_DATA_PRIM) { + llc->sap->conf(cfm_prim); + goto out; + } + if (!llc_data_accept_state(llc->state)) { + /* In this state, we can send I pdu */ + /* FIXME: check if we don't need to see if sk->lock.users != 0 + * is needed here */ + rc = llc->sap->conf(cfm_prim); + if (rc) /* confirmation didn't accept by upper layer */ + llc->failed_data_req = 1; + } else + llc->failed_data_req = 1; +out: return rc; +} + +void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb) +{ + llc_sock_assert(sk); + /* queue PDU to send to MAC layer */ + skb_queue_tail(&sk->write_queue, skb); + llc_conn_send_pdus(sk); +} + +/** + * llc_conn_rtn_pdu - sends received data pdu to upper layer + * @sk: Active connection + * @skb: Received data frame + * @ev: Occurred event + * + * Sends received data pdu to upper layer (by using indicate function). + * Prepares service parameters (prim and prim_data). calling indication + * function will be done in llc_conn_send_ev. + */ +void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb, + struct llc_conn_state_ev *ev) +{ + struct llc_prim_if_block *prim = &llc_ind_prim; + union llc_u_prim_data *prim_data = llc_ind_prim.data; + + prim_data->data.sk = sk; + prim_data->data.pri = 0; + prim_data->data.skb = skb; + prim_data->data.link = LLC_SK(sk)->link; + prim->data = prim_data; + prim->prim = LLC_DATA_PRIM; + prim->sap = LLC_SK(sk)->sap; + ev->flag = 1; + /* saving prepd prim in event for future use in llc_conn_send_ev */ + ev->ind_prim = prim; +} + +/** + * llc_conn_resend_i_pdu_as_cmd - resend all all unacknowledged I PDUs + * @sk: active connection + * @nr: NR + * @first_p_bit: p_bit value of first pdu + * + * Resend all unacknowledged I PDUs, starting with the NR; send first as + * command PDU with P bit equal first_p_bit; if more than one send + * subsequent as command PDUs with P bit equal zero (0). + */ +void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit) +{ + struct sk_buff *skb; + llc_pdu_sn_t *pdu; + u16 nbr_unack_pdus; + u8 howmany_resend = 0; + + llc_conn_remove_acked_pdus(sk, nr, &nbr_unack_pdus); + if (!nbr_unack_pdus) + goto out; + /* process unack PDUs only if unack queue is not empty; remove + * appropriate PDUs, fix them up, and put them on mac_pdu_q. */ + while ((skb = skb_dequeue(&LLC_SK(sk)->pdu_unack_q)) != NULL) { + pdu = (llc_pdu_sn_t *)skb->nh.raw; + llc_pdu_set_cmd_rsp(skb, LLC_PDU_CMD); + llc_pdu_set_pf_bit(skb, first_p_bit); + skb_queue_tail(&sk->write_queue, skb); + first_p_bit = 0; + LLC_SK(sk)->vS = LLC_I_GET_NS(pdu); + howmany_resend++; + } + if (howmany_resend > 0) + LLC_SK(sk)->vS = (LLC_SK(sk)->vS + 1) % LLC_2_SEQ_NBR_MODULO; + /* any PDUs to re-send are queued up; start sending to MAC */ + llc_conn_send_pdus(sk); +out:; +} + +/** + * llc_conn_resend_i_pdu_as_rsp - Resend all unacknowledged I PDUs + * @sk: active connection. + * @nr: NR + * @first_f_bit: f_bit value of first pdu. + * + * Resend all unacknowledged I PDUs, starting with the NR; send first as + * response PDU with F bit equal first_f_bit; if more than one send + * subsequent as response PDUs with F bit equal zero (0). + */ +void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit) +{ + struct sk_buff *skb; + llc_pdu_sn_t *pdu; + u16 nbr_unack_pdus; + u8 howmany_resend = 0; + + llc_conn_remove_acked_pdus(sk, nr, &nbr_unack_pdus); + if (!nbr_unack_pdus) + goto out; + /* process unack PDUs only if unack queue is not empty; remove + * appropriate PDUs, fix them up, and put them on mac_pdu_q */ + while ((skb = skb_dequeue(&LLC_SK(sk)->pdu_unack_q)) != NULL) { + pdu = (llc_pdu_sn_t *)skb->nh.raw; + llc_pdu_set_cmd_rsp(skb, LLC_PDU_RSP); + llc_pdu_set_pf_bit(skb, first_f_bit); + skb_queue_tail(&sk->write_queue, skb); + first_f_bit = 0; + LLC_SK(sk)->vS = LLC_I_GET_NS(pdu); + howmany_resend++; + } + if (howmany_resend > 0) + LLC_SK(sk)->vS = (LLC_SK(sk)->vS + 1) % LLC_2_SEQ_NBR_MODULO; + /* any PDUs to re-send are queued up; start sending to MAC */ + llc_conn_send_pdus(sk); +out:; +} + +/** + * llc_conn_remove_acked_pdus - Removes acknowledged pdus from tx queue + * @sk: active connection + * nr: NR + * how_many_unacked: size of pdu_unack_q after removing acked pdus + * + * Removes acknowledged pdus from transmit queue (pdu_unack_q). Returns + * the number of pdus that removed from queue. + */ +int llc_conn_remove_acked_pdus(struct sock *sk, u8 nr, u16 *how_many_unacked) +{ + int pdu_pos, i; + struct sk_buff *skb; + llc_pdu_sn_t *pdu; + int nbr_acked = 0; + int q_len = skb_queue_len(&LLC_SK(sk)->pdu_unack_q); + + if (!q_len) + goto out; + skb = skb_peek(&LLC_SK(sk)->pdu_unack_q); + pdu = (llc_pdu_sn_t *)skb->nh.raw; + + /* finding position of last acked pdu in queue */ + pdu_pos = ((int)LLC_2_SEQ_NBR_MODULO + (int)nr - + (int)LLC_I_GET_NS(pdu)) % LLC_2_SEQ_NBR_MODULO; + + for (i = 0; i < pdu_pos && i < q_len; i++) { + skb = skb_dequeue(&LLC_SK(sk)->pdu_unack_q); + if (skb) + kfree_skb(skb); + nbr_acked++; + } +out: *how_many_unacked = skb_queue_len(&LLC_SK(sk)->pdu_unack_q); + return nbr_acked; +} + +/** + * llc_conn_send_pdus - Sends queued PDUs + * @sk: active connection + * + * Sends queued pdus to MAC layer for transmition. + */ +static void llc_conn_send_pdus(struct sock *sk) +{ + struct sk_buff *skb; + + while ((skb = skb_dequeue(&sk->write_queue)) != NULL) { + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw; + + if (!LLC_PDU_TYPE_IS_I(pdu) && + !(skb->dev->flags & IFF_LOOPBACK)) + skb_queue_tail(&LLC_SK(sk)->pdu_unack_q, skb); + mac_send_pdu(skb); + if (LLC_PDU_TYPE_IS_I(pdu) || + (skb->dev && skb->dev->flags & IFF_LOOPBACK)) + kfree_skb(skb); + } +} + +/** + * llc_conn_free_ev - free event + * @ev: event to free + * + * Free allocated event. + */ +void llc_conn_free_ev(struct llc_conn_state_ev *ev) +{ + if (ev->type == LLC_CONN_EV_TYPE_PDU) { + /* free the frame that binded to this event */ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; + + if (LLC_PDU_TYPE_IS_I(pdu) || !ev->flag || !ev->ind_prim) + kfree_skb(ev->data.pdu.skb); + } + /* free event structure to free list of the same */ + kfree(ev); +} + +/** + * llc_conn_service - finds transition and changes state of connection + * @sk: connection + * @ev: happened event + * + * This function finds transition that matches with happened event, then + * executes related actions and finally changes state of connection. + * Returns 0 for success, 1 for failure. + */ +static int llc_conn_service(struct sock *sk, struct llc_conn_state_ev *ev) +{ + int rc = 1; + struct llc_conn_state_trans *trans; + + if (LLC_SK(sk)->state > NBR_CONN_STATES) + goto out; + rc = 0; + trans = llc_qualify_conn_ev(sk, ev); + if (trans) { + rc = llc_exec_conn_trans_actions(sk, trans, ev); + if (!rc && trans->next_state != NO_STATE_CHANGE) + LLC_SK(sk)->state = trans->next_state; + } +out: return rc; +} + +/** + * llc_qualify_conn_ev - finds transition for event + * @sk: connection + * @ev: happened event + * + * This function finds transition that matches with happened event. + * Returns pointer to found transition on success, %NULL otherwise. + */ +static struct llc_conn_state_trans * + llc_qualify_conn_ev(struct sock *sk, struct llc_conn_state_ev *ev) +{ + struct llc_conn_state_trans **next_trans; + llc_conn_ev_qfyr_t *next_qualifier; + struct llc_conn_state *curr_state = + &llc_conn_state_table[LLC_SK(sk)->state - 1]; + + /* search thru events for this state until list exhausted or until + no more */ + for (next_trans = curr_state->transitions + + llc_find_offset(LLC_SK(sk)->state - 1, ev->type); + (*next_trans)->ev; next_trans++) { + if (!((*next_trans)->ev)(sk, ev)) { + /* got POSSIBLE event match; the event may require + * qualification based on the values of a number of + * state flags; if all qualifications are met (i.e., + * if all qualifying functions return success, or 0, + * then this is THE event we're looking for */ + for (next_qualifier = (*next_trans)->ev_qualifiers; + next_qualifier && *next_qualifier && + !(*next_qualifier)(sk, ev); next_qualifier++) + /* nothing */; + if (!next_qualifier || !*next_qualifier) + /* all qualifiers executed successfully; this is + * our transition; return it so we can perform + * the associated actions & change the state */ + return *next_trans; + } + } + return NULL; +} + +/** + * llc_exec_conn_trans_actions - executes related actions + * @sk: connection + * @trans: transition that it's actions must be performed + * @ev: happened event + * + * Executes actions that is related to happened event. Returns 0 for + * success, 1 to indicate failure of at least one action or 2 if the + * connection was freed (llc_conn_disc was called) + */ +static int llc_exec_conn_trans_actions(struct sock *sk, + struct llc_conn_state_trans *trans, + struct llc_conn_state_ev *ev) +{ + int rc = 0; + llc_conn_action_t *next_action; + + for (next_action = trans->ev_actions; + next_action && *next_action; next_action++) { + int rc2 = (*next_action)(sk, ev); + + if (rc2 == 2) { + rc = rc2; + break; + } else if (rc2) + rc = 1; + } + return rc; +} + +/** + * llc_find_sock - Finds connection in sap for the remote/local sap/mac + * @sap: SAP + * @daddr: address of remote LLC (MAC + SAP) + * @laddr: address of local LLC (MAC + SAP) + * + * Search connection list of the SAP and finds connection using the remote + * mac, remote sap, local mac, and local sap. Returns pointer for + * connection found, %NULL otherwise. + */ +struct sock *llc_find_sock(struct llc_sap *sap, struct llc_addr *daddr, + struct llc_addr *laddr) +{ + struct sock *rc = NULL; + struct list_head *entry; + + spin_lock_bh(&sap->sk_list.lock); + if (list_empty(&sap->sk_list.list)) + goto out; + list_for_each(entry, &sap->sk_list.list) { + struct llc_opt *llc = list_entry(entry, struct llc_opt, node); + + if (llc->laddr.lsap == laddr->lsap && + llc->daddr.lsap == daddr->lsap && + !memcmp(llc->laddr.mac, laddr->mac, ETH_ALEN) && + !memcmp(llc->daddr.mac, daddr->mac, ETH_ALEN)) { + rc = llc->sk; + break; + } + } + if (rc) + sock_hold(rc); +out: spin_unlock_bh(&sap->sk_list.lock); + return rc; +} + +/** + * llc_data_accept_state - designates if in this state data can be sent. + * @state: state of connection. + * + * Returns 0 if data can be sent, 1 otherwise. + */ +u8 llc_data_accept_state(u8 state) +{ + if (state != LLC_CONN_STATE_NORMAL && state != LLC_CONN_STATE_BUSY && + state != LLC_CONN_STATE_REJ) + return 1; /* data_conn_refuse */ + return 0; +} + +/** + * find_next_offset - finds offset for next category of transitions + * @state: state table. + * @offset: start offset. + * + * Finds offset of next category of transitions in transition table. + * Returns the start index of next category. + */ +u16 find_next_offset(struct llc_conn_state *state, u16 offset) +{ + u16 cnt = 0; + struct llc_conn_state_trans **next_trans; + + for (next_trans = state->transitions + offset; + (*next_trans)->ev; next_trans++) + ++cnt; + return cnt; +} + +/** + * llc_build_offset_table - builds offset table of connection + * + * Fills offset table of connection state transition table + * (llc_offset_table). + */ +void __init llc_build_offset_table(void) +{ + struct llc_conn_state *curr_state; + int state, ev_type, next_offset; + + memset(llc_offset_table, 0, sizeof(llc_offset_table)); + for (state = 0; state < NBR_CONN_STATES; state++) { + curr_state = &llc_conn_state_table[state]; + next_offset = 0; + for (ev_type = 0; ev_type < NBR_CONN_EV; ev_type++) { + llc_offset_table[state][ev_type] = next_offset; + next_offset += find_next_offset(curr_state, + next_offset) + 1; + } + } +} + +/** + * llc_find_offset - finds start offset of category of transitions + * @state: state of connection + * @ev_type: type of happened event + * + * Finds start offset of desired category of transitions. Returns the + * desired start offset. + */ +static int llc_find_offset(int state, int ev_type) +{ + int rc = 0; + /* at this stage, llc_offset_table[..][2] is not important. it is for + * init_pf_cycle and I don't know what is it. */ + switch (ev_type) { + case LLC_CONN_EV_TYPE_PRIM: + rc = llc_offset_table[state][0]; break; + case LLC_CONN_EV_TYPE_PDU: + rc = llc_offset_table[state][4]; break; + case LLC_CONN_EV_TYPE_SIMPLE: + rc = llc_offset_table[state][1]; break; + case LLC_CONN_EV_TYPE_P_TMR: + case LLC_CONN_EV_TYPE_ACK_TMR: + case LLC_CONN_EV_TYPE_REJ_TMR: + case LLC_CONN_EV_TYPE_BUSY_TMR: + rc = llc_offset_table[state][3]; break; + } + return rc; +} Index: kernel-acme/net/llc/llc_evnt.c diff -u /dev/null kernel-acme/net/llc/llc_evnt.c:1.1.6.2 --- /dev/null Sat Dec 22 02:21:13 2001 +++ kernel-acme/net/llc/llc_evnt.c Fri Dec 7 15:49:02 2001 @@ -0,0 +1,112 @@ +/* + * llc_evnt.c - LLC station component event match functions + * Description : + * Functions in this module are implementation of station component events. + * Details of events can be found in IEEE-802.2 standard document. + * All functions have one station and one event as input argument. All of + * them return 0 On success and 1 otherwise. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include + +int llc_stat_ev_enable_with_dup_addr_check(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + return ev->type == LLC_STATION_EV_TYPE_SIMPLE && + ev->data.a.ev == + LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK ? 0 : 1; +} + +int llc_stat_ev_enable_without_dup_addr_check(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + return ev->type == LLC_STATION_EV_TYPE_SIMPLE && + ev->data.a.ev == + LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK ? 0 : 1; +} + +int llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + return ev->type == LLC_STATION_EV_TYPE_ACK_TMR && + station->retry_count < station->maximum_retry ? 0 : 1; +} + +int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + return ev->type == LLC_STATION_EV_TYPE_ACK_TMR && + station->retry_count == station->maximum_retry ? 0 : 1; +} + +int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return ev->type == LLC_STATION_EV_TYPE_PDU && + !LLC_PDU_IS_CMD(pdu) && /* command PDU */ + !LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ + LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID && + !pdu->dsap ? 0 : 1; /* NULL DSAP value */ +} + +int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return ev->type == LLC_STATION_EV_TYPE_PDU && + !LLC_PDU_IS_RSP(pdu) && /* response PDU */ + !LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ + LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID && + !pdu->dsap && /* NULL DSAP value */ + !station->xid_r_count ? 0 : 1; +} + +int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return ev->type == LLC_STATION_EV_TYPE_PDU && + !LLC_PDU_IS_RSP(pdu) && /* response PDU */ + !LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ + LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID && + !pdu->dsap && /* NULL DSAP value */ + station->xid_r_count == 1 ? 0 : 1; +} + +int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return ev->type == LLC_STATION_EV_TYPE_PDU && + !LLC_PDU_IS_CMD(pdu) && /* command PDU */ + !LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ + LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST && + !pdu->dsap ? 0 : 1; /* NULL DSAP */ +} + +int llc_stat_ev_disable_req(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + return ev->type == LLC_STATION_EV_TYPE_PRIM && + ev->data.prim.prim == LLC_DISABLE_PRIM && + ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; +} Index: kernel-acme/net/llc/llc_if.c diff -u /dev/null kernel-acme/net/llc/llc_if.c:1.1.6.5 --- /dev/null Sat Dec 22 02:21:13 2001 +++ kernel-acme/net/llc/llc_if.c Tue Dec 11 00:26:46 2001 @@ -0,0 +1,514 @@ +/* + * llc_if.c - Defines LLC interface to upper layer + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int llc_sap_req(struct llc_prim_if_block *prim); +static int llc_unitdata_req_handler(struct llc_prim_if_block *prim); +static int llc_test_req_handler(struct llc_prim_if_block *prim); +static int llc_xid_req_handler(struct llc_prim_if_block *prim); +static int llc_data_req_handler(struct llc_prim_if_block *prim); +static int llc_conn_req_handler(struct llc_prim_if_block *prim); +static int llc_disc_req_handler(struct llc_prim_if_block *prim); +static int llc_rst_req_handler(struct llc_prim_if_block *prim); +static int llc_flowcontrol_req_handler(struct llc_prim_if_block *prim); +static int llc_sap_resp(struct llc_prim_if_block *prim); +static int llc_conn_rsp_handler(struct llc_prim_if_block *prim); +static int llc_rst_rsp_handler(struct llc_prim_if_block *prim); +static int llc_no_rsp_handler(struct llc_prim_if_block *prim); + +extern void llc_register_sap(unsigned char sap, + int (*rcvfunc)(struct sk_buff *skb, + struct net_device *dev, + struct packet_type *pt)); +extern void llc_unregister_sap(unsigned char sap); + +/* table of request handler functions */ +static llc_prim_call_t llc_req_prim[LLC_NBR_PRIMITIVES] = { + llc_unitdata_req_handler, /* order of functions must not change */ + llc_conn_req_handler, + llc_data_req_handler, + llc_disc_req_handler, + llc_rst_req_handler, + llc_flowcontrol_req_handler, + NULL, + llc_xid_req_handler, + llc_test_req_handler, +}; + +/* table of response handler functions */ +static llc_prim_call_t llc_resp_prim[LLC_NBR_PRIMITIVES] = { + llc_no_rsp_handler, /* order of functions must not change */ + llc_conn_rsp_handler, + llc_no_rsp_handler, + llc_no_rsp_handler, + llc_rst_rsp_handler, + llc_no_rsp_handler, +}; + +/** + * llc_sap_open - open interface to the upper layers. + * @nw_indicate: pointer to indicate function of upper layer. + * @nw_confirm: pointer to confirm function of upper layer. + * @lsap: SAP number. + * @sap: pointer to allocated SAP (output argument). + * + * Interface function to upper layer. each one who wants to get a SAP + * (for example NetBEUI) should call this function. Returns 0 for + * success, 1 for failure. + */ +struct llc_sap *llc_sap_open(llc_prim_call_t nw_indicate, + llc_prim_call_t nw_confirm, u8 lsap) +{ + /* verify this SAP is not already open; if so, return error */ + struct llc_sap *sap; + + MOD_INC_USE_COUNT; + sap = llc_sap_find(lsap); + if (sap) { /* SAP already exists */ + sap = NULL; + goto err; + } + /* sap requested does not yet exist */ + sap = llc_sap_alloc(); + if (!sap) + goto err; + /* allocated a SAP; initialize it and clear out its memory pool */ + sap->laddr.lsap = lsap; + sap->req = llc_sap_req; + sap->resp = llc_sap_resp; + sap->ind = nw_indicate; + sap->conf = nw_confirm; + sap->parent_station = llc_station_get(); + /* initialized SAP; add it to list of SAPs this station manages */ + llc_sap_save(sap); + llc_register_sap(lsap, mac_indicate); +out: return sap; +err: MOD_DEC_USE_COUNT; + goto out; +} + +/** + * llc_sap_close - close interface for upper layers. + * @sap: SAP to be closed. + * + * Close interface function to upper layer. each one who wants to + * close an open SAP (for example NetBEUI) should call this function. + */ +void llc_sap_close(struct llc_sap *sap) +{ + llc_unregister_sap(sap->laddr.lsap); + llc_free_sap(sap); + MOD_DEC_USE_COUNT; +} + +/** + * llc_sap_req - Request interface for upper layers + * @prim: pointer to structure that contains service parameters. + * + * Request interface function to upper layer. each one who wants to + * request a service from LLC, must call this function. details of + * requested service is defined in input argument(prim). Returns 0 for + * success, 1 otherwise. + */ +static int llc_sap_req(struct llc_prim_if_block *prim) +{ + int rc = 1; + + if (prim->prim > 8 || prim->prim == 6) { + printk(KERN_ERR __FUNCTION__ ": invalid primitive %d\n", + prim->prim); + goto out; + } + /* receive REQUEST primitive from network layer; call the appropriate + * primitive handler which then packages it up as an event and sends it + * to the SAP or CONNECTION event handler */ + if (prim->prim < LLC_NBR_PRIMITIVES) + /* valid primitive; call the function to handle it */ + rc = llc_req_prim[prim->prim](prim); +out: return rc; +} + +/** + * llc_unitdata_req_handler - unitdata request interface for upper layers + * @prim: pointer to structure that contains service parameters + * + * Upper layers calls this function when upper layer wants to send data + * using connection-less mode communication (UI pdu). Returns 0 for + * success, 1 otherwise. + */ +static int llc_unitdata_req_handler(struct llc_prim_if_block *prim) +{ + int rc = 1; + struct llc_sap_state_ev *ev; + /* accept data frame from network layer to be sent using connection- + * less mode communication; timeout/retries handled by network layer; + * package primitive as an event and send to SAP event handler */ + struct llc_sap *sap = llc_sap_find(prim->data->udata.saddr.lsap); + + if (!sap) + goto out; + ev = llc_sap_alloc_ev(sap); + if (!ev) + goto out; + ev->type = LLC_SAP_EV_TYPE_PRIM; + ev->data.prim.prim = LLC_DATAUNIT_PRIM; + ev->data.prim.type = LLC_PRIM_TYPE_REQ; + ev->data.prim.data = prim; + rc = 0; + llc_sap_send_ev(sap, ev); +out: return rc; +} + +/** + * llc_test_req_handler - TEST interface for upper layers. + * @prim: pointer to structure that contains service parameters. + * + * This function is called when upper layer wants to send a TEST pdu. + * Returns 0 for success, 1 otherwise. + */ +static int llc_test_req_handler(struct llc_prim_if_block *prim) +{ + int rc = 1; + struct llc_sap_state_ev *ev; + /* package primitive as an event and send to SAP event handler */ + struct llc_sap *sap = llc_sap_find(prim->data->udata.saddr.lsap); + if (!sap) + goto out; + ev = llc_sap_alloc_ev(sap); + if (!ev) + goto out; + ev->type = LLC_SAP_EV_TYPE_PRIM; + ev->data.prim.prim = LLC_TEST_PRIM; + ev->data.prim.type = LLC_PRIM_TYPE_REQ; + ev->data.prim.data = prim; + rc = 0; + llc_sap_send_ev(sap, ev); +out: return rc; +} + +/** + * llc_xid_req_handler - XID interface for upper layers + * @prim: pointer to structure that contains service parameters. + * + * This function is called when upper layer wants to send a XID pdu. + * Returns 0 for success, 1 otherwise. + */ +static int llc_xid_req_handler(struct llc_prim_if_block *prim) +{ + int rc = 1; + struct llc_sap_state_ev *ev; + /* package primitive as an event and send to SAP event handler */ + struct llc_sap *sap = llc_sap_find(prim->data->udata.saddr.lsap); + + if (!sap) + goto out; + ev = llc_sap_alloc_ev(sap); + if (!ev) + goto out; + ev->type = LLC_SAP_EV_TYPE_PRIM; + ev->data.prim.prim = LLC_XID_PRIM; + ev->data.prim.type = LLC_PRIM_TYPE_REQ; + ev->data.prim.data = prim; + rc = 0; + llc_sap_send_ev(sap, ev); +out: return rc; +} + +/** + * llc_data_req_handler - Connection data sending for upper layers. + * @prim: pointer to structure that contains service parameters + * + * This function is called when upper layer wants to send data using + * connection oriented communication mode. during sending data, connection + * will be locked and received frames and expired timers will be queued. + * Returns 0 for success, -ECONNABORTED when the connection already + * closed. and -EBUSY when sending data is not permitted in this state or + * LLC has send an I pdu with p bit set to 1 and is waiting for it's + * response. + */ +static int llc_data_req_handler(struct llc_prim_if_block *prim) +{ + struct llc_conn_state_ev *ev; + int rc = -ECONNABORTED; + /* accept data frame from network layer to be sent using connection + * mode communication; timeout/retries handled by this layer; + * package primitive as an event and send to connection event handler */ + struct sock *sk = prim->data->data.sk; + struct llc_opt *llc = LLC_SK(sk); + + lock_sock(sk); + if (llc->state == LLC_CONN_STATE_ADM) + goto out; + rc = -EBUSY; + if (llc_data_accept_state(llc->state)) { /* data_conn_refuse */ + llc->failed_data_req = 1; + goto out; + } + if (llc->p_flag) { + llc->failed_data_req = 1; + goto out; + } + rc = -ENOMEM; + ev = llc_conn_alloc_ev(sk); + if (ev) { + ev->type = LLC_CONN_EV_TYPE_PRIM; + ev->data.prim.prim = LLC_DATA_PRIM; + ev->data.prim.type = LLC_PRIM_TYPE_REQ; + ev->data.prim.data = prim; + prim->data->data.skb->dev = llc->dev; + rc = llc_conn_send_ev(sk, ev); + } +out: release_sock(sk); + return rc; +} + +/** + * confirm_impossible - Informs upper layer about failed connection + * @prim: pointer to structure that contains confirmation data. + * + * Informs upper layer about failing in connection establishment. This + * function is called by llc_conn_req_handler. + */ +static void confirm_impossible(struct llc_prim_if_block *prim) +{ + prim->data->conn.status = LLC_STATUS_IMPOSSIBLE; + prim->sap->conf(prim); +} + +/** + * llc_conn_req_handler - Called by upper layer to establish a conn + * @prim: pointer to structure that contains service parameters. + * + * Upper layer calls this to establish an LLC connection with a remote + * machine. this function packages a proper event and sends it connection + * component state machine. Success or failure of connection + * establishment will inform to upper layer via calling it's confirm + * function and passing proper information. + */ +static int llc_conn_req_handler(struct llc_prim_if_block *prim) +{ + int rc = -EBUSY; + struct llc_opt *llc; + struct llc_sap *sap = prim->sap; + struct llc_conn_state_ev *ev; + struct net_device *ddev = mac_dev_peer(prim->data->conn.dev, + prim->data->conn.dev->type, + prim->data->conn.daddr.mac), + *sdev = (ddev->flags & IFF_LOOPBACK) ? + ddev : prim->data->conn.dev; + struct llc_addr laddr, daddr; + /* network layer supplies addressing required to establish connection; + * package as an event and send it to the connection event handler */ + struct sock *sk; + + memcpy(laddr.mac, sdev->dev_addr, sizeof(laddr.mac)); + laddr.lsap = prim->data->conn.saddr.lsap; + memcpy(daddr.mac, ddev->dev_addr, sizeof(daddr.mac)); + daddr.lsap = prim->data->conn.daddr.lsap; + sk = llc_find_sock(sap, &daddr, &laddr); + if (sk) { + confirm_impossible(prim); + goto out_put; + } + rc = -ENOMEM; + if (prim->data->conn.sk) { + sk = prim->data->conn.sk; + if (llc_sock_init(sk)) + goto out; + } else { + sk = llc_sock_alloc(); + if (!sk) { + confirm_impossible(prim); + goto out; + } + prim->data->conn.sk = sk; + } + sock_hold(sk); + lock_sock(sk); + /* assign new connection to it's SAP */ + llc_sap_assign_sock(sap, sk); + llc = LLC_SK(sk); + memcpy(&llc->daddr, &daddr, sizeof(llc->daddr)); + memcpy(&llc->laddr, &laddr, sizeof(llc->laddr)); + llc->dev = ddev; + llc->link = prim->data->conn.link; + llc->handler = prim->data->conn.handler; + ev = llc_conn_alloc_ev(sk); + if (ev) { + ev->type = LLC_CONN_EV_TYPE_PRIM; + ev->data.prim.prim = LLC_CONN_PRIM; + ev->data.prim.type = LLC_PRIM_TYPE_REQ; + ev->data.prim.data = prim; + rc = llc_conn_send_ev(sk, ev); + } + if (rc) { + llc_sap_unassign_sock(sap, sk); + llc_sock_free(sk); + confirm_impossible(prim); + } + release_sock(sk); +out_put: + sock_put(sk); +out: return rc; +} + +/** + * llc_disc_req_handler - Called by upper layer to close a connection + * @prim: pointer to structure that contains service parameters. + * + * Upper layer calls this when it wants to close an established LLC + * connection with a remote machine. this function packages a proper event + * and sends it to connection component state machine. Returns 0 for + * success, 1 otherwise. + */ +static int llc_disc_req_handler(struct llc_prim_if_block *prim) +{ + u16 rc = 1; + struct llc_conn_state_ev *ev; + struct sock* sk = prim->data->disc.sk; + + sock_hold(sk); + lock_sock(sk); + if (LLC_SK(sk)->state == LLC_CONN_STATE_ADM || + LLC_SK(sk)->state == LLC_CONN_OUT_OF_SVC) + goto out; + /* postpone unassigning the connection from its SAP and returning the + * connection until all ACTIONs have been completely executed */ + ev = llc_conn_alloc_ev(sk); + if (!ev) + goto out; + ev->type = LLC_CONN_EV_TYPE_PRIM; + ev->data.prim.prim = LLC_DISC_PRIM; + ev->data.prim.type = LLC_PRIM_TYPE_REQ; + ev->data.prim.data = prim; + rc = llc_conn_send_ev(sk, ev); +out: release_sock(sk); + sock_put(sk); + return rc; +} + +/** + * llc_rst_req_handler - Resets an established LLC connection + * @prim: pointer to structure that contains service parameters. + * + * Called when upper layer wants to reset an established LLC connection + * with a remote machine. this function packages a proper event and sends + * it to connection component state machine. Returns 0 for success, 1 + * otherwise. + */ +static int llc_rst_req_handler(struct llc_prim_if_block *prim) +{ + int rc = 1; + struct sock *sk = prim->data->res.sk; + struct llc_conn_state_ev *ev; + + lock_sock(sk); + ev = llc_conn_alloc_ev(sk); + if (ev) { + ev->type = LLC_CONN_EV_TYPE_PRIM; + ev->data.prim.prim = LLC_RESET_PRIM; + ev->data.prim.type = LLC_PRIM_TYPE_REQ; + ev->data.prim.data = prim; + rc = llc_conn_send_ev(sk, ev); + } + release_sock(sk); + return rc; +} + +/* We don't support flow control. The original code from procom has + * some bits, but for now I'm cleaning this */ +static int llc_flowcontrol_req_handler(struct llc_prim_if_block *prim) +{ + return 1; +} + +/** + * llc_sap_resp - Sends response to peer + * @prim: pointer to structure that contains service parameters + * + * This function is a interface function to upper layer. each one who + * wants to response to an indicate can call this function via calling + * sap_resp with proper service parameters. Returns 0 for success, 1 + * otherwise. + */ +static int llc_sap_resp(struct llc_prim_if_block *prim) +{ + u16 rc = 1; + /* network layer RESPONSE primitive received; package primitive + * as an event and send it to the connection event handler */ + if (prim->prim < LLC_NBR_PRIMITIVES) + /* valid primitive; call the function to handle it */ + rc = llc_resp_prim[prim->prim](prim); + return rc; +} + +/** + * llc_conn_rsp_handler - Response to connect indication + * @prim: pointer to structure that contains response info. + * + * Response to connect indication. + */ +static int llc_conn_rsp_handler(struct llc_prim_if_block *prim) +{ + struct sock *sk = prim->data->conn.sk; + + LLC_SK(sk)->link = prim->data->conn.link; + return 0; +} + +/** + * llc_rst_rsp_handler - Response to RESET indication + * @prim: pointer to structure that contains response info + * + * Returns 0 for success, 1 otherwise + */ +static int llc_rst_rsp_handler(struct llc_prim_if_block *prim) +{ + int rc = 1; + /* network layer supplies connection handle; map it to a connection; + * package as event and send it to connection event handler */ + struct sock *sk = prim->data->res.sk; + struct llc_conn_state_ev *ev = llc_conn_alloc_ev(sk); + + if (ev) { + ev->type = LLC_CONN_EV_TYPE_PRIM; + ev->data.prim.prim = LLC_RESET_PRIM; + ev->data.prim.type = LLC_PRIM_TYPE_RESP; + ev->data.prim.data = prim; + rc = llc_conn_send_ev(sk, ev); + } + return rc; +} + +static int llc_no_rsp_handler(struct llc_prim_if_block *prim) +{ + return 0; +} + +EXPORT_SYMBOL(llc_sap_open); +EXPORT_SYMBOL(llc_sap_close); Index: kernel-acme/net/llc/llc_mac.c diff -u /dev/null kernel-acme/net/llc/llc_mac.c:1.1.6.7 --- /dev/null Sat Dec 22 02:21:13 2001 +++ kernel-acme/net/llc/llc_mac.c Tue Dec 11 00:26:46 2001 @@ -0,0 +1,311 @@ +/* + * llc_mac.c - Manages interface between LLC and MAC + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_TR +extern void tr_source_route(struct sk_buff *skb, struct trh_hdr *trh, + struct net_device *dev); +#endif +/* function prototypes */ +static void fix_up_incoming_skb(struct sk_buff *skb); + +/** + * mac_send_pdu - Sends PDU to specific device. + * @skb: pdu which must be sent + * + * If module is not initialized then returns failure, else figures out + * where to direct this PDU. Sends PDU to specific device, at this point a + * device must has been assigned to the PDU; If not, can't transmit the + * PDU. PDU sent to MAC layer, is free to re-send at a later time. Returns + * 0 on success, 1 for failure. + */ +int mac_send_pdu(struct sk_buff *skb) +{ + struct sk_buff *skb2; + int pri = GFP_ATOMIC, rc = -1; + + if (!skb->dev) { + printk(KERN_ERR __FUNCTION__ ": skb->dev == NULL!"); + goto out; + } + if (skb->sk) + pri = (int)skb->sk->priority; + skb2 = skb_clone(skb, pri); + if (!skb2) + goto out; + rc = 0; + dev_queue_xmit(skb2); +out: return rc; +} + +/** + * mac_indicate - 802.2 entry point from net lower layers + * @skb: received pdu + * @dev: device that receive pdu + * @pt: packet type + * + * When the system receives a 802.2 frame this function is called. It + * checks SAP and connection of received pdu and passes frame to + * llc_pdu_router for sending to proper state machine. If frame is + * related to a busy connection (a connection is sending data now), + * function queues this frame in connection's backlog. + */ +int mac_indicate(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt) +{ + struct llc_sap *sap; + llc_pdu_sn_t *pdu; + u8 dest; + + /* When the interface is in promisc. mode, drop all the crap that it + receives, do not try to analyse it. */ + if (skb->pkt_type == PACKET_OTHERHOST) { + printk(KERN_INFO __FUNCTION__ ": PACKET_OTHERHOST\n"); + goto drop; + } + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + goto out; + fix_up_incoming_skb(skb); + pdu = (llc_pdu_sn_t *)skb->nh.raw; + if (!pdu->dsap) { /* NULL DSAP, refer to station */ + llc_pdu_router(NULL, NULL, skb, 0); + goto out; + } + sap = llc_sap_find(pdu->dsap); + if (!sap) /* unknown SAP */ + goto drop; + llc_decode_pdu_type(skb, &dest); + if (dest == LLC_DEST_SAP) /* type 1 services */ + llc_pdu_router(sap, NULL, skb, LLC_TYPE_1); + else if (dest == LLC_DEST_CONN) { + struct llc_addr saddr, daddr; + struct sock *sk; + + llc_pdu_decode_sa(skb, saddr.mac); + llc_pdu_decode_ssap(skb, &saddr.lsap); + llc_pdu_decode_da(skb, daddr.mac); + llc_pdu_decode_dsap(skb, &daddr.lsap); + + sk = llc_find_sock(sap, &saddr, &daddr); + if (!sk) { /* didn't find an active connection; allocate a + connection to use; associate it with this SAP */ + sk = llc_sock_alloc(); + if (!sk) + goto drop; + memcpy(&LLC_SK(sk)->daddr, &saddr, sizeof(saddr)); + llc_sap_assign_sock(sap, sk); + sock_hold(sk); + } + bh_lock_sock(sk); + if (!sk->lock.users) { + /* FIXME: Check this on SMP as it is now calling + * llc_pdu_router _with_ the lock held. + * Old comment: + * With the current code one can't call + * llc_pdu_router with the socket lock held, cause + * it'll route the pdu to the upper layers and it can + * reenter llc and in llc_req_prim will try to grab + * the same lock, maybe we should use spin_trylock_bh + * in the llc_req_prim (llc_data_req_handler, etc) and + * add the request to the backlog, well see... */ + llc_pdu_router(LLC_SK(sk)->sap, sk, skb, LLC_TYPE_2); + bh_unlock_sock(sk); + } else { + skb->cb[0] = LLC_PACKET; + sk_add_backlog(sk, skb); + bh_unlock_sock(sk); + } + sock_put(sk); + } else /* unknown or not supported pdu */ + goto drop; +out: return 0; +drop: kfree_skb(skb); + goto out; +} + +/** + * fix_up_incoming_skb - initializes skb pointers + * @skb: This argument points to incoming skb + * + * Initializes internal skb pointer to start of network layer by deriving + * length of LLC header; finds length of LLC control field in LLC header + * by looking at the two lowest-order bits of the first control field + * byte; field is either 3 or 4 bytes long. + */ +static void fix_up_incoming_skb(struct sk_buff *skb) +{ + u8 llc_len = 2; + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->data; + + if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U) + llc_len = 1; + llc_len += 2; + skb_pull(skb, llc_len); + if (skb->protocol == htons(ETH_P_802_2)) { + u16 pdulen = ((struct ethhdr *)skb->mac.raw)->h_proto, + data_size = ntohs(pdulen) - llc_len; + + skb_trim(skb, data_size); + } +} + +/** + * llc_pdu_router - routes received pdus to the upper layers + * @sap: current sap component structure. + * @sk: current connection structure. + * @frame: received frame. + * @type: type of received frame, that is LLC_TYPE_1 or LLC_TYPE_2 + * + * Queues received PDUs from LLC_MAC PDU receive queue until queue is + * empty; examines LLC header to determine the destination of PDU, if DSAP + * is NULL then data unit destined for station else frame destined for SAP + * or connection; finds a matching open SAP, if one, forwards the packet + * to it; if no matching SAP, drops the packet. Returns 0 or the return of + * llc_conn_send_ev (that may well result in the connection being + * destroyed) + */ +int llc_pdu_router(struct llc_sap *sap, struct sock* sk, + struct sk_buff *skb, u8 type) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw; + int rc = 0; + + if (!pdu->dsap) { + struct llc_station *station = llc_station_get(); + struct llc_station_state_ev *stat_ev = + llc_station_alloc_ev(station); + if (stat_ev) { + stat_ev->type = LLC_STATION_EV_TYPE_PDU; + stat_ev->data.pdu.skb = skb; + stat_ev->data.pdu.reason = 0; + llc_station_send_ev(station, stat_ev); + } + } else if (type == LLC_TYPE_1) { + struct llc_sap_state_ev *sap_ev = llc_sap_alloc_ev(sap); + + if (sap_ev) { + sap_ev->type = LLC_SAP_EV_TYPE_PDU; + sap_ev->data.pdu.skb = skb; + sap_ev->data.pdu.reason = 0; + llc_sap_send_ev(sap, sap_ev); + } + } else if (type == LLC_TYPE_2) { + struct llc_conn_state_ev *conn_ev = llc_conn_alloc_ev(sk); + struct llc_opt *llc = LLC_SK(sk); + + if (!llc->dev) + llc->dev = skb->dev; + if (conn_ev) { + conn_ev->type = LLC_CONN_EV_TYPE_PDU; + conn_ev->data.pdu.skb = skb; + conn_ev->data.pdu.reason = 0; + rc = llc_conn_send_ev(sk, conn_ev); + } + } + return rc; +} + +/** + * lan_hdrs_init - fills MAC header fields + * @skb: Address of the frame to initialize its MAC header + * @sa: The MAC source address + * @da: The MAC destination address + * + * Fills MAC header fields, depending on MAC type. Returns 0, If MAC type + * is a valid type and initialization completes correctly 1, otherwise. + */ +u16 lan_hdrs_init(struct sk_buff *skb, u8 *sa, u8 *da) +{ + u8 *saddr; + u8 *daddr; + u16 rc = 0; + + switch (skb->dev->type) { +#ifdef CONFIG_TR + case ARPHRD_IEEE802: { + struct trh_hdr *trh = (struct trh_hdr *) + skb_push(skb, sizeof(*trh)); + struct net_device *dev = skb->dev; + + trh->ac = AC; + trh->fc = LLC_FRAME; + if (sa) + memcpy(trh->saddr, sa, dev->addr_len); + else + memset(trh->saddr, 0, dev->addr_len); + if (da) { + memcpy(trh->daddr, da, dev->addr_len); + tr_source_route(skb, trh, dev); + } + skb->mac.raw = skb->data; + break; + } +#endif + case ARPHRD_ETHER: + case ARPHRD_LOOPBACK: { + unsigned short len = skb->len; + + skb->mac.raw = skb_push(skb, sizeof(struct ethhdr)); + memset(skb->mac.raw, 0, sizeof(struct ethhdr)); + ((struct ethhdr *)skb->mac.raw)->h_proto = htons(len); + daddr = ((struct ethhdr *)skb->mac.raw)->h_dest; + saddr = ((struct ethhdr *)skb->mac.raw)->h_source; + memcpy(daddr, da, ETH_ALEN); + memcpy(saddr, sa, ETH_ALEN); + break; + } + default: + printk(KERN_WARNING "Unknown DEVICE type : %d\n", + skb->dev->type); + rc = 1; + } + return rc; +} + +/** + * mac_dev_peer - search the appropriate dev to send packets to peer + * @current_dev - Current device suggested by upper layer + * @type - hardware type + * @mac - mac address + * + * Check if the we should use loopback to send packets, i.e., if the + * dmac belongs to one of the local interfaces, returning the pointer + * to the loopback &net_device struct or the current_dev if it is not + * local. + */ +struct net_device *mac_dev_peer(struct net_device *current_dev, int type, + u8 *mac) +{ + struct net_device *dev; + + rtnl_lock(); + dev = dev_getbyhwaddr(type, mac); + if (dev) + dev = __dev_get_by_name("lo"); + rtnl_unlock(); + return dev ? : current_dev; +} Index: kernel-acme/net/llc/llc_main.c diff -u /dev/null kernel-acme/net/llc/llc_main.c:1.1.6.6 --- /dev/null Sat Dec 22 02:21:13 2001 +++ kernel-acme/net/llc/llc_main.c Fri Dec 21 02:12:16 2001 @@ -0,0 +1,626 @@ +/* + * llc_main.c - This module contains main functions to manage station, saps + * and connections of the LLC. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* static function prototypes */ +static void llc_station_service_events(struct llc_station *station); +static void llc_station_free_ev(struct llc_station *station, + struct llc_station_state_ev *ev); +static void llc_station_send_pdus(struct llc_station *station); +static u16 llc_station_next_state(struct llc_station *station, + struct llc_station_state_ev *ev); +static u16 llc_exec_station_trans_actions(struct llc_station *station, + struct llc_station_state_trans *trans, + struct llc_station_state_ev *ev); +static struct llc_station_state_trans * + llc_find_station_trans(struct llc_station *station, + struct llc_station_state_ev *ev); +static int llc_rtn_all_conns(struct llc_sap *sap); + +extern void llc_register_sap(unsigned char sap, + int (*rcvfunc)(struct sk_buff *skb, + struct net_device *dev, + struct packet_type *pt)); +extern void llc_unregister_sap(unsigned char sap); + +static struct llc_station llc_main_station; /* only one of its kind */ +struct llc_prim_if_block llc_ind_prim, llc_cfm_prim; +static union llc_u_prim_data llc_ind_data_prim, llc_cfm_data_prim; + +/** + * llc_sap_alloc - allocates and initializes sap. + * + * Allocates and initializes sap. + */ +struct llc_sap *llc_sap_alloc(void) +{ + struct llc_sap *sap = kmalloc(sizeof(*sap), GFP_ATOMIC); + + if (sap) { + memset(sap, 0, sizeof(*sap)); + sap->state = LLC_SAP_STATE_ACTIVE; + memcpy(sap->laddr.mac, llc_main_station.mac_sa, ETH_ALEN); + spin_lock_init(&sap->sk_list.lock); + INIT_LIST_HEAD(&sap->sk_list.list); + skb_queue_head_init(&sap->mac_pdu_q); + } + return sap; +} + +/** + * llc_free_sap - frees a sap + * @sap: Address of the sap + * + * Frees all associated connections (if any), removes this sap from + * the list of saps in te station and them frees the memory for this sap. + */ +void llc_free_sap(struct llc_sap *sap) +{ + struct llc_station *station = sap->parent_station; + + llc_rtn_all_conns(sap); + spin_lock_bh(&station->sap_list.lock); + list_del(&sap->node); + spin_unlock_bh(&station->sap_list.lock); + kfree(sap); +} + +/** + * llc_sap_save - add sap to station list + * @sap: Address of the sap + * + * Adds a sap to the LLC's station sap list. + */ +void llc_sap_save(struct llc_sap *sap) +{ + spin_lock_bh(&llc_main_station.sap_list.lock); + list_add_tail(&sap->node, &llc_main_station.sap_list.list); + spin_unlock_bh(&llc_main_station.sap_list.lock); +} + +/** + * llc_sap_find - searchs a SAP in station + * @sap_value: sap to be found + * + * Searchs for a sap in the sap list of the LLC's station upon the sap ID. + * Returns the sap or %NULL if not found. + */ +struct llc_sap *llc_sap_find(u8 sap_value) +{ + struct llc_sap* sap = NULL; + struct list_head *entry; + + spin_lock_bh(&llc_main_station.sap_list.lock); + list_for_each(entry, &llc_main_station.sap_list.list) { + sap = list_entry(entry, struct llc_sap, node); + if (sap->laddr.lsap == sap_value) + break; + } + if (entry == &llc_main_station.sap_list.list) /* not found */ + sap = NULL; + spin_unlock_bh(&llc_main_station.sap_list.lock); + return sap; +} + +/** + * llc_backlog_rcv - Processes rx frames and expired timers. + * @sk: LLC sock (p8022 connection) + * @skb: queued rx frame or event + * + * This function processes frames that has received and timers that has + * expired during sending an I pdu (refer to data_req_handler). frames + * queue by mac_indicate function (llc_mac.c) and timers queue by timer + * callback functions(llc_c_ac.c). + */ +static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb) +{ + int rc = 0; + struct llc_opt *llc = LLC_SK(sk); + + if (skb->cb[0] == LLC_PACKET) { + if (llc->state > 1) /* not closed */ + rc = llc_pdu_router(llc->sap, sk, skb, LLC_TYPE_2); + else + kfree_skb(skb); + } else if (skb->cb[0] == LLC_EVENT) { + struct llc_conn_state_ev *ev = + (struct llc_conn_state_ev *)skb->data; + /* timer expiration event */ + if (llc->state > 1) /* not closed */ + rc = llc_conn_send_ev(sk, ev); + else + llc_conn_free_ev(ev); + kfree_skb(skb); + } + return rc; +} + +/** + * llc_sock_init - Initialize a socket with default llc values. + * @sk: socket to intiailize. + */ +int llc_sock_init(struct sock* sk) +{ + struct llc_opt *llc = kmalloc(sizeof(*llc), GFP_ATOMIC); + int rc = -ENOMEM; + + if (!llc) + goto out; + memset(llc, 0, sizeof(*llc)); + rc = 0; + llc->sk = sk; + llc->state = LLC_CONN_STATE_ADM; + llc->inc_cntr = llc->dec_cntr = 2; + llc->dec_step = llc->connect_step = 1; + llc->ack_timer.expire = LLC_ACK_TIME; + llc->pf_cycle_timer.expire = LLC_P_TIME; + llc->rej_sent_timer.expire = LLC_REJ_TIME; + llc->busy_state_timer.expire = LLC_BUSY_TIME; + llc->n2 = 2; /* max retransmit */ + llc->k = 2; /* tx win size, will adjust dynam */ + llc->rw = 128; /* rx win size (opt and equal to + tx_win of remote LLC) */ + skb_queue_head_init(&llc->pdu_unack_q); + sk->backlog_rcv = llc_backlog_rcv; + LLC_SK(sk) = llc; +out: return rc; +} + +/** + * __llc_sock_alloc - Allocates LLC sock + * + * Allocates a LLC sock and initializes it. Returns the new LLC sock + * or %NULL if there's no memory available for one + */ +struct sock *__llc_sock_alloc(void) +{ + struct sock *sk = sk_alloc(PF_LLC, GFP_ATOMIC, 1, NULL); + + if (!sk) + goto out; + if (llc_sock_init(sk)) + goto outsk; + sock_init_data(NULL, sk); +out: return sk; +outsk: sk_free(sk); + sk = NULL; + goto out; +} + +/** + * __llc_sock_free - Frees a LLC socket + * @sk - socket to free + * + * Frees a LLC socket + */ +void __llc_sock_free(struct sock *sk, u8 free) +{ + struct llc_opt *llc = LLC_SK(sk); + + llc->state = LLC_CONN_OUT_OF_SVC; + /* stop all (possibly) running timers */ + llc_conn_ac_stop_all_timers(sk, NULL); + /* handle return of frames on lists */ + printk(KERN_INFO __FUNCTION__ ": unackq=%d, txq=%d\n", + skb_queue_len(&llc->pdu_unack_q), + skb_queue_len(&sk->write_queue)); + skb_queue_purge(&sk->write_queue); + skb_queue_purge(&llc->pdu_unack_q); + if (free) + sock_put(sk); +} + +/** + * llc_sock_reset - resets a connection + * @sk: LLC socket to reset + * + * Resets a connection to the out of service state. Stops its timers + * and frees any frames in the queues of the connection. + */ +void llc_sock_reset(struct sock *sk) +{ + struct llc_opt *llc = LLC_SK(sk); + + llc_conn_ac_stop_all_timers(sk, NULL); + skb_queue_purge(&sk->write_queue); + skb_queue_purge(&llc->pdu_unack_q); + llc->remote_busy_flag = 0; + llc->cause_flag = 0; + llc->retry_count = 0; + llc->p_flag = 0; + llc->f_flag = 0; + llc->s_flag = 0; + llc->ack_pf = 0; + llc->first_pdu_Ns = 0; + llc->ack_must_be_send = 0; + llc->dec_step = 1; + llc->inc_cntr = 2; + llc->dec_cntr = 2; + llc->X = 0; + llc->failed_data_req = 0 ; + llc->last_nr = 0; +} + +/** + * llc_rtn_all_conns - Closes all connections of a sap + * @sap: sap to close its connections + * + * Closes all connections of a sap. Returns 0 if all actions complete + * successfully, nonzero otherwise + */ +static int llc_rtn_all_conns(struct llc_sap *sap) +{ + int rc = 0; + union llc_u_prim_data prim_data; + struct llc_prim_if_block prim; + struct list_head *entry, *tmp; + + spin_lock_bh(&sap->sk_list.lock); + if (list_empty(&sap->sk_list.list)) + goto out; + list_for_each_safe(entry, tmp, &sap->sk_list.list) { + struct llc_opt *llc = list_entry(entry, struct llc_opt, node); + + prim.sap = sap; + prim_data.disc.sk = llc->sk; + prim.prim = LLC_DISC_PRIM; + prim.data = &prim_data; + llc->state = LLC_CONN_STATE_TEMP; + if (sap->req(&prim)) + rc = 1; + } +out: spin_unlock_bh(&sap->sk_list.lock); + return rc; +} + +/** + * llc_station_get - get addr of global station. + * + * Returns address of a place to copy the global station to it. + */ +struct llc_station *llc_station_get(void) +{ + return &llc_main_station; +} + +/** + * llc_station_alloc_ev - allocates an event + * @station: Address of the station + * + * Allocates an event in this station. Returns the allocated event on + * success, %NULL otherwise. + */ +struct llc_station_state_ev *llc_station_alloc_ev(struct llc_station *station) +{ + struct llc_station_state_ev *ev = kmalloc(sizeof(*ev), GFP_ATOMIC); + + if (ev) + memset(ev, 0, sizeof(*ev)); + return ev; +} + +/** + * llc_station_send_ev: queue event and try to process queue. + * @station: Address of the station + * @ev: Address of the event + * + * Queues an event (on the station event queue) for handling by the + * station state machine and attempts to process any queued-up events. + */ +void llc_station_send_ev(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + spin_lock_bh(&station->ev_q.lock); + list_add_tail(&ev->node, &station->ev_q.list); + llc_station_service_events(station); + spin_unlock_bh(&station->ev_q.lock); +} + +/** + * llc_station_send_pdu - queues PDU to send + * @station: Address of the station + * @skb: Address of the PDU + * + * Queues a PDU to send to the MAC layer. + */ +void llc_station_send_pdu(struct llc_station *station, struct sk_buff *skb) +{ + skb_queue_tail(&station->mac_pdu_q, skb); + llc_station_send_pdus(station); +} + +/** + * llc_station_send_pdus - tries to send queued PDUs + * @station: Address of the station + * + * Tries to send any PDUs queued in the station mac_pdu_q to the MAC + * layer. + */ +static void llc_station_send_pdus(struct llc_station *station) +{ + struct sk_buff *skb; + + while ((skb = skb_dequeue(&station->mac_pdu_q)) != NULL) { + int rc = mac_send_pdu(skb); + + kfree_skb(skb); + if (rc) + break; + } +} + +/** + * llc_station_free_ev - frees an event + * @station: Address of the station + * @event: Address of the event + * + * Frees an event. + */ +static void llc_station_free_ev(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + struct sk_buff *skb = ev->data.pdu.skb; + + if (ev->type == LLC_STATION_EV_TYPE_PDU) + kfree_skb(skb); + kfree(ev); +} + +/** + * llc_station_service_events - service events in the queue + * @station: Address of the station + * + * Get an event from the station event queue (if any); attempt to service + * the event; if event serviced, get the next event (if any) on the event + * queue; if event not service, re-queue the event on the event queue and + * attempt to service the next event; when serviced all events in queue, + * finished; if don't transition to different state, just service all + * events once; if transition to new state, service all events again. + * Caller must hold station->ev_q.lock. + */ +static void llc_station_service_events(struct llc_station *station) +{ + struct llc_station_state_ev *ev; + struct list_head *entry, *tmp; + + list_for_each_safe(entry, tmp, &station->ev_q.list) { + ev = list_entry(entry, struct llc_station_state_ev, node); + list_del(&ev->node); + llc_station_next_state(station, ev); + } +} + +/** + * llc_station_next_state - processes event and goes to the next state + * @station: Address of the station + * @ev: Address of the event + * + * Processes an event, executes any transitions related to that event and + * updates the state of the station. + */ +static u16 llc_station_next_state(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + u16 rc = 1; + struct llc_station_state_trans *trans; + + if (station->state > LLC_NBR_STATION_STATES) + goto out; + trans = llc_find_station_trans(station, ev); + if (trans) { + /* got the state to which we next transition; perform the + * actions associated with this transition before actually + * transitioning to the next state */ + rc = llc_exec_station_trans_actions(station, trans, ev); + if (!rc) + /* transition station to next state if all actions + * execute successfully; done; wait for next event */ + station->state = trans->next_state; + } else + /* event not recognized in current state; re-queue it for + * processing again at a later time; return failure */ + rc = 0; +out: llc_station_free_ev(station, ev); + return rc; +} + +/** + * llc_find_station_trans - finds transition for this event + * @station: Address of the station + * @ev: Address of the event + * + * Search thru events of the current state of the station until list + * exhausted or it's obvious that the event is not valid for the current + * state. Returns the address of the transition if cound, %NULL otherwise. + */ +static struct llc_station_state_trans * + llc_find_station_trans(struct llc_station *station, + struct llc_station_state_ev *ev) +{ + int i = 0; + struct llc_station_state_trans *rc = NULL; + struct llc_station_state_trans **next_trans; + struct llc_station_state *curr_state = + &llc_station_state_table[station->state - 1]; + + for (next_trans = curr_state->transitions; next_trans[i]->ev; i++) + if (!next_trans[i]->ev(station, ev)) { + rc = next_trans[i]; + break; + } + return rc; +} + +/** + * llc_exec_station_trans_actions - executes actions for transition + * @station: Address of the station + * @trans: Address of the transition + * @ev: Address of the event that caused the transition + * + * Executes actions of a transition of the station state machine. Returns + * 0 if all actions complete successfully, nonzero otherwise. + */ +static u16 llc_exec_station_trans_actions(struct llc_station *station, + struct llc_station_state_trans *trans, + struct llc_station_state_ev *ev) +{ + u16 rc = 0; + llc_station_action_t *next_action; + + for (next_action = trans->ev_actions; + next_action && *next_action; next_action++) + if ((*next_action)(station, ev)) + rc = 1; + return rc; +} + +/** + * llc_alloc_frame - allocates sk_buff for frame + * + * Allocates an sk_buff for frame and initializes sk_buff fields. + * Returns allocated skb or %NULL when out of memory. + */ +struct sk_buff *llc_alloc_frame(void) +{ + struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC); + + if (skb) { + skb_reserve(skb, 50); + skb->nh.raw = skb->h.raw = skb->data; + skb->protocol = htons(ETH_P_802_2); + skb->dev = dev_base->next; + skb->mac.raw = skb->head; + } + return skb; +} + +static int llc_proc_get_info(char *bf, char **start, off_t offset, int length) +{ + struct llc_opt *llc; + struct list_head *sap_entry, *llc_entry; + off_t begin = 0, pos = 0; + int len = 0; + + spin_lock_bh(&llc_main_station.sap_list.lock); + list_for_each(sap_entry, &llc_main_station.sap_list.list) { + struct llc_sap *sap = list_entry(sap_entry, struct llc_sap, + node); + + len += sprintf(bf + len, "lsap=%d\n", sap->laddr.lsap); + spin_lock_bh(&sap->sk_list.lock); + if (list_empty(&sap->sk_list.list)) { + len += sprintf(bf + len, "no connections\n"); + goto unlock; + } + len += sprintf(bf + len, + "connection list:\nstate retr txwin rxwin\n"); + list_for_each(llc_entry, &sap->sk_list.list) { + llc = list_entry(llc_entry, struct llc_opt, node); + len += sprintf(bf + len, " %-5d%-5d%-6d%-5d\n", + llc->state, llc->retry_count, llc->k, + llc->rw); + } +unlock: spin_unlock_bh(&sap->sk_list.lock); + pos = begin + len; + if (pos < offset) { + len = 0; /* Keep dumping into the buffer start */ + begin = pos; + } + if (pos > offset + length) /* We have dumped enough */ + break; + } + spin_unlock_bh(&llc_main_station.sap_list.lock); + + /* The data in question runs from begin to begin + len */ + *start = bf + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Remove unwanted header data from length */ + return len; +} + +static char llc_banner[] __initdata = + KERN_INFO "LLC 2.0 by Procom, 1997, Arnaldo C. Melo, 2001\n" + KERN_INFO "NET4.0 IEEE 802.2 extended support\n"; +static char llc_error_msg[] __initdata = + KERN_ERR "LLC install NOT successful.\n"; + +static int __init llc_init(void) +{ + u16 rc = 0; + struct llc_station_state_ev *ev; + + printk(llc_banner); + INIT_LIST_HEAD(&llc_main_station.ev_q.list); + spin_lock_init(&llc_main_station.ev_q.lock); + INIT_LIST_HEAD(&llc_main_station.sap_list.list); + spin_lock_init(&llc_main_station.sap_list.lock); + skb_queue_head_init(&llc_main_station.mac_pdu_q); + ev = kmalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) + goto err; + memset(ev, 0, sizeof(*ev)); + memcpy(llc_main_station.mac_sa, dev_base->next->dev_addr, ETH_ALEN); + llc_main_station.ack_timer.expires = jiffies + 3 * HZ; + /* initialize the station component */ + llc_register_sap(0, mac_indicate); + llc_main_station.maximum_retry = 1; + llc_main_station.state = LLC_STATION_STATE_DOWN; + ev->type = LLC_STATION_EV_TYPE_SIMPLE; + ev->data.a.ev = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK; + rc = llc_station_next_state(&llc_main_station, ev); + llc_build_offset_table(); + llc_ind_prim.data = &llc_ind_data_prim; + llc_cfm_prim.data = &llc_cfm_data_prim; + proc_net_create("802.2", 0, llc_proc_get_info); + llc_ui_init(); +out: return rc; +err: printk(llc_error_msg); + rc = 1; + goto out; +} + +static void __exit llc_exit(void) +{ + llc_ui_exit(); + llc_unregister_sap(0); + proc_net_remove("802.2"); +} + +module_init(llc_init); +module_exit(llc_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Procom, 1997, Arnaldo C. Melo, Jay Schullist, 2001"); +MODULE_DESCRIPTION("LLC 2.0, NET4.0 IEEE 802.2 extended support"); Index: kernel-acme/net/llc/llc_pdu.c diff -u /dev/null kernel-acme/net/llc/llc_pdu.c:1.1.6.1 --- /dev/null Sat Dec 22 02:21:13 2001 +++ kernel-acme/net/llc/llc_pdu.c Thu Nov 29 20:36:56 2001 @@ -0,0 +1,652 @@ +/* + * llc_pdu.c - access to PDU internals + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include + +static int llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type); +static int llc_get_llc_hdr_length(u8 pdu_type); +static u8 llc_pdu_get_pf_bit(llc_pdu_sn_t *pdu); + +/** + * llc_pdu_header_init - initializes pdu header + * @skb: input skb that header must be set into it. + * @pdu_type: type of PDU (U, I or S). + * @ssap: source sap. + * @dsap: destination sap. + * @cr: command/response bit (0 or 1). + * + * This function sets DSAP, SSAP and command/Response bit in LLC header. + */ +void llc_pdu_header_init(struct sk_buff *skb, u8 pdu_type, u8 ssap, + u8 dsap, u8 cr) +{ + llc_pdu_un_t *p; + + skb->nh.raw = skb_push(skb, llc_get_llc_hdr_length(pdu_type)); + p = (llc_pdu_un_t *)skb->nh.raw; + p->dsap = dsap; + p->ssap = ssap; + p->ssap |= cr; +} + +void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 pdu_type) +{ + ((llc_pdu_un_t *)skb->nh.raw)->ssap |= pdu_type; +} + +/** + * pdu_set_pf_bit - sets poll/final bit in LLC header + * @pdu_frame: input frame that p/f bit must be set into it. + * @bit_value: poll/final bit (0 or 1). + * + * This function sets poll/final bit in LLC header (based on type of PDU). + * in I or S pdus, p/f bit is right bit of fourth byte in header. in U + * pdus p/f bit is fifth bit of third byte. + */ +void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value) +{ + u8 pdu_type; + + if (llc_pdu_decode_pdu_type(skb, &pdu_type)) + goto out; + switch (pdu_type) { + case LLC_PDU_TYPE_I: + case LLC_PDU_TYPE_S: + ((llc_pdu_sn_t *)skb->nh.raw)->ctrl_2 = + (((llc_pdu_sn_t *)skb->nh.raw)->ctrl_2 & 0xFE) | + bit_value; + break; + case LLC_PDU_TYPE_U: + ((llc_pdu_un_t *)skb->nh.raw)->ctrl_1 |= + (((llc_pdu_un_t *)skb->nh.raw)->ctrl_1 & 0xEF) | + (bit_value << 4); + break; + } +out:; +} + +/** + * llc_pdu_decode_pf_bit - extracs poll/final bit from LLC header + * @skb: input skb that p/f bit must be extracted from it + * @pf_bit: poll/final bit (0 or 1) + * + * This function extracts poll/final bit from LLC header (based on type of + * PDU). In I or S pdus, p/f bit is right bit of fourth byte in header. In + * U pdus p/f bit is fifth bit of third byte. + */ +int llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit) +{ + u8 pdu_type; + int rc = llc_pdu_decode_pdu_type(skb, &pdu_type); + + if (rc) + goto out; + switch (pdu_type) { + case LLC_PDU_TYPE_I: + case LLC_PDU_TYPE_S: + *pf_bit = ((llc_pdu_sn_t *)skb->nh.raw)->ctrl_2 & + LLC_S_PF_BIT_MASK; + break; + case LLC_PDU_TYPE_U: + *pf_bit = (((llc_pdu_un_t *)skb->nh.raw)->ctrl_1 & + LLC_U_PF_BIT_MASK) >> 4; + break; + } +out: return 0; +} + +/** + * llc_pdu_decode_cr_bit - extracs command response bit from LLC header + * @skb: input skb that c/r bit must be extracted from it. + * @cr_bit: command/response bit (0 or 1). + * + * This function extracts command/response bit from LLC header. this bit + * is right bit of source SAP. + */ +int llc_pdu_decode_cr_bit(struct sk_buff *skb, u8 *cr_bit) +{ + *cr_bit = ((llc_pdu_un_t *)skb->nh.raw)->ssap & LLC_PDU_CMD_RSP_MASK; + return 0; +} + +/** + * llc_pdu_decode_sa - extracs source address (MAC) of input frame + * @skb: input skb that source address must be extracted from it. + * @sa: pointer to source address (6 byte array). + * + * This function extracts source address(MAC) of input frame. + */ +int llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa) +{ + if (skb->protocol == ntohs(ETH_P_802_2)) + memcpy(sa, ((struct ethhdr *)skb->mac.raw)->h_source, ETH_ALEN); + else if (skb->protocol == ntohs(ETH_P_TR_802_2)) + memcpy(sa, ((struct trh_hdr *)skb->mac.raw)->saddr, ETH_ALEN); + return 0; +} + +/** + * llc_pdu_decode_da - extracts dest address of input frame + * @skb: input skb that destination address must be extracted from it + * @sa: pointer to destination address (6 byte array). + * + * This function extracts destination address(MAC) of input frame. + */ +int llc_pdu_decode_da(struct sk_buff *skb, u8 *da) +{ + if (skb->protocol == ntohs(ETH_P_802_2)) + memcpy(da, ((struct ethhdr *)skb->mac.raw)->h_dest, ETH_ALEN); + else if (skb->protocol == ntohs(ETH_P_TR_802_2)) + memcpy(da, ((struct trh_hdr *)skb->mac.raw)->daddr, ETH_ALEN); + return 0; +} + +/** + * llc_pdu_decode_dsap - extracts dest SAP of input frame + * @skb: input skb that destination SAP must be extracted from it. + * @dsap: destination SAP (output argument). + * + * This function extracts destination SAP of input frame. right bit of + * DSAP designates individual/group SAP. + */ +int llc_pdu_decode_dsap(struct sk_buff *skb, u8 *dsap) +{ + *dsap = ((llc_pdu_un_t *)skb->nh.raw)->dsap & 0xFE; + return 0; +} + +/** + * llc_pdu_decode_ssap - extracts source SAP of input frame + * @skb: input skb that source SAP must be extracted from it. + * @ssap: source SAP (output argument). + * + * This function extracts source SAP of input frame. right bit of SSAP is + * command/response bit. + */ +int llc_pdu_decode_ssap(struct sk_buff *skb, u8 *ssap) +{ + *ssap = ((llc_pdu_un_t *)skb->nh.raw)->ssap & 0xFE; + return 0; +} + +/** + * llc_pdu_init_as_ui_cmd - sets LLC header as UI PDU + * @skb: input skb that header must be set into it. + * + * This function sets third byte of LLC header as a UI PDU. + */ +int llc_pdu_init_as_ui_cmd(struct sk_buff *skb) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_U; + pdu->ctrl_1 |= LLC_1_PDU_CMD_UI; + return 0; +} + +/** + * llc_pdu_init_as_xid_cmd - sets bytes 3, 4 & 5 of LLC header as XID + * @skb: input skb that header must be set into it. + * + * This function sets third,fourth,fifth and sixth bytes of LLC header as + * a XID PDU. + */ +int llc_pdu_init_as_xid_cmd(struct sk_buff *skb, u8 svcs_supported, + u8 rx_window) +{ + llc_xid_info_t *xid_info; + llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_U; + pdu->ctrl_1 |= LLC_1_PDU_CMD_XID; + pdu->ctrl_1 |= LLC_U_PF_BIT_MASK; + xid_info = (llc_xid_info_t *)(((u8 *)&pdu->ctrl_1) + 1); + xid_info->fmt_id = LLC_XID_FMT_ID; /* 0x81*/ + xid_info->type = svcs_supported; + xid_info->rw = (rx_window << 1); /* size of recieve window */ + skb_put(skb, 3); + return 0; +} + +/** + * llc_pdu_init_as_test_cmd - sets PDU as TEST + * @skb - Address of the skb to build + * + * Sets a PDU as TEST + */ +int llc_pdu_init_as_test_cmd(struct sk_buff *skb) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_U; + pdu->ctrl_1 |= LLC_1_PDU_CMD_TEST; + pdu->ctrl_1 |= LLC_U_PF_BIT_MASK; + return 0; +} + +/** + * llc_pdu_init_as_disc_cmd - Builds DISC PDU + * @skb: Address of the skb to build + * @p_bit: The P bit to set in the PDU + * + * Builds a pdu frame as a DISC command. + */ +int llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_U; + pdu->ctrl_1 |= LLC_2_PDU_CMD_DISC; + pdu->ctrl_1 |= (((p_bit & 1) << 4) & LLC_U_PF_BIT_MASK); + return 0; +} + +/** + * pdu_init_as_i_cmd - builds I pdu + * @skb: Address of the skb to build + * @p_bit: The P bit to set in the PDU + * @ns: The sequence number of the data PDU + * @nr: The seq. number of the expected I PDU from the remote + * + * Builds a pdu frame as an I command. + */ +int llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_I; + pdu->ctrl_2 = 0; + pdu->ctrl_2 |= (p_bit & LLC_I_PF_BIT_MASK); /* p/f bit */ + pdu->ctrl_1 |= ((ns << 1) & 0xFE); /* set N(S) in bits 2..8 */ + pdu->ctrl_2 |= ((nr << 1) & 0xFE); /* set N(R) in bits 10..16 */ + return 0; +} + +/** + * pdu_init_as_rej_cmd - builds REJ PDU + * @skb: Address of the skb to build + * @p_bit: The P bit to set in the PDU + * @nr: The seq. number of the expected I PDU from the remote + * + * Builds a pdu frame as a REJ command. + */ +int llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_S; + pdu->ctrl_1 |= LLC_2_PDU_CMD_REJ; + pdu->ctrl_2 = 0; + pdu->ctrl_2 |= (p_bit & LLC_S_PF_BIT_MASK); + pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */ + pdu->ctrl_2 |= ((nr << 1) & 0xFE); /* set N(R) in bits 10..16 */ + return 0; +} + +/** + * pdu_init_as_rnr_cmd - builds RNR pdu + * @skb: Address of the skb to build + * @p_bit: The P bit to set in the PDU + * @nr: The seq. number of the expected I PDU from the remote + * + * Builds a pdu frame as an RNR command. + */ +int llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_S; + pdu->ctrl_1 |= LLC_2_PDU_CMD_RNR; + pdu->ctrl_2 = 0; + pdu->ctrl_2 |= (p_bit & LLC_S_PF_BIT_MASK); + pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */ + pdu->ctrl_2 |= ((nr << 1) & 0xFE); /* set N(R) in bits 10..16 */ + return 0; +} + +/** + * pdu_init_as_rr_cmd - Builds RR pdu + * @skb: Address of the skb to build + * @p_bit: The P bit to set in the PDU + * @nr: The seq. number of the expected I PDU from the remote + * + * Builds a pdu frame as an RR command. + */ +int llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_S; + pdu->ctrl_1 |= LLC_2_PDU_CMD_RR; + pdu->ctrl_2 = (p_bit & LLC_S_PF_BIT_MASK); + pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */ + pdu->ctrl_2 |= ((nr << 1) & 0xFE); /* set N(R) in bits 10..16 */ + return 0; +} + +/** + * pdu_init_as_sabme_cmd - builds SABME pdu + * @skb: Address of the skb to build + * @p_bit: The P bit to set in the PDU + * + * Builds a pdu frame as an SABME command. + */ +int llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_U; + pdu->ctrl_1 |= LLC_2_PDU_CMD_SABME; + pdu->ctrl_1 |= (((p_bit & 1) << 4) & LLC_U_PF_BIT_MASK); + return 0; +} + +/** + * pdu_init_as_dm_rsp - builds DM response pdu + * @skb: Address of the skb to build + * @f_bit: The F bit to set in the PDU + * + * Builds a pdu frame as a DM response. + */ +int llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_U; + pdu->ctrl_1 |= LLC_2_PDU_RSP_DM; + pdu->ctrl_1 |= (((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK); + return 0; +} + +/** + * pdu_init_as_xid_rsp - builds XID response PDU + * @skb: Address of the skb to build + * @svcs_supported: The class of the LLC (I or II) + * @rx_window: The size of the receive window of the LLC + * + * Builds a pdu frame as an XID response. + */ +int llc_pdu_init_as_xid_rsp(struct sk_buff *skb, u8 svcs_supported, + u8 rx_window) +{ + llc_xid_info_t *xid_info; + llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_U; + pdu->ctrl_1 |= LLC_1_PDU_CMD_XID; + pdu->ctrl_1 |= LLC_U_PF_BIT_MASK; + + xid_info = (llc_xid_info_t *)(((u8 *)&pdu->ctrl_1) + 1); + xid_info->fmt_id = LLC_XID_FMT_ID; + xid_info->type = svcs_supported; + xid_info->rw = rx_window << 1; + skb_put(skb, 3); + return 0; +} + +/** + * pdu_init_as_test_rsp - build TEST response PDU + * @skb: Address of the skb to build + * @ev_skb: The received TEST command PDU frame + * + * Builds a pdu frame as a TEST response. + */ +int llc_pdu_init_as_test_rsp(struct sk_buff *skb, struct sk_buff *ev_skb) +{ + int dsize; + llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_U; + pdu->ctrl_1 |= LLC_1_PDU_CMD_TEST; + pdu->ctrl_1 |= LLC_U_PF_BIT_MASK; + if (ev_skb->protocol == ntohs(ETH_P_802_2)) { + dsize = ntohs(((struct ethhdr *)ev_skb->mac.raw)->h_proto) - 3; + memcpy(((u8 *)skb->nh.raw) + 3, + ((u8 *)ev_skb->nh.raw) + 3, dsize); + skb_put(skb, dsize); + } + return 0; +} + +/** + * pdu_init_as_frmr_rsp - builds FRMR response PDU + * @pdu_frame: Address of the frame to build + * @prev_pdu: The rejected PDU frame + * @f_bit: The F bit to set in the PDU + * @vs: tx state vari value for the data link conn at the rejecting LLC + * @vr: rx state var value for the data link conn at the rejecting LLC + * @vzyxw: completely described in the IEEE Std 802.2 document (Pg 55) + * + * Builds a pdu frame as a FRMR response. + */ +int llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, llc_pdu_sn_t *prev_pdu, + u8 f_bit, u8 vs, u8 vr, u8 vzyxw) +{ + llc_frmr_info_t *frmr_info; + u8 prev_pf = 0; + u8 *ctrl; + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_U; + pdu->ctrl_1 |= LLC_2_PDU_RSP_FRMR; + pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK; + + frmr_info = (llc_frmr_info_t *)&pdu->ctrl_2; + ctrl = (u8 *)&prev_pdu->ctrl_1; + FRMR_INFO_SET_REJ_CNTRL(frmr_info,ctrl); + FRMR_INFO_SET_Vs(frmr_info, vs); + FRMR_INFO_SET_Vr(frmr_info, vr); + prev_pf = llc_pdu_get_pf_bit(prev_pdu); + FRMR_INFO_SET_C_R_BIT(frmr_info, prev_pf); + FRMR_INFO_SET_INVALID_PDU_CTRL_IND(frmr_info, vzyxw); + FRMR_INFO_SET_INVALID_PDU_INFO_IND(frmr_info, vzyxw); + FRMR_INFO_SET_PDU_INFO_2LONG_IND(frmr_info, vzyxw); + FRMR_INFO_SET_PDU_INVALID_Nr_IND(frmr_info, vzyxw); + FRMR_INFO_SET_PDU_INVALID_Ns_IND(frmr_info, vzyxw); + skb_put(skb, 5); + return 0; +} + +/** + * pdu_init_as_rr_rsp - builds RR response pdu + * @skb: Address of the skb to build + * @f_bit: The F bit to set in the PDU + * @nr: The seq. number of the expected data PDU from the remote + * + * Builds a pdu frame as an RR response. + */ +int llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_S; + pdu->ctrl_1 |= LLC_2_PDU_RSP_RR; + pdu->ctrl_2 = 0; + pdu->ctrl_2 |= (f_bit & LLC_S_PF_BIT_MASK); + pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */ + pdu->ctrl_2 |= ((nr << 1) & 0xFE); /* set N(R) in bits 10..16 */ + return 0; +} + +/** + * pdu_init_as_rej_rsp - builds REJ response pdu + * @skb: Address of the skb to build + * @f_bit: The F bit to set in the PDU + * @nr: The seq. number of the expected data PDU from the remote + * + * Builds a pdu frame as a REJ response. + */ +int llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_S; + pdu->ctrl_1 |= LLC_2_PDU_RSP_REJ; + pdu->ctrl_2 = 0; + pdu->ctrl_2 |= (f_bit & LLC_S_PF_BIT_MASK); + pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */ + pdu->ctrl_2 |= ((nr << 1) & 0xFE); /* set N(R) in bits 10..16 */ + return 0; +} + +/** + * pdu_init_as_rnr_rsp - builds RNR response pdu + * @pdu_frame: Address of the frame to build + * @f_bit: The F bit to set in the PDU + * @nr: The seq. number of the expected data PDU from the remote + * + * Builds a pdu frame as an RNR response. + */ +int llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr) +{ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_S; + pdu->ctrl_1 |= LLC_2_PDU_RSP_RNR; + pdu->ctrl_2 = 0; + pdu->ctrl_2 |= (f_bit & LLC_S_PF_BIT_MASK); + pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */ + pdu->ctrl_2 |= ((nr << 1) & 0xFE); /* set N(R) in bits 10..16 */ + return 0; +} + +/** + * pdu_init_as_ua_rsp - builds UA response pdu + * @skb: Address of the frame to build + * @f_bit: The F bit to set in the PDU + * + * Builds a pdu frame as a UA response. + */ +int llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw; + + pdu->ctrl_1 = LLC_PDU_TYPE_U; + pdu->ctrl_1 |= LLC_2_PDU_RSP_UA; + pdu->ctrl_1 |= (((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK); + return 0; +} + +/** + * llc_pdu_decode_pdu_type - designates PDU type + * @skb: input skb that type of it must be designated. + * @type: type of PDU (output argument). + * + * This function designates type of PDU (I,S or U). + */ +static int llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw; + + if (pdu->ctrl_1 & 1) { + if ((pdu->ctrl_1 & LLC_PDU_TYPE_U) == LLC_PDU_TYPE_U) + *type = LLC_PDU_TYPE_U; + else + *type = LLC_PDU_TYPE_S; + } else + *type = LLC_PDU_TYPE_I; + return 0; +} + +/** + * llc_decode_pdu_type - designates component LLC must handle for PDU + * @skb: input skb + * @dest: destination component + * + * This function designates which component of LLC must handle this PDU. + */ +int llc_decode_pdu_type(struct sk_buff *skb, u8 *dest) +{ + u8 type = LLC_DEST_CONN; /* I-PDU or S-PDU type */ + llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw; + + if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) != LLC_PDU_TYPE_U) + goto out; + switch (LLC_U_PDU_CMD(pdu)) { + case LLC_1_PDU_CMD_XID: + case LLC_1_PDU_CMD_UI: + case LLC_1_PDU_CMD_TEST: + type = LLC_DEST_SAP; + break; + case LLC_2_PDU_CMD_SABME: + case LLC_2_PDU_CMD_DISC: + case LLC_2_PDU_RSP_UA: + case LLC_2_PDU_RSP_DM: + case LLC_2_PDU_RSP_FRMR: + break; + default: + type = LLC_DEST_INVALID; + break; + } +out: *dest = type; + return 0; +} + +/** + * get_llc_hdr_len - designates LLC header length + * @pdu_type: type of PDU. + * + * This function designates LLC header length of PDU. header length for I + * and S PDU is 4 and for U is 3 bytes. Returns the length of header. + */ +static int llc_get_llc_hdr_length(u8 pdu_type) +{ + int rtn_val = 0; + + switch (pdu_type) { + case LLC_PDU_TYPE_I: + case LLC_PDU_TYPE_S: + rtn_val = 4; + break; + case LLC_PDU_TYPE_U: + rtn_val = 3; + break; + } + return rtn_val; +} + +/** + * llc_pdu_get_pf_bit - extracts p/f bit of input PDU + * @pdu: pointer to LLC header. + * + * This function extracts p/f bit of input PDU. at first examines type of + * PDU and then extracts p/f bit. Returns the p/f bit. + */ +static u8 llc_pdu_get_pf_bit(llc_pdu_sn_t *pdu) +{ + u8 pdu_type; + u8 pf_bit = 0; + + if (pdu->ctrl_1 & 1) { + if ((pdu->ctrl_1 & LLC_PDU_TYPE_U) == LLC_PDU_TYPE_U) + pdu_type = LLC_PDU_TYPE_U; + else + pdu_type = LLC_PDU_TYPE_S; + } else + pdu_type = LLC_PDU_TYPE_I; + switch (pdu_type) { + case LLC_PDU_TYPE_I: + case LLC_PDU_TYPE_S: + pf_bit = pdu->ctrl_2 & LLC_S_PF_BIT_MASK; + break; + case LLC_PDU_TYPE_U: + pf_bit = (pdu->ctrl_1 & LLC_U_PF_BIT_MASK) >> 4; + break; + } + return pf_bit; +} Index: kernel-acme/net/llc/llc_s_ac.c diff -u /dev/null kernel-acme/net/llc/llc_s_ac.c:1.1.6.1 --- /dev/null Sat Dec 22 02:21:13 2001 +++ kernel-acme/net/llc/llc_s_ac.c Thu Nov 29 20:36:56 2001 @@ -0,0 +1,222 @@ +/* + * llc_s_ac.c - actions performed during sap state transition. + * + * Description : + * Functions in this module are implementation of sap component actions. + * Details of actions can be found in IEEE-802.2 standard document. + * All functions have one sap and one event as input argument. All of + * them return 0 On success and 1 otherwise. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include + +/** + * llc_sap_action_unit_data_ind - forward UI PDU to network layer + * @sap: SAP + * @ev: the event to forward + * + * Received a UI PDU from MAC layer; forward to network layer as a + * UNITDATA INDICATION; verify our event is the kind we expect + */ +int llc_sap_action_unitdata_ind(struct llc_sap *sap, + struct llc_sap_state_ev *ev) +{ + llc_sap_rtn_pdu(sap, ev->data.pdu.skb, ev); + return 0; +} + +/** + * llc_sap_action_send_ui - sends UI PDU resp to UNITDATA REQ to MAC layer + * @sap: SAP + * @ev: the event to send + * + * Sends a UI PDU to the MAC layer in response to a UNITDATA REQUEST + * primitive from the network layer. Verifies event is a primitive type of + * event. Verify the primitive is a UNITDATA REQUEST. + */ +int llc_sap_action_send_ui(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + struct llc_prim_if_block *prim = ev->data.prim.data; + struct llc_prim_unit_data *prim_data = &prim->data->udata; + struct sk_buff *skb = prim->data->udata.skb; + int rc; + + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap, + prim_data->daddr.lsap, LLC_PDU_CMD); + rc = llc_pdu_init_as_ui_cmd(skb); + if (rc) + goto out; + rc = lan_hdrs_init(skb, prim_data->saddr.mac, prim_data->daddr.mac); + if (!rc) + llc_sap_send_pdu(sap, skb); +out: return rc; +} + +/** + * llc_sap_action_send_xid_c - send XID PDU as response to XID REQ + * @sap: SAP + * @ev: the event to send + * + * Send a XID command PDU to MAC layer in response to a XID REQUEST + * primitive from the network layer. Verify event is a primitive type + * event. Verify the primitive is a XID REQUEST. + */ +int llc_sap_action_send_xid_c(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + struct llc_prim_if_block *prim = ev->data.prim.data; + struct llc_prim_xid *prim_data = &prim->data->xid; + struct sk_buff *skb = prim_data->skb; + int rc; + + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap, + prim_data->daddr.lsap, LLC_PDU_CMD); + rc = llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0); + if (rc) + goto out; + rc = lan_hdrs_init(skb, prim_data->saddr.mac, prim_data->daddr.mac); + if (!rc) + llc_sap_send_pdu(sap, skb); +out: return rc; +} + +/** + * llc_sap_action_send_xid_r - send XID PDU resp to MAC for received XID + * @sap: SAP + * @ev: the event to send + * + * Send XID response PDU to MAC in response to an earlier received XID + * command PDU. Verify event is a PDU type event + */ +int llc_sap_action_send_xid_r(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap; + int rc = 1; + struct sk_buff *ev_skb = ev->data.pdu.skb; + struct sk_buff *skb; + + llc_pdu_decode_sa(ev_skb, mac_da); + llc_pdu_decode_da(ev_skb, mac_sa); + llc_pdu_decode_ssap(ev_skb, &dsap); + skb = llc_alloc_frame(); + if (!skb) + goto out; + skb->dev = ev_skb->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, + LLC_PDU_RSP); + rc = llc_pdu_init_as_xid_rsp(skb, LLC_XID_NULL_CLASS_2, 0); + if (rc) + goto out; + rc = lan_hdrs_init(skb, mac_sa, mac_da); + if (!rc) + llc_sap_send_pdu(sap, skb); +out: return rc; +} + +/** + * llc_sap_action_send_test_c - send TEST PDU to MAC in resp to TEST REQ + * @sap: SAP + * @ev: the event to send + * + * Send a TEST command PDU to the MAC layer in response to a TEST REQUEST + * primitive from the network layer. Verify event is a primitive type + * event; verify the primitive is a TEST REQUEST. + */ +int llc_sap_action_send_test_c(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + struct llc_prim_if_block *prim = ev->data.prim.data; + struct llc_prim_test *prim_data = &prim->data->test; + struct sk_buff *skb = prim_data->skb; + int rc; + + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap, + prim_data->daddr.lsap, LLC_PDU_CMD); + rc = llc_pdu_init_as_test_cmd(skb); + if (rc) + goto out; + rc = lan_hdrs_init(skb, prim_data->saddr.mac, prim_data->daddr.mac); + if (!rc) + llc_sap_send_pdu(sap, skb); +out: return rc; +} + +int llc_sap_action_send_test_r(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap; + int rc = 1; + struct sk_buff *ev_skb = ev->data.pdu.skb; + struct sk_buff *skb; + + llc_pdu_decode_sa(ev_skb, mac_da); + llc_pdu_decode_da(ev_skb, mac_sa); + llc_pdu_decode_ssap(ev_skb, &dsap); + skb = llc_alloc_frame(); + if (!skb) + goto out; + skb->dev = ev_skb->dev; + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, + LLC_PDU_RSP); + rc = llc_pdu_init_as_test_rsp(skb, ev_skb); + if (rc) + goto out; + rc = lan_hdrs_init(skb, mac_sa, mac_da); + if (!rc) + llc_sap_send_pdu(sap, skb); +out: return rc; +} + +/** + * llc_sap_action_report_status - report data link status to layer mgmt + * @sap: SAP + * @ev: the event to send + * + * Report data link status to layer management. Verify our event is the + * kind we expect. + */ +int llc_sap_action_report_status(struct llc_sap *sap, + struct llc_sap_state_ev *ev) +{ + return 0; +} + +/** + * llc_sap_action_xid_ind - send XID PDU resp to net layer via XID IND + * @sap: SAP + * @ev: the event to send + * + * Send a XID response PDU to the network layer via a XID INDICATION + * primitive. + */ +int llc_sap_action_xid_ind(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + llc_sap_rtn_pdu(sap, ev->data.pdu.skb, ev); + return 0; +} + +/** + * llc_sap_action_test_ind - send TEST PDU to net layer via TEST IND + * @sap: SAP + * @ev: the event to send + * + * Send a TEST response PDU to the network layer via a TEST INDICATION + * primitive. Verify our event is a PDU type event. + */ +int llc_sap_action_test_ind(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + llc_sap_rtn_pdu(sap, ev->data.pdu.skb, ev); + return 0; +} Index: kernel-acme/net/llc/llc_s_ev.c diff -u /dev/null kernel-acme/net/llc/llc_s_ev.c:1.1.6.2 --- /dev/null Sat Dec 22 02:21:13 2001 +++ kernel-acme/net/llc/llc_s_ev.c Fri Dec 7 15:49:02 2001 @@ -0,0 +1,101 @@ +/* + * llc_s_ev.c - Defines SAP component events + * + * The followed event functions are SAP component events which are described + * in 802.2 LLC protocol standard document. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include + +int llc_sap_ev_activation_req(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + return ev->type == LLC_SAP_EV_TYPE_SIMPLE && + ev->data.a.ev == LLC_SAP_EV_ACTIVATION_REQ ? 0 : 1; +} + +int llc_sap_ev_rx_ui(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) && + !LLC_PDU_TYPE_IS_U(pdu) && + LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_UI ? 0 : 1; +} + +int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + return ev->type == LLC_SAP_EV_TYPE_PRIM && + ev->data.prim.prim == LLC_DATAUNIT_PRIM && + ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; + +} + +int llc_sap_ev_xid_req(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + return ev->type == LLC_SAP_EV_TYPE_PRIM && + ev->data.prim.prim == LLC_XID_PRIM && + ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; +} + +int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) && + !LLC_PDU_TYPE_IS_U(pdu) && + LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID ? 0 : 1; +} + +int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_RSP(pdu) && + !LLC_PDU_TYPE_IS_U(pdu) && + LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID ? 0 : 1; +} + +int llc_sap_ev_test_req(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + return ev->type == LLC_SAP_EV_TYPE_PRIM && + ev->data.prim.prim == LLC_TEST_PRIM && + ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; +} + +int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) && + !LLC_PDU_TYPE_IS_U(pdu) && + LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST ? 0 : 1; +} + +int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_RSP(pdu) && + !LLC_PDU_TYPE_IS_U(pdu) && + LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_TEST ? 0 : 1; +} + +int llc_sap_ev_deactivation_req(struct llc_sap *sap, + struct llc_sap_state_ev *ev) +{ + return ev->type == LLC_SAP_EV_TYPE_SIMPLE && + ev->data.a.ev == LLC_SAP_EV_DEACTIVATION_REQ ? 0 : 1; +} Index: kernel-acme/net/llc/llc_s_st.c diff -u /dev/null kernel-acme/net/llc/llc_s_st.c:1.1.6.2 --- /dev/null Sat Dec 22 02:21:13 2001 +++ kernel-acme/net/llc/llc_s_st.c Tue Dec 11 00:26:46 2001 @@ -0,0 +1,163 @@ +/* + * llc_s_st.c - Defines SAP component state machine transitions. + * + * The followed transitions are SAP component state machine transitions + * which are described in 802.2 LLC protocol standard document. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include + +/* dummy last-transition indicator; common to all state transition groups */ +/* last entry for this state */ +/* all members are zeros, .bss zeroes it */ +static struct llc_sap_state_trans llc_sap_state_trans_n; + +/* state LLC_SAP_STATE_INACTIVE transition for LLC_SAP_EV_ACTIVATION_REQ event */ +static llc_sap_action_t llc_sap_inactive_state_actions_1[] = { + llc_sap_action_report_status, + NULL +}; + +static struct llc_sap_state_trans llc_sap_inactive_state_trans_1 = { + llc_sap_ev_activation_req, LLC_SAP_STATE_ACTIVE, + llc_sap_inactive_state_actions_1 +}; + +/* array of pointers; one to each transition */ +static struct llc_sap_state_trans *llc_sap_inactive_state_transitions[] = { + &llc_sap_inactive_state_trans_1, + &llc_sap_state_trans_n +}; + +/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_UI event */ +static llc_sap_action_t llc_sap_active_state_actions_1[] = { + llc_sap_action_unitdata_ind, + NULL +}; + +static struct llc_sap_state_trans llc_sap_active_state_trans_1 = { + llc_sap_ev_rx_ui, LLC_SAP_STATE_ACTIVE, + llc_sap_active_state_actions_1 +}; + +/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_UNITDATA_REQ event */ +static llc_sap_action_t llc_sap_active_state_actions_2[] = { + llc_sap_action_send_ui, + NULL +}; + +static struct llc_sap_state_trans llc_sap_active_state_trans_2 = { + llc_sap_ev_unitdata_req, LLC_SAP_STATE_ACTIVE, + llc_sap_active_state_actions_2 +}; + + +/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_XID_REQ event */ +static llc_sap_action_t llc_sap_active_state_actions_3[] = { + llc_sap_action_send_xid_c, + NULL +}; + +static struct llc_sap_state_trans llc_sap_active_state_trans_3 = { + llc_sap_ev_xid_req, LLC_SAP_STATE_ACTIVE, + llc_sap_active_state_actions_3 +}; + +/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_XID_C event */ +static llc_sap_action_t llc_sap_active_state_actions_4[] = { + llc_sap_action_send_xid_r, + NULL +}; + +static struct llc_sap_state_trans llc_sap_active_state_trans_4 = { + llc_sap_ev_rx_xid_c, LLC_SAP_STATE_ACTIVE, + llc_sap_active_state_actions_4 +}; + +/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_XID_R event */ +static llc_sap_action_t llc_sap_active_state_actions_5[] = { + llc_sap_action_xid_ind, + NULL +}; + +static struct llc_sap_state_trans llc_sap_active_state_trans_5 = { + llc_sap_ev_rx_xid_r, LLC_SAP_STATE_ACTIVE, + llc_sap_active_state_actions_5 +}; + +/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_TEST_REQ event */ +static llc_sap_action_t llc_sap_active_state_actions_6[] = { + llc_sap_action_send_test_c, + NULL +}; + +static struct llc_sap_state_trans llc_sap_active_state_trans_6 = { + llc_sap_ev_test_req, LLC_SAP_STATE_ACTIVE, + llc_sap_active_state_actions_6 +}; + +/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_TEST_C event */ +static llc_sap_action_t llc_sap_active_state_actions_7[] = { + llc_sap_action_send_test_r, + NULL +}; + +static struct llc_sap_state_trans llc_sap_active_state_trans_7 = { + llc_sap_ev_rx_test_c, LLC_SAP_STATE_ACTIVE, + llc_sap_active_state_actions_7 +}; + +/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_TEST_R event */ +static llc_sap_action_t llc_sap_active_state_actions_8[] = { + llc_sap_action_test_ind, + NULL +}; + +static struct llc_sap_state_trans llc_sap_active_state_trans_8 = { + llc_sap_ev_rx_test_r, LLC_SAP_STATE_ACTIVE, + llc_sap_active_state_actions_8 +}; + +/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_DEACTIVATION_REQ event */ +static llc_sap_action_t llc_sap_active_state_actions_9[] = { + llc_sap_action_report_status, + NULL +}; + +static struct llc_sap_state_trans llc_sap_active_state_trans_9 = { + llc_sap_ev_deactivation_req, LLC_SAP_STATE_INACTIVE, + llc_sap_active_state_actions_9 +}; + +/* array of pointers; one to each transition */ +static struct llc_sap_state_trans *llc_sap_active_state_transitions[] = { + &llc_sap_active_state_trans_2, + &llc_sap_active_state_trans_1, + &llc_sap_active_state_trans_3, + &llc_sap_active_state_trans_4, + &llc_sap_active_state_trans_5, + &llc_sap_active_state_trans_6, + &llc_sap_active_state_trans_7, + &llc_sap_active_state_trans_8, + &llc_sap_active_state_trans_9, + &llc_sap_state_trans_n +}; + +/* SAP state transition table */ +struct llc_sap_state llc_sap_state_table[] = { + { LLC_SAP_STATE_INACTIVE, llc_sap_inactive_state_transitions }, + { LLC_SAP_STATE_ACTIVE, llc_sap_active_state_transitions } +}; Index: kernel-acme/net/llc/llc_sap.c diff -u /dev/null kernel-acme/net/llc/llc_sap.c:1.1.6.5 --- /dev/null Sat Dec 22 02:21:13 2001 +++ kernel-acme/net/llc/llc_sap.c Tue Dec 11 00:26:46 2001 @@ -0,0 +1,259 @@ +/* + * llc_sap.c - driver routines for SAP component. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void llc_sap_free_ev(struct llc_sap *sap, struct llc_sap_state_ev *ev); +static int llc_sap_next_state(struct llc_sap *sap, struct llc_sap_state_ev *ev); +static int llc_exec_sap_trans_actions(struct llc_sap *sap, + struct llc_sap_state_trans *trans, + struct llc_sap_state_ev *ev); +static struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap, + struct llc_sap_state_ev *ev); + +/** + * llc_sap_assign_sock - adds a connection to a SAP + * @sap: pointer to SAP. + * @conn: pointer to connection. + * + * This function adds a connection to connection_list of a SAP. + */ +void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk) +{ + spin_lock_bh(&sap->sk_list.lock); + LLC_SK(sk)->sap = sap; + list_add_tail(&LLC_SK(sk)->node, &sap->sk_list.list); + sock_hold(sk); + spin_unlock_bh(&sap->sk_list.lock); +} + +/** + * llc_sap_unassign_sock - removes a connection from SAP + * @sap: SAP + * @sk: pointer to connection + * + * This function removes a connection from connection_list of a SAP. + * List locking is performed by caller (rtn_all_conns). + */ +void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk) +{ + spin_lock_bh(&sap->sk_list.lock); + list_del(&LLC_SK(sk)->node); + sock_put(sk); + spin_unlock_bh(&sap->sk_list.lock); +} + +/** + * llc_sap_alloc_ev - allocates sap event + * @sap: pointer to SAP + * @ev: allocated event (output argument) + * + * Returns the allocated sap event or %NULL when out of memory. + */ +struct llc_sap_state_ev *llc_sap_alloc_ev(struct llc_sap *sap) +{ + struct llc_sap_state_ev *ev = kmalloc(sizeof(*ev), GFP_ATOMIC); + + if (ev) + memset(ev, 0, sizeof(*ev)); + return ev; +} + +/** + * llc_sap_send_ev - sends event to SAP state machine + * @sap: pointer to SAP + * @ev: pointer to occurred event + * + * After executing actions of the event, upper layer will be indicated + * if needed(on receiving an UI frame). + */ +void llc_sap_send_ev(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + struct llc_prim_if_block *prim; + u8 flag; + + llc_sap_next_state(sap, ev); + flag = ev->ind_cfm_flag; + prim = ev->prim; + if (flag == LLC_IND) { + skb_get(ev->data.pdu.skb); + sap->ind(prim); + } + llc_sap_free_ev(sap, ev); +} + +/** + * llc_sap_rtn_pdu - Informs upper layer on rx of an UI, XID or TEST pdu. + * @sap: pointer to SAP + * @skb: received pdu + * @ev: pointer to occurred event + */ +void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb, + struct llc_sap_state_ev *ev) +{ + llc_pdu_un_t *pdu; + struct llc_prim_if_block *prim = &llc_ind_prim; + union llc_u_prim_data *prim_data = llc_ind_prim.data; + u8 lfb; + + llc_pdu_decode_sa(skb, prim_data->udata.saddr.mac); + llc_pdu_decode_da(skb, prim_data->udata.daddr.mac); + llc_pdu_decode_dsap(skb, &prim_data->udata.daddr.lsap); + llc_pdu_decode_ssap(skb, &prim_data->udata.saddr.lsap); + prim_data->udata.pri = 0; + prim_data->udata.skb = skb; + pdu = (llc_pdu_un_t *)skb->nh.raw; + switch (LLC_U_PDU_RSP(pdu)) { + case LLC_1_PDU_CMD_TEST: + prim->prim = LLC_TEST_PRIM; + break; + case LLC_1_PDU_CMD_XID: + prim->prim = LLC_XID_PRIM; + break; + case LLC_1_PDU_CMD_UI: + if (skb->protocol == ntohs(ETH_P_TR_802_2)) { + if (((struct trh_hdr *)skb->mac.raw)->rcf) { + lfb = ntohs(((struct trh_hdr *) + skb->mac.raw)->rcf) & + 0x0070; + prim_data->udata.lfb = lfb >> 4; + } else { + lfb = 0xFF; + prim_data->udata.lfb = 0xFF; + } + } + prim->prim = LLC_DATAUNIT_PRIM; + break; + } + prim->data = prim_data; + prim->sap = sap; + ev->ind_cfm_flag = LLC_IND; + ev->prim = prim; +} + +/** + * llc_sap_send_pdu - Sends a frame to MAC layer for transmition + * @sap: pointer to SAP + * @skb: pdu that must be sent + */ +void llc_sap_send_pdu(struct llc_sap *sap, struct sk_buff *skb) +{ + mac_send_pdu(skb); + kfree_skb(skb); +} + +/** + * llc_sap_free_ev - frees an sap event + * @sap: pointer to SAP + * @ev: released event + */ +static void llc_sap_free_ev(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + if (ev->type == LLC_SAP_EV_TYPE_PDU) { + llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; + + if (LLC_U_PDU_CMD(pdu) != LLC_1_PDU_CMD_UI) + kfree_skb(ev->data.pdu.skb); + } + kfree(ev); +} + +/** + * llc_sap_next_state - finds transition, execs actions & change SAP state + * @sap: pointer to SAP + * @ev: happened event + * + * This function finds transition that matches with happened event, then + * executes related actions and finally changes state of SAP. It returns + * 0 on success and 1 for failure. + */ +static int llc_sap_next_state(struct llc_sap *sap, struct llc_sap_state_ev *ev) +{ + int rc = 1; + struct llc_sap_state_trans *trans; + + if (sap->state <= LLC_NBR_SAP_STATES) { + trans = llc_find_sap_trans(sap, ev); + if (trans) { + /* got the state to which we next transition; perform + * the actions associated with this transition before + * actually transitioning to the next state */ + rc = llc_exec_sap_trans_actions(sap, trans, ev); + if (!rc) + /* transition SAP to next state if all actions + execute successfully */ + sap->state = trans->next_state; + } + } + return rc; +} + +/** + * llc_find_sap_trans - finds transition for event + * @sap: pointer to SAP + * @ev: happened event + * + * This function finds transition that matches with happened event. + * Returns the pointer to found transition on success or %NULL for + * failure. + */ +static struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap, + struct llc_sap_state_ev* ev) +{ + int i = 0; + struct llc_sap_state_trans *rc = NULL; + struct llc_sap_state_trans **next_trans; + struct llc_sap_state *curr_state = &llc_sap_state_table[sap->state - 1]; + /* search thru events for this state until list exhausted or until + * its obvious the event is not valid for the current state */ + for (next_trans = curr_state->transitions; next_trans [i]->ev; i++) + if (!next_trans[i]->ev(sap, ev)) { + /* got event match; return it */ + rc = next_trans[i]; + break; + } + return rc; +} + +/** + * llc_exec_sap_trans_actions - execute actions related to event + * @sap: pointer to SAP + * @trans: pointer to transition that it's actions must be performed + * @ev: happened event. + * + * This function executes actions that is related to happened event. + * Returns 0 for success and 1 for failure of at least one action. + */ +static int llc_exec_sap_trans_actions(struct llc_sap *sap, + struct llc_sap_state_trans *trans, + struct llc_sap_state_ev *ev) +{ + int rc = 0; + llc_sap_action_t *next_action; + + for (next_action = trans->ev_actions; + next_action && *next_action; next_action++) + if ((*next_action)(sap, ev)) + rc = 1; + return rc; +} Index: kernel-acme/net/llc/llc_sock.c diff -u /dev/null kernel-acme/net/llc/llc_sock.c:1.1.6.10 --- /dev/null Sat Dec 22 02:21:13 2001 +++ kernel-acme/net/llc/llc_sock.c Fri Dec 21 02:12:16 2001 @@ -0,0 +1,1744 @@ +/* + * llc_sock.c - LLC User Interface SAPs + * Description: + * Functions in this module are implementation of socket based llc + * communications for the Linux operating system. Support of llc class + * one and class two is provided via SOCK_DGRAM and SOCK_STREAM + * respectively. + * + * An llc2 connection is (mac + sap), only one llc2 sap connection + * is allowed per mac. Though one sap may have multiple mac + sap + * connections. + * + * Copyright (c) 2001 by Jay Schulist + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define dprintk(format, a...) printk(KERN_INFO __FUNCTION__ ": " format, ##a) + +/* remember: uninitialized global data is zeroed because its in .bss */ +static u16 llc_ui_sap_last_autoport = LLC_SAP_DYN_START; +static u16 llc_ui_sap_link_no_max[256]; +static u8 llc_ui_addrany[IFHWADDRLEN]; +static struct sockaddr_llc llc_ui_addrnull; +static struct proto_ops llc_ui_ops; +static struct sock *llc_ui_sockets; +static rwlock_t llc_ui_sockets_lock = RW_LOCK_UNLOCKED; + +static int llc_ui_indicate(struct llc_prim_if_block *prim); +static int llc_ui_confirm(struct llc_prim_if_block *prim); +static int llc_ui_wait_for_conn(struct sock *sk, int seconds); +static int llc_ui_wait_for_disc(struct sock *sk, int seconds); + +/** + * llc_ui_next_link_no - return the next unused link number for a sap + * @sap: Address of sap to get link number from. + * + * Return the next unused link number for a given sap. + */ +static inline u16 llc_ui_next_link_no(int sap) +{ + return llc_ui_sap_link_no_max[sap]++; +} + +/** + * llc_ui_mac_match - determines if two mac addresses are the same + * @mac1: First mac address to compare. + * @mac2: Second mac address to compare. + * + * Determines if two given mac address are the same. Returns 0 if there + * is not a complete match up to len, 1 if a complete match up to len is + * found. + */ +static inline u8 llc_ui_mac_match(u8 *mac1, u8 *mac2) +{ + return !memcmp(mac1, mac2, IFHWADDRLEN); +} + +/** + * llc_ui_mac_null - determines if a address is a null mac address + * @mac: Mac address to test if null. + * + * Determines if a given address is a null mac address. Returns 0 if the + * address is not a null mac, 1 if the address is a null mac. + */ +static inline u8 llc_ui_mac_null(u8 *mac) +{ + return !memcmp(mac, llc_ui_addrany, IFHWADDRLEN); +} + +/** + * llc_ui_addr_null - determines if a address structure is null + * @addr: Address to test if null. + */ +static inline u8 llc_ui_addr_null(struct sockaddr_llc *addr) +{ + return !memcmp(addr, &llc_ui_addrnull, sizeof(*addr)); +} + +/** + * llc_ui_protocol_type - return eth protocol for ARP header type + * @arphrd: ARP header type. + * + * Given an ARP header type return the corresponding ethernet protocol. + * Returns 0 if ARP header type not supported or the corresponding + * ethernet protocol type. + */ +static inline u16 llc_ui_protocol_type(u16 arphrd) +{ + u16 rc = htons(ETH_P_802_2); + + if (arphrd == ARPHRD_IEEE802) + rc = htons(ETH_P_TR_802_2); + return rc; +} + +/** + * llc_ui_header_len - return length of llc header based on operation + * @sk: Socket which contains a valid llc socket type. + * @addr: Complete sockaddr_llc structure received from the user. + * + * Provide the length of the llc header depending on what kind of + * operation the user would like to perform and the type of socket. + * Returns the correct llc header length. + */ +static inline u8 llc_ui_header_len(struct sock *sk, struct sockaddr_llc *addr) +{ + u8 rc = LLC_PDU_LEN_U; + + if (addr->sllc_test || addr->sllc_xid) + rc = LLC_PDU_LEN_U; + else if (sk->type == SOCK_STREAM) + rc = LLC_PDU_LEN_I; + return rc; +} + +/** + * llc_ui_send_conn - send connect command for new llc2 connection + * @sap : Sap the socket is bound to. + * @addr: Source and destination fields provided by the user. + * @dev : Device which this connection should use. + * @link: Link number to assign to this connection. + * + * Send a connect command to the llc layer for a new llc2 connection. + * Returns 0 upon success, non-zero if action didn't succeed. + */ +static int llc_ui_send_conn(struct sock *sk, struct llc_sap *sap, + struct sockaddr_llc *addr, + struct net_device *dev, int link) +{ + union llc_u_prim_data prim_data; + struct llc_prim_if_block prim; + + prim.data = &prim_data; + prim.sap = sap; + prim.prim = LLC_CONN_PRIM; + prim_data.conn.dev = dev; + prim_data.conn.link = link; + prim_data.conn.sk = NULL; + prim_data.conn.handler = sk; + prim_data.conn.pri = 0; + prim_data.conn.saddr.lsap = LLC_UI_SK(sk)->addr.sllc_ssap; + prim_data.conn.daddr.lsap = addr->sllc_dsap; + memcpy(prim_data.conn.saddr.mac, dev->dev_addr, IFHWADDRLEN); + memcpy(prim_data.conn.daddr.mac, addr->sllc_dmac, IFHWADDRLEN); + return sap->req(&prim); +} + +/** + * llc_ui_send_disc - send disc command to llc layer + * @sk: Socket with valid llc information. + * + * Send a disconnect command to the llc layer for an established + * llc2 connection. + * Returns 0 upon success, non-zero if action did not succeed. + */ +static int llc_ui_send_disc(struct sock *sk) +{ + struct llc_ui_opt *llc = LLC_UI_SK(sk); + union llc_u_prim_data prim_data; + struct llc_prim_if_block prim; + int rc = 0; + + if (sk->type != SOCK_STREAM || sk->state != TCP_ESTABLISHED) + goto out; + sk->state = TCP_CLOSING; + prim.data = &prim_data; + prim.sap = llc->sap; + prim.prim = LLC_DISC_PRIM; + prim_data.disc.sk = llc->core_sk; + prim_data.disc.link = llc->link; + rc = llc->sap->req(&prim); +out: return rc; +} + +/** + * llc_ui_send_data - send data via reliable llc2 connection + * @sap: Sap the socket is bound to. + * @sk: Connection the socket is using. + * @skb: Data the user wishes to send. + * @addr: Source and destination fields provided by the user. + * + * Send data via reliable llc2 connection. + * Returns 0 upon success, non-zero if action did not succeed. + */ +static int llc_ui_send_data(struct llc_sap *sap, struct sock* sk, + struct sk_buff *skb, struct sockaddr_llc *addr) +{ + union llc_u_prim_data prim_data; + struct llc_prim_if_block prim; + struct sock* core_sk = LLC_UI_SK(sk)->core_sk; + int rc; + + prim.data = &prim_data; + prim.sap = sap; + prim.prim = LLC_DATA_PRIM; + prim_data.data.skb = skb; + prim_data.data.pri = 0; + prim_data.data.sk = core_sk; + skb->protocol = llc_ui_protocol_type(addr->sllc_arphrd); + sock_hold(sk); +try: rc = sap->req(&prim); + if (rc != -EBUSY) + goto out; + rc = wait_event_interruptible(sk->socket->wait, + !LLC_UI_SK(sk)->core_sk || + !LLC_SK(core_sk)->failed_data_req); + if (!rc) + goto try; + if (!LLC_UI_SK(sk)->core_sk) + rc = -ENOTCONN; +out: sock_put(sk); + return rc; +} + +/** + * llc_ui_send_llc1 - send llc1 prim data block to llc layer. + * @sap : Sap the socket is bound to. + * @skb : Data the user wishes to send. + * @addr : Source and destination fields provided by the user. + * @primitive: Action the llc layer should perform. + * + * Send an llc1 primitive data block to the llc layer for processing. + * This function is used for test, xid and unit_data messages. + * Returns 0 upon success, non-zero if action did not succeed. + */ +static int llc_ui_send_llc1(struct llc_sap *sap, struct sk_buff *skb, + struct sockaddr_llc *addr, int primitive) +{ + union llc_u_prim_data prim_data; + struct llc_prim_if_block prim; + + prim.data = &prim_data; + prim.sap = sap; + prim.prim = primitive; + prim_data.test.skb = skb; + prim_data.test.saddr.lsap = sap->laddr.lsap; + prim_data.test.daddr.lsap = addr->sllc_dsap; + skb->protocol = llc_ui_protocol_type(addr->sllc_arphrd); + memcpy(prim_data.test.saddr.mac, skb->dev->dev_addr, IFHWADDRLEN); + memcpy(prim_data.test.daddr.mac, addr->sllc_dmac, IFHWADDRLEN); + return sap->req(&prim); +} + +/** + * llc_ui_find_sap - returns sap struct that matches sap number specified + * @sap: Sap number to search for. + * + * Search the local socket list and return the first instance of the sap + * structure which matches the sap number the user specified. + * Returns llc_sap upon match, %NULL otherwise. + */ +static inline struct llc_sap *llc_ui_find_sap(u8 sap) +{ + struct sock *sk; + struct llc_sap *s = NULL; + + read_lock_bh(&llc_ui_sockets_lock); + for (sk = llc_ui_sockets; sk; sk = sk->next) { + struct llc_ui_opt *llc = LLC_UI_SK(sk); + + if (!llc->sap) + continue; + if (llc->sap->laddr.lsap == sap) { + s = llc->sap; + break; + } + } + read_unlock_bh(&llc_ui_sockets_lock); + return s; +} + +static struct sock *__llc_ui_find_sk_by_exact(struct llc_addr *laddr, + struct llc_addr *daddr) +{ + struct sock *sk; + + for (sk = llc_ui_sockets; sk; sk = sk->next) { + struct llc_ui_opt *llc = LLC_UI_SK(sk); + + if (llc->addr.sllc_ssap == laddr->lsap && + llc->addr.sllc_dsap == daddr->lsap && + llc_ui_mac_null(llc->addr.sllc_mmac) && + llc_ui_mac_match(llc->addr.sllc_smac, laddr->mac) && + llc_ui_mac_match(llc->addr.sllc_dmac, daddr->mac)) + break; + } + return sk; +} + +/** + * __llc_ui_find_sk_by_addr - return socket matching local mac + sap. + * @addr: Local address to match. + * + * Search the local socket list and return the socket which has a matching + * local (mac + sap) address (allows null mac). This search will work on + * unconnected and connected sockets, though find_by_link_no is recommend + * for connected sockets. + * Returns sock upon match, %NULL otherwise. + */ +static struct sock *__llc_ui_find_sk_by_addr(struct llc_addr *laddr, + struct llc_addr *daddr, + struct net_device *dev) +{ + struct sock *sk, *tmp_sk; + + for (sk = llc_ui_sockets; sk; sk = sk->next) { + struct llc_ui_opt *llc = LLC_UI_SK(sk); + + if (llc->addr.sllc_ssap != laddr->lsap) + continue; + if (llc_ui_mac_null(llc->addr.sllc_smac)) { + if (!llc_ui_mac_null(llc->addr.sllc_mmac) && + !llc_ui_mac_match(llc->addr.sllc_mmac, laddr->mac)) + continue; + break; + } + if (dev && !llc_ui_mac_null(llc->addr.sllc_mmac) && + llc_ui_mac_match(llc->addr.sllc_mmac, laddr->mac) && + llc_ui_mac_match(llc->addr.sllc_smac, dev->dev_addr)) + break; + if (dev->flags & IFF_LOOPBACK) + break; + if (!llc_ui_mac_match(llc->addr.sllc_smac, laddr->mac)) + continue; + tmp_sk = __llc_ui_find_sk_by_exact(laddr, daddr); + if (tmp_sk) { + sk = tmp_sk; + break; + } + if (llc_ui_mac_null(llc->addr.sllc_dmac)) + break; + } + return sk; +} + +static struct sock *llc_ui_find_sk_by_addr(struct llc_addr *addr, + struct llc_addr *daddr, + struct net_device *dev) +{ + struct sock *sk; + + read_lock(&llc_ui_sockets_lock); + sk = __llc_ui_find_sk_by_addr(addr, daddr, dev); + if (sk) + sock_hold(sk); + read_unlock(&llc_ui_sockets_lock); + return sk; +} + +static struct sock *llc_ui_bh_find_sk_by_addr(struct llc_addr *addr, + struct llc_addr *daddr, + struct net_device *dev) +{ + struct sock *sk; + + read_lock_bh(&llc_ui_sockets_lock); + sk = __llc_ui_find_sk_by_addr(addr, daddr, dev); + if (sk) + sock_hold(sk); + read_unlock_bh(&llc_ui_sockets_lock); + return sk; +} + +/** + * llc_ui_insert_socket - insert socket into list + * @sk: Socket to insert. + * + * Insert a socket into the local llc socket list. + */ +static inline void llc_ui_insert_socket(struct sock *sk) +{ + write_lock_bh(&llc_ui_sockets_lock); + sk->next = llc_ui_sockets; + if (sk->next) + llc_ui_sockets->pprev = &sk->next; + llc_ui_sockets = sk; + sk->pprev = &llc_ui_sockets; + sock_hold(sk); + write_unlock_bh(&llc_ui_sockets_lock); +} + +/** + * llc_ui_remove_socket - remove socket from list + * @sk: Socket to remove. + * + * Remove a socket from the local llc socket list. + */ +static inline void llc_ui_remove_socket(struct sock *sk) +{ + write_lock_bh(&llc_ui_sockets_lock); + if (sk->pprev) { + if (sk->next) + sk->next->pprev = sk->pprev; + *sk->pprev = sk->next; + sk->pprev = NULL; + /* this only makes sense if the socket was inserted on the + * list, if sk->pprev is NULL it wasn't */ + sock_put(sk); + } + write_unlock_bh(&llc_ui_sockets_lock); +} + +/** + * llc_ui_destroy_sk - destroy socket + * @data: Socket which is to be destroyed. + * + * Really destroy the socket. + */ +static void llc_ui_destroy_sk(struct sock *sk) +{ + skb_queue_purge(&sk->receive_queue); + skb_queue_purge(&sk->write_queue); + sock_put(sk); + MOD_DEC_USE_COUNT; +} + +/** + * llc_ui_destroy_timer - try to destroy socket again + * @data: Socket which is to be destroyed. + * + * Attempt to destroy a socket which was previously destroyed but + * was still in use at the time. + */ +static void llc_ui_destroy_timer(unsigned long data) +{ + struct sock *sk = (struct sock *)data; + + if (!atomic_read(&sk->wmem_alloc) && + !atomic_read(&sk->rmem_alloc) && sk->dead) + llc_ui_destroy_sk(sk); + else { + sk->timer.expires = jiffies + SOCK_DESTROY_TIME; + add_timer(&sk->timer); + } +} + +/** + * llc_ui_create - alloc and init a new llc_ui socket + * @sock: Socket to initialize and attach allocated sk to. + * @protocol: Unused. + * + * Allocate and initialize a new llc_ui socket, validate the user wants a + * socket type we have available. + * Returns 0 upon success, negative upon failure. + */ +static int llc_ui_create(struct socket *sock, int protocol) +{ + struct sock *sk; + struct llc_ui_opt *llc; + int rc = -ESOCKTNOSUPPORT; + + MOD_INC_USE_COUNT; + if (sock->type != SOCK_DGRAM && sock->type != SOCK_STREAM) + goto decmod; + rc = -ENOMEM; + sk = sk_alloc(PF_LLC, GFP_KERNEL, 1, NULL); + if (!sk) + goto decmod; + llc = kmalloc(sizeof(*llc), GFP_KERNEL); + if (!llc) + goto outsk; + memset(llc, 0, sizeof(*llc)); + rc = 0; + sock_init_data(sock, sk); + LLC_UI_SK(sk) = llc; + sock->ops = &llc_ui_ops; +out: return rc; +outsk: sk_free(sk); +decmod: MOD_DEC_USE_COUNT; + goto out; +} + +/** + * llc_ui_release - shutdown socket + * @sock: Socket to release. + * + * Shutdown and deallocate an existing socket. + */ +static int llc_ui_release(struct socket *sock) +{ + struct sock *sk = sock->sk; + struct llc_ui_opt *llc; + + if (!sk) + goto out; + llc = LLC_UI_SK(sk); + if (llc->core_sk && !llc_ui_send_disc(sk)) + llc_ui_wait_for_disc(sk, 255); + llc_ui_remove_socket(sk); + if (llc->sap && !llc_ui_find_sap(llc->sap->laddr.lsap)) + llc_sap_close(llc->sap); + dprintk("rxq=%d, txq=%d\n", skb_queue_len(&sk->receive_queue), + skb_queue_len(&sk->write_queue)); + sock_orphan(sk); + sock->sk = NULL; + if (!atomic_read(&sk->wmem_alloc) && + !atomic_read(&sk->rmem_alloc) && sk->dead) + llc_ui_destroy_sk(sk); + else { + init_timer(&sk->timer); + sk->timer.expires = jiffies + SOCK_DESTROY_TIME; + sk->timer.function = llc_ui_destroy_timer; + sk->timer.data = (unsigned long)sk; + add_timer(&sk->timer); + } +out: return 0; +} + +/** + * llc_ui_autoport - provide dynamicly allocate SAP number + * + * Provide the caller with a dynamicly allocated SAP number according + * to the rules that are set in this function. Returns: 0, upon failure, + * SAP number otherwise. + */ +static int llc_ui_autoport(void) +{ + struct llc_sap *sap; + int i, tries = 0; + + while (tries < LLC_SAP_DYN_TRIES) { + for (i = llc_ui_sap_last_autoport; + i < LLC_SAP_DYN_STOP; i += 2) { + sap = llc_ui_find_sap(i); + if (!sap) { + llc_ui_sap_last_autoport = i + 2; + goto out; + } + } + llc_ui_sap_last_autoport = LLC_SAP_DYN_START; + tries++; + } + i = 0; +out: return i; +} + +/** + * llc_ui_autobind - Bind a socket to a specific address. + * @sk: Socket to bind an address to. + * @addr: Address the user wants the socket bound to. + * + * Bind a socket to a specific address. For llc a user is able to bind to + * a specific sap only or mac + sap. If the user only specifies a sap and + * a null dmac (all zeros) the user is attempting to bind to an entire + * sap. This will stop anyone else on the local system from using that + * sap. If someone else has a mac + sap open the bind to null + sap will + * fail. + * If the user desires to bind to a specific mac + sap, it is possible to + * have multiple sap connections via multiple macs. + * Bind and autobind for that matter must enforce the correct sap usage + * otherwise all hell will break loose. + * Returns: 0 upon success, negative otherwise. + */ +static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) +{ + struct sock *sk = sock->sk; + struct llc_sap *sap; + struct net_device *dev = NULL; + int rc = -EINVAL; + + if (!sk->zapped) + goto out; + /* bind to a specific mac, optional. */ + if (!llc_ui_mac_null(addr->sllc_smac)) { + rtnl_lock(); + dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_smac); + rtnl_unlock(); + rc = -ENETUNREACH; + if (!dev) + goto out; + LLC_UI_SK(sk)->dev = dev; + } + /* bind to a specific sap, optional. */ + if (!addr->sllc_ssap) { + rc = -EUSERS; + addr->sllc_ssap = llc_ui_autoport(); + if (!addr->sllc_ssap) + goto out; + } + sap = llc_ui_find_sap(addr->sllc_ssap); + if (!sap) { + sap = llc_sap_open(llc_ui_indicate, llc_ui_confirm, + addr->sllc_ssap); + rc = -EBUSY; /* some other network layer is using the sap */ + if (!sap) + goto out; + } else { + struct llc_addr laddr, daddr; + struct sock *ask; + + rc = -EUSERS; /* can't get exclusive use of sap */ + if (!dev && llc_ui_mac_null(addr->sllc_mmac)) + goto out; + memset(&laddr, 0, sizeof(laddr)); + memset(&daddr, 0, sizeof(daddr)); + if (!llc_ui_mac_null(addr->sllc_mmac)) { + if (sk->type != SOCK_DGRAM) { + rc = -EOPNOTSUPP; + goto out; + } + memcpy(laddr.mac, addr->sllc_mmac, IFHWADDRLEN); + } else + memcpy(laddr.mac, addr->sllc_smac, IFHWADDRLEN); + laddr.lsap = addr->sllc_ssap; + rc = -EADDRINUSE; /* mac + sap clash. */ + ask = llc_ui_bh_find_sk_by_addr(&laddr, &daddr, dev); + if (ask) { + sock_put(ask); + goto out; + } + } + memcpy(&LLC_UI_SK(sk)->addr, addr, sizeof(*addr)); + LLC_UI_SK(sk)->sap = sap; + rc = sk->zapped = 0; + llc_ui_insert_socket(sk); +out: return rc; +} + +/** + * llc_ui_bind - bind a socket to a specific address. + * @sock: Socket to bind an address to. + * @uaddr: Address the user wants the socket bound to. + * @addrlen: Length of the uaddr structure. + * + * Bind a socket to a specific address. For llc a user is able to bind to + * a specific sap only or mac + sap. If the user only specifies a sap and + * a null dmac (all zeros) the user is attempting to bind to an entire + * sap. This will stop anyone else on the local system from using that + * sap. If someone else has a mac + sap open the bind to null + sap will + * fail. + * If the user desires to bind to a specific mac + sap, it is possible to + * have multiple sap connections via multiple macs. + * Bind and autobind for that matter must enforce the correct sap usage + * otherwise all hell will break loose. + * Returns: 0 upon success, negative otherwise. + */ +static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) +{ + struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr; + struct sock *sk = sock->sk; + int rc = -EINVAL; + + if (!sk->zapped || addrlen != sizeof(*addr)) + goto out; + rc = -EAFNOSUPPORT; + if (addr->sllc_family != AF_LLC) + goto out; + /* use autobind, to avoid code replication. */ + rc = llc_ui_autobind(sock, addr); +out: return rc; +} + +/** + * llc_ui_shutdown - shutdown a connect llc2 socket. + * @sock: Socket to shutdown. + * @how: What part of the socket to shutdown. + * + * Shutdown a connected llc2 socket. Currently this function only supports + * shutting down both sends and receives (2), we could probably make this + * function such that a user can shutdown only half the connection but not + * right now. + * Returns: 0 upon success, negative otherwise. + */ +static int llc_ui_shutdown(struct socket *sock, int how) +{ + struct sock *sk = sock->sk; + int rc = -ENOTCONN; + + lock_sock(sk); + if (sk->state != TCP_ESTABLISHED) + goto out; + rc = -EINVAL; + if (how != 2) + goto out; + rc = llc_ui_send_disc(sk); + if (!rc) + llc_ui_wait_for_disc(sk, 255); + /* Wake up anyone sleeping in poll */ + sk->state_change(sk); +out: release_sock(sk); + return rc; +} + +/** + * llc_ui_connect - Connect to a remote llc2 mac + sap. + * @sock: Socket which will be connected to the remote destination. + * @uaddr: Remote and possibly the local address of the new connection. + * @addrlen: Size of uaddr structure. + * @flags: Operational flags specified by the user. + * + * Connect to a remote llc2 mac + sap. The caller must specify the + * destination mac and address to connect to. If the user previously + * called bind(2) with a smac the user does not need to specify the source + * address and mac. + * This function will autobind if user did not previously call bind. + * Returns: 0 upon success, negative otherwise. + */ +static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, + int addrlen, int flags) +{ + struct sock *sk = sock->sk; + struct llc_ui_opt *llc = LLC_UI_SK(sk); + struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr; + struct net_device *dev; + int rc = -EINVAL; + + lock_sock(sk); + if (addrlen != sizeof(*addr)) + goto out; + rc = -EAFNOSUPPORT; + if (addr->sllc_family != AF_LLC) + goto out; + /* bind connection to sap if user hasn't done it. */ + if (sk->zapped) { + /* bind to sap with null dev, exclusive */ + rc = llc_ui_autobind(sock, addr); + if (rc) + goto out; + } + if (!llc->dev) { + rtnl_lock(); + dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_smac); + rtnl_unlock(); + if (!dev) + goto out; + } else + dev = llc->dev; + if (sk->type != SOCK_STREAM) + goto out; + rc = -EALREADY; + if (sock->state == SS_CONNECTING) + goto out; + sock->state = SS_CONNECTING; + sk->state = TCP_SYN_SENT; + llc->link = llc_ui_next_link_no(llc->sap->laddr.lsap); + rc = llc_ui_send_conn(sk, llc->sap, addr, dev, llc->link); + if (rc) { + sock->state = SS_UNCONNECTED; + sk->state = TCP_CLOSE; + goto out; + } + rc = llc_ui_wait_for_conn(sk, 255); +out: release_sock(sk); + return rc; +} + +/** + * llc_ui_listen - allow a normal socket to accept incoming connections + * @sock: Socket to allow incoming connections on. + * @backlog: Number of connections to queue. + * + * Allow a normal socket to accept incoming connections. + * Returns 0 upon success, negative otherwise. + */ +static int llc_ui_listen(struct socket *sock, int backlog) +{ + struct sock *sk = sock->sk; + int rc = -EINVAL; + + lock_sock(sk); + if (sock->state != SS_UNCONNECTED) + goto out; + rc = -EOPNOTSUPP; + if (sk->type != SOCK_STREAM && sk->type != SOCK_SEQPACKET) + goto out; + rc = -EAGAIN; + if (sk->zapped) + goto out; + rc = 0; + if (!(unsigned)backlog) /* BSDism */ + backlog = 1; + if ((unsigned)backlog > SOMAXCONN) + backlog = SOMAXCONN; + sk->max_ack_backlog = backlog; + if (sk->state != TCP_LISTEN) { + sk->ack_backlog = 0; + sk->state = TCP_LISTEN; + } + sk->socket->flags |= __SO_ACCEPTCON; +out: release_sock(sk); + return rc; +} + +static int llc_ui_wait_for_disc(struct sock *sk, int seconds) +{ + DECLARE_WAITQUEUE(wait, current); + int rc, timeout = seconds * HZ; + + add_wait_queue_exclusive(sk->sleep, &wait); + for (;;) { + __set_current_state(TASK_INTERRUPTIBLE); + rc = 0; + if (sk->state != TCP_CLOSE) + timeout = schedule_timeout(timeout); + else + break; + rc = -ERESTARTSYS; + if (signal_pending(current)) + break; + rc = -EAGAIN; + if (!timeout) + break; + } + __set_current_state(TASK_RUNNING); + remove_wait_queue(sk->sleep, &wait); + return rc; +} + +static int llc_ui_wait_for_conn(struct sock *sk, int seconds) +{ + DECLARE_WAITQUEUE(wait, current); + int rc, timeout = seconds * HZ; + + add_wait_queue_exclusive(sk->sleep, &wait); + for (;;) { + __set_current_state(TASK_INTERRUPTIBLE); + rc = 0; + if (sk->state != TCP_ESTABLISHED) + timeout = schedule_timeout(timeout); + if (sk->state == TCP_ESTABLISHED) { + if (!LLC_UI_SK(sk)->core_sk) + rc = -EAGAIN; + break; + } + rc = -EAGAIN; + if (sk->state == TCP_CLOSE) + break; + rc = -ERESTARTSYS; + if (signal_pending(current)) + break; + rc = -EAGAIN; + if (!timeout) + break; + } + __set_current_state(TASK_RUNNING); + remove_wait_queue(sk->sleep, &wait); + return rc; +} + +/** + * llc_ui_accept - accept a new incoming connection. + * @sock: Socket which connections arrive on. + * @newsock: Socket to move incoming connection to. + * @flags: User specified operational flags. + * + * Accept a new incoming connection. + * Returns 0 upon success, negative otherwise. + */ +static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags) +{ + struct sock *sk = sock->sk, *newsk; + struct llc_ui_opt *llc, *newllc; + struct sk_buff *skb; + int rc = -EOPNOTSUPP; + + lock_sock(sk); + if (sk->type != SOCK_SEQPACKET && sk->type != SOCK_STREAM) + goto out; + rc = -EINVAL; + if (sock->state != SS_UNCONNECTED || sk->state != TCP_LISTEN) + goto out; + /* wait for a connection to arrive. */ + do { + skb = skb_dequeue(&sk->receive_queue); + if (!skb) { + rc = -EWOULDBLOCK; + if (flags & O_NONBLOCK) + goto out; + interruptible_sleep_on(sk->sleep); + rc = -ERESTARTSYS; + if (signal_pending(current)) + goto out; + } + } while (!skb); + + rc = -EINVAL; + if(!skb->sk) + goto frees; + /* attach connection to a new socket. */ + rc = llc_ui_create(newsock, sk->protocol); + if (rc) + goto frees; + rc = 0; + newsk = newsock->sk; + newsk->pair = NULL; + newsk->socket = newsock; + newsk->sleep = &newsock->wait; + newsk->zapped = 0; + newsk->state = TCP_ESTABLISHED; + newsock->state = SS_CONNECTED; + llc = LLC_UI_SK(sk); + newllc = LLC_UI_SK(newsk); + newllc->sap = llc->sap; + newllc->dev = llc->dev; + newllc->core_sk = skb->sk; + newllc->link = LLC_SK(newllc->core_sk)->link; + LLC_SK(newllc->core_sk)->handler = newsk; + memcpy(&newllc->addr, &llc->addr, sizeof(llc->addr)); + memcpy(newllc->addr.sllc_dmac, LLC_SK(skb->sk)->daddr.mac, IFHWADDRLEN); + LLC_UI_SK(newsk)->addr.sllc_dsap = LLC_SK(skb->sk)->daddr.lsap; + /* put original socket back into a clean listen state. */ + sk->state = TCP_LISTEN; + sk->ack_backlog--; + llc_ui_insert_socket(newsk); + skb->sk = NULL; +frees: kfree_skb(skb); +out: release_sock(sk); + return rc; +} + +/** + * llc_ui_recvmsg - copy received data to the socket user. + * @sock: Socket to copy data from. + * @msg: Various user space related information. + * @size: Size of user buffer. + * @flags: User specified flags. + * @scm: Unknown. + * + * Copy received data to the socket user. + * Returns non-negative upon success, negative otherwise. + */ +static int llc_ui_recvmsg(struct socket *sock, struct msghdr *msg, int size, + int flags, struct scm_cookie *scm) +{ + struct sock *sk = sock->sk; + struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name; + struct sk_buff *skb; + int rc = -ENOMEM, copied = 0; + int noblock = flags & MSG_DONTWAIT; + + lock_sock(sk); + skb = skb_recv_datagram(sk, flags, noblock, &rc); + if (!skb) + goto out; + copied = skb->len; + if (copied > size) { + copied = size; + msg->msg_flags |= MSG_TRUNC; + } + rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + if (rc) + goto dgram_free; + if (uaddr) + memcpy(uaddr, LLC_UI_SKB_CB(skb), sizeof(*uaddr)); + msg->msg_namelen = sizeof(*uaddr); +dgram_free: + skb_free_datagram(sk, skb); /* Free the datagram. */ +out: release_sock(sk); + return rc ? : copied; +} + +/** + * llc_ui_sendmsg - Transmit data provided by the socket user. + * @sock: Socket to transmit data from. + * @msg: Various user related information. + * @len: Length of data to transmit. + * @scm: Unknown. + * + * Transmit data provided by the socket user. + * Returns non-negative upon success, negative otherwise. + */ +static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, int len, + struct scm_cookie *scm) +{ + struct sock *sk = sock->sk; + struct llc_ui_opt *llc = LLC_UI_SK(sk); + struct sockaddr_llc *addr = (struct sockaddr_llc *)msg->msg_name; + int flags = msg->msg_flags; + struct net_device *dev; + struct sk_buff *skb; + int rc = -EOPNOTSUPP, size = 0; + + lock_sock(sk); + if (flags & ~MSG_DONTWAIT) + goto release; + rc = -EINVAL; + if (addr) { + if (msg->msg_namelen < sizeof(*addr)) + goto release; + } else { + if (llc_ui_addr_null(&llc->addr)) + goto release; + addr = &llc->addr; + } + /* must bind connection to sap if user hasn't done it. */ + if (sk->zapped) { + /* bind to sap with null dev, exclusive. */ + rc = llc_ui_autobind(sock, addr); + if (rc) + goto release; + } + if (!llc->dev) { + rtnl_lock(); + dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_smac); + rtnl_unlock(); + rc = -ENETUNREACH; + if (!dev) + goto release; + } else + dev = llc->dev; + size = dev->hard_header_len + len + llc_ui_header_len(sk, addr); + rc = -EMSGSIZE; + if (size > dev->mtu) + goto release; + skb = sock_alloc_send_skb(sk, size, flags & MSG_DONTWAIT, &rc); + if (!skb) + goto release; + skb->sk = sk; + skb->dev = dev; + skb_reserve(skb, dev->hard_header_len + llc_ui_header_len(sk, addr)); + rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); + if (rc) + goto release; + if (addr->sllc_test) { + rc = llc_ui_send_llc1(llc->sap, skb, addr, LLC_TEST_PRIM); + goto out; + } + if (addr->sllc_xid) { + rc = llc_ui_send_llc1(llc->sap, skb, addr, LLC_XID_PRIM); + goto out; + } + if (sk->type == SOCK_DGRAM || addr->sllc_ua) { + rc = llc_ui_send_llc1(llc->sap, skb, addr, LLC_DATAUNIT_PRIM); + goto out; + } + rc = -ENOPROTOOPT; + if (!(sk->type == SOCK_STREAM && !addr->sllc_ua)) + goto out; + rc = -ENOTCONN; + if (!llc->core_sk) + goto out; + rc = llc_ui_send_data(llc->sap, sk, skb, addr); +out: if (rc) + skb_free_datagram(sk, skb); +release: + release_sock(sk); + return rc ? : len; +} + +/** + * llc_ui_getname - return the address info of a socket + * @sock: Socket to get address of. + * @uaddr: Address structure to return information. + * @uaddrlen: Length of address structure. + * @peer: Does user want local or remote address information. + * + * Return the address information of a socket. + */ +static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr, + int *uaddrlen, int peer) +{ + struct sockaddr_llc sllc; + struct sock *sk = sock->sk; + struct llc_ui_opt *llc = LLC_UI_SK(sk); + int rc = 0; + + lock_sock(sk); + if (sk->zapped) + goto out; + *uaddrlen = sizeof(sllc); + memset(uaddr, 0, *uaddrlen); + if (peer) { + rc = -ENOTCONN; + if (sk->state != TCP_ESTABLISHED) + goto out; + if(llc->dev) + sllc.sllc_arphrd = llc->dev->type; + sllc.sllc_dsap = LLC_SK(llc->core_sk)->daddr.lsap; + memcpy(&sllc.sllc_dmac, &LLC_SK(llc->core_sk)->daddr.mac, + IFHWADDRLEN); + } else { + rc = -EINVAL; + if (!llc->sap) + goto out; + sllc.sllc_ssap = llc->sap->laddr.lsap; + + if (llc->dev) { + sllc.sllc_arphrd = llc->dev->type; + memcpy(&sllc.sllc_smac, &llc->dev->dev_addr, + IFHWADDRLEN); + } + } + rc = 0; + sllc.sllc_family = AF_LLC; + memcpy(uaddr, &sllc, sizeof(sllc)); +out: release_sock(sk); + return rc; +} + +/** + * llc_ui_ioctl - io controls for PF_LLC + * @sock: Socket to get/set info + * @cmd: command + * @arg: optional argument for cmd + * + * get/set info on llc sockets + */ +static int llc_ui_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg) +{ + return dev_ioctl(cmd, (void *)arg); +} + +/** + * llc_ui_setsockopt - set various connection specific parameters. + * @sock: Socket to set options on. + * @level: Socket level user is requesting operations on. + * @optname: Operation name. + * @optval User provided operation data. + * @optlen: Length of optval. + * + * Set various connection specific parameters. + */ +static int llc_ui_setsockopt(struct socket *sock, int level, int optname, + char *optval, int optlen) +{ + struct sock *sk = sock->sk; + struct llc_ui_opt *llc = LLC_UI_SK(sk); + struct llc_opt *core_llc; + int rc = -EINVAL, opt; + + lock_sock(sk); + if (level != SOL_LLC || optlen != sizeof(int)) + goto out; + rc = -ENOTCONN; + if (!llc->core_sk) + goto out; + rc = get_user(opt, (int *)optval); + if (rc) + goto out; + rc = -EINVAL; + core_llc = LLC_SK(llc->core_sk); + switch (optname) { + case LLC_OPT_RETRY: + if (opt > LLC_OPT_MAX_RETRY) + goto out; + core_llc->n2 = opt; + break; + case LLC_OPT_SIZE: + if (opt > LLC_OPT_MAX_SIZE) + goto out; + core_llc->n1 = opt; + break; + case LLC_OPT_ACK_TMR_EXP: + if (opt > LLC_OPT_MAX_ACK_TMR_EXP) + goto out; + core_llc->ack_timer.expire = opt; + break; + case LLC_OPT_P_TMR_EXP: + if (opt > LLC_OPT_MAX_P_TMR_EXP) + goto out; + core_llc->pf_cycle_timer.expire = opt; + break; + case LLC_OPT_REJ_TMR_EXP: + if (opt > LLC_OPT_MAX_REJ_TMR_EXP) + goto out; + core_llc->rej_sent_timer.expire = opt; + break; + case LLC_OPT_BUSY_TMR_EXP: + if (opt > LLC_OPT_MAX_BUSY_TMR_EXP) + goto out; + core_llc->busy_state_timer.expire = opt; + break; + case LLC_OPT_TX_WIN: + if (opt > LLC_OPT_MAX_WIN) + goto out; + core_llc->k = opt; + break; + case LLC_OPT_RX_WIN: + if (opt > LLC_OPT_MAX_WIN) + goto out; + core_llc->rw = opt; + break; + default: + rc = -ENOPROTOOPT; + goto out; + } + rc = 0; +out: release_sock(sk); + return rc; +} + +/** + * llc_ui_getsockopt - get connection specific socket info + * @sock: Socket to get information from. + * @level: Socket level user is requesting operations on. + * @optname: Operation name. + * @optval: Variable to return operation data in. + * @optlen: Length of optval. + * + * Get connection specific socket information. + */ +static int llc_ui_getsockopt(struct socket *sock, int level, int optname, + char *optval, int *optlen) +{ + struct sock *sk = sock->sk; + struct llc_ui_opt *llc = LLC_UI_SK(sk); + struct llc_opt *core_llc; + int val = 0, len = 0, rc = -EINVAL; + + lock_sock(sk); + if (level != SOL_LLC) + goto out; + rc = -ENOTCONN; + if (!llc->core_sk) + goto out; + rc = get_user(len, optlen); + if (rc) + goto out; + rc = -EINVAL; + if (len != sizeof(int)) + goto out; + core_llc = LLC_SK(llc->core_sk); + switch (optname) { + case LLC_OPT_RETRY: + val = core_llc->n2; break; + case LLC_OPT_SIZE: + val = core_llc->n1; break; + case LLC_OPT_ACK_TMR_EXP: + val = core_llc->ack_timer.expire; break; + case LLC_OPT_P_TMR_EXP: + val = core_llc->pf_cycle_timer.expire; break; + case LLC_OPT_REJ_TMR_EXP: + val = core_llc->rej_sent_timer.expire; break; + case LLC_OPT_BUSY_TMR_EXP: + val = core_llc->busy_state_timer.expire; break; + case LLC_OPT_TX_WIN: + val = core_llc->k; break; + case LLC_OPT_RX_WIN: + val = core_llc->rw; break; + default: + rc = -ENOPROTOOPT; + goto out; + } + rc = 0; + if (put_user(len, optlen) || copy_to_user(optval, &val, len)) + rc = -EFAULT; +out: release_sock(sk); + return rc; +} + +/** + * llc_ui_ind_test - handle TEST indication + * @prim: Primitive block provided by the llc layer. + * + * handle TEST indication. + */ +static void llc_ui_ind_test(struct llc_prim_if_block *prim) +{ + struct llc_prim_test *prim_data = &prim->data->test; + struct sk_buff *skb = prim_data->skb; + struct sockaddr_llc *llc = LLC_UI_SKB_CB(skb); + struct sock *sk = llc_ui_find_sk_by_addr(&prim_data->daddr, + &prim_data->saddr, skb->dev); + if (!sk) + goto out; + if (sk->state == TCP_LISTEN) + goto out_put; + /* save primitive for use by the user. */ + llc->sllc_family = AF_LLC; + llc->sllc_arphrd = skb->dev->type; + llc->sllc_test = 1; + llc->sllc_xid = 0; + llc->sllc_ua = 0; + llc->sllc_dsap = prim_data->daddr.lsap; + memcpy(llc->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN); + llc->sllc_ssap = prim_data->saddr.lsap; + memcpy(llc->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN); + /* queue skb to the user. */ + if (sock_queue_rcv_skb(sk, skb)) + kfree_skb(skb); +out_put: + sock_put(sk); +out:; +} + +/** + * llc_ui_ind_xid - handle XID indication + * @prim: Primitive block provided by the llc layer. + * + * handle XID indication. + */ +static void llc_ui_ind_xid(struct llc_prim_if_block *prim) +{ + struct llc_prim_xid *prim_data = &prim->data->xid; + struct sk_buff *skb = prim_data->skb; + struct sockaddr_llc *llc = LLC_UI_SKB_CB(skb); + struct sock *sk = llc_ui_find_sk_by_addr(&prim_data->daddr, + &prim_data->saddr, skb->dev); + if (!sk) + goto out; + if (sk->state == TCP_LISTEN) + goto out_put; + /* save primitive for use by the user. */ + llc->sllc_family = AF_LLC; + llc->sllc_arphrd = 0; + llc->sllc_test = 0; + llc->sllc_xid = 1; + llc->sllc_ua = 0; + llc->sllc_dsap = prim_data->daddr.lsap; + memcpy(llc->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN); + llc->sllc_ssap = prim_data->saddr.lsap; + memcpy(llc->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN); + /* queue skb to the user. */ + if (sock_queue_rcv_skb(sk, skb)) + kfree_skb(skb); +out_put: + sock_put(sk); +out:; +} + +/** + * llc_ui_ind_dataunit - handle DATAUNIT indication + * @prim: Primitive block provided by the llc layer. + * + * handle DATAUNIT indication. + */ +static void llc_ui_ind_dataunit(struct llc_prim_if_block *prim) +{ + struct llc_prim_unit_data *prim_data = &prim->data->udata; + struct sk_buff *skb = prim_data->skb; + struct sockaddr_llc *llc = LLC_UI_SKB_CB(skb); + struct sock *sk = llc_ui_find_sk_by_addr(&prim_data->daddr, + &prim_data->saddr, skb->dev); + if (!sk) + goto out; + if (sk->state == TCP_LISTEN) + goto out_put; + /* save primitive for use by the user. */ + llc->sllc_family = AF_LLC; + llc->sllc_arphrd = skb->dev->type; + llc->sllc_test = 0; + llc->sllc_xid = 0; + llc->sllc_ua = 1; + llc->sllc_dsap = prim_data->daddr.lsap; + memcpy(llc->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN); + llc->sllc_ssap = prim_data->saddr.lsap; + memcpy(llc->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN); + /* queue skb to the user. */ + if (sock_queue_rcv_skb(sk, skb)) + kfree_skb(skb); +out_put: + sock_put(sk); +out:; +} + +/** + * llc_ui_ind_conn - handle CONNECT indication + * @prim: Primitive block provided by the llc layer. + * + * handle CONNECT indication. + */ +static void llc_ui_ind_conn(struct llc_prim_if_block *prim) +{ + struct llc_prim_conn *prim_data = &prim->data->conn; + struct sock* sk; + struct sk_buff *skb2; + + LLC_SK(prim_data->sk)->laddr.lsap = prim->sap->laddr.lsap; + sk = llc_ui_find_sk_by_addr(&LLC_SK(prim_data->sk)->laddr, + &prim_data->saddr, prim_data->dev); + if (!sk) { + dprintk("llc_ui_find_sk_by_addr failed\n"); + goto out; + } + if (sk->type != SOCK_STREAM || sk->state != TCP_LISTEN) + goto out_put; + if (prim->data->conn.status) + goto out_put; /* bad status. */ + /* give this connection a link number. */ + LLC_SK(prim_data->sk)->link = + llc_ui_next_link_no(LLC_SK(prim_data->sk)->laddr.lsap); + skb2 = alloc_skb(0, GFP_ATOMIC); + if (!skb2) + goto out_put; + skb2->sk = prim_data->sk; + skb_queue_tail(&sk->receive_queue, skb2); + sk->state_change(sk); +out_put: + sock_put(sk); +out:; +} + +/** + * llc_ui_ind_data - handle DATA indication + * @prim: Primitive block provided by the llc layer. + * + * handle CONNECT indication. + */ +static void llc_ui_ind_data(struct llc_prim_if_block *prim) +{ + struct llc_prim_data *prim_data = &prim->data->data; + struct sk_buff *skb = prim_data->skb; + struct sockaddr_llc *llc = LLC_UI_SKB_CB(skb); + struct sock* sk = LLC_SK(prim_data->sk)->handler; + + if (!sk) + goto out; + sock_hold(sk); + if (sk->type != SOCK_STREAM || sk->state != TCP_ESTABLISHED) + goto out_put; + /* save primitive for use by the user. */ + llc->sllc_family = AF_LLC; + llc->sllc_arphrd = skb->dev->type; + llc->sllc_test = 0; + llc->sllc_xid = 0; + llc->sllc_ua = 0; + llc->sllc_dsap = LLC_UI_SK(sk)->sap->laddr.lsap; + memcpy(llc->sllc_dmac, LLC_SK(prim_data->sk)->laddr.mac, IFHWADDRLEN); + llc->sllc_ssap = LLC_SK(prim_data->sk)->daddr.lsap; + memcpy(llc->sllc_smac, LLC_SK(prim_data->sk)->daddr.mac, IFHWADDRLEN); + /* queue skb to the user. */ + if (sock_queue_rcv_skb(sk, skb)) { + dprintk("sock_queue_rcv_skb failed!\n"); + kfree_skb(skb); + } +out_put: + sock_put(sk); +out:; +} + +/** + * llc_ui_ind_disc - handle DISC indication + * @prim: Primitive block provided by the llc layer. + * + * handle DISC indication. + */ +static void llc_ui_ind_disc(struct llc_prim_if_block *prim) +{ + struct llc_prim_disc *prim_data = &prim->data->disc; + struct sock* sk = LLC_SK(prim_data->sk)->handler; + + if (!sk) + goto out; + sock_hold(sk); + if (sk->type != SOCK_STREAM || sk->state != TCP_ESTABLISHED) + goto out_put; + LLC_UI_SK(sk)->core_sk = NULL; + sk->shutdown = SHUTDOWN_MASK; + sk->socket->state = SS_UNCONNECTED; + sk->state = TCP_CLOSE; + if (!sk->dead) { + sk->state_change(sk); + sk->dead = 1; + } +out_put: + sock_put(sk); +out:; +} + +/** + * llc_ui_indicate - LLC user interface hook into the LLC layer. + * @prim: Primitive block provided by the llc layer. + * + * LLC user interface hook into the LLC layer, every llc_ui sap references + * this function as its indicate handler. + * Always returns 0 to indicate reception of primitive. + */ +static int llc_ui_indicate(struct llc_prim_if_block *prim) +{ + switch (prim->prim) { + case LLC_TEST_PRIM: + llc_ui_ind_test(prim); break; + case LLC_XID_PRIM: + llc_ui_ind_xid(prim); break; + case LLC_DATAUNIT_PRIM: + llc_ui_ind_dataunit(prim); break; + case LLC_CONN_PRIM: + llc_ui_ind_conn(prim); break; + case LLC_DATA_PRIM: + llc_ui_ind_data(prim); break; + case LLC_DISC_PRIM: + llc_ui_ind_disc(prim); break; + case LLC_RESET_PRIM: + case LLC_FLOWCONTROL_PRIM: + default: break; + } + return 0; +} + +/** + * llc_ui_conf_conn - handle CONN confirm. + * @prim: Primitive block provided by the llc layer. + * + * handle CONN confirm. + */ +static void llc_ui_conf_conn(struct llc_prim_if_block *prim) +{ + struct llc_prim_conn *prim_data = &prim->data->conn; + struct sock* sk = LLC_SK(prim_data->sk)->handler; + + if (!sk) { + dprintk("core_sk->handler == NULL!\n"); + goto out; + } + sock_hold(sk); + if (sk->type != SOCK_STREAM || sk->state != TCP_SYN_SENT) + goto out_put; + if (!prim->data->conn.status) { + sk->socket->state = SS_CONNECTED; + sk->state = TCP_ESTABLISHED; + LLC_UI_SK(sk)->core_sk = prim_data->sk; + } else { + dprintk("prim->data->conn.status = %d\n", + prim->data->conn.status); + sk->socket->state = SS_UNCONNECTED; + sk->state = TCP_CLOSE; + LLC_UI_SK(sk)->core_sk = NULL; + } + sk->state_change(sk); +out_put: + sock_put(sk); +out:; +} + +/** + * llc_ui_conf_data - handle DATA confirm. + * @prim: Primitive block provided by the llc layer. + * + * handle DATA confirm. + */ +static void llc_ui_conf_data(struct llc_prim_if_block *prim) +{ + struct llc_prim_data *prim_data = &prim->data->data; + struct sock* sk = LLC_SK(prim_data->sk)->handler; + + if (sk) + wake_up(sk->sleep); +} + +/** + * llc_ui_conf_disc - handle DISC confirm. + * @prim: Primitive block provided by the llc layer. + * + * handle DISC confirm. + */ +static void llc_ui_conf_disc(struct llc_prim_if_block *prim) +{ + struct llc_prim_disc *prim_data = &prim->data->disc; + struct sock* sk = LLC_SK(prim_data->sk)->handler; + + if (!sk) + goto out; + sock_hold(sk); + if (sk->type != SOCK_STREAM || sk->state != TCP_CLOSING) + goto out_put; + LLC_UI_SK(sk)->core_sk = NULL; + sk->socket->state = SS_UNCONNECTED; + sk->state = TCP_CLOSE; + sk->state_change(sk); +out_put: + sock_put(sk); +out:; +} + +/** + * llc_ui_confirm - LLC user interface hook into the LLC layer + * @prim: Primitive block provided by the llc layer. + * + * LLC user interface hook into the LLC layer, every llc_ui sap references + * this function as its confirm handler. + * Always returns 0 to indicate reception of primitive. + */ +static int llc_ui_confirm(struct llc_prim_if_block *prim) +{ + switch (prim->prim) { + case LLC_CONN_PRIM: + llc_ui_conf_conn(prim); break; + case LLC_DATA_PRIM: + llc_ui_conf_data(prim); break; + case LLC_DISC_PRIM: + llc_ui_conf_disc(prim); break; + case LLC_RESET_PRIM: break; + default: + printk(KERN_ERR __FUNCTION__ ": unknown prim %d\n", + prim->prim); + break; + } + return 0; +} + +#ifdef CONFIG_PROC_FS +/** + * llc_ui_get_info - return info to procfs + * @buffer: where to put the formatted output + * @start: starting from + * @offset: offset into buffer. + * @length: size of the buffer + * + * Get the output of the local llc ui socket list to the caller. + * Returns the length of data wrote to buffer. + */ +static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length) +{ + off_t pos = 0; + off_t begin = 0; + struct sock *s; + int len = sprintf(buffer, "SocketID SKt Mc local_mac_sap\t " + "remote_mac_sap\t tx_queue rx_queue st uid " + "link_no\n"); + /* Output the LLC socket data for the /proc filesystem */ + read_lock_bh(&llc_ui_sockets_lock); + for (s = llc_ui_sockets; s; s = s->next) { + struct llc_ui_opt *llc = LLC_UI_SK(s); + len += sprintf(buffer + len, "%p %02X %02X ", s, s->type, + !llc_ui_mac_null(llc->addr.sllc_mmac)); + if (llc->sap) { + if (llc->dev && llc_ui_mac_null(llc->addr.sllc_mmac)) + len += sprintf(buffer + len, + "%02X:%02X:%02X:%02X:%02X:%02X", + llc->dev->dev_addr[0], + llc->dev->dev_addr[1], + llc->dev->dev_addr[2], + llc->dev->dev_addr[3], + llc->dev->dev_addr[4], + llc->dev->dev_addr[5]); + else { + if (!llc_ui_mac_null(llc->addr.sllc_mmac)) + len += sprintf(buffer + len, + "%02X:%02X:%02X:%02X:%02X:%02X", + llc->addr.sllc_mmac[0], + llc->addr.sllc_mmac[1], + llc->addr.sllc_mmac[2], + llc->addr.sllc_mmac[3], + llc->addr.sllc_mmac[4], + llc->addr.sllc_mmac[5]); + else + len += sprintf(buffer + len, + "00:00:00:00:00:00"); + } + len += sprintf(buffer + len, "@%02X ", + llc->sap->laddr.lsap); + } else + len += sprintf(buffer + len, "00:00:00:00:00:00@00 "); + len += sprintf(buffer + len, + "%02X:%02X:%02X:%02X:%02X:%02X@%02X " + "%08X:%08X %02X %-3d ", + llc->addr.sllc_dmac[0], llc->addr.sllc_dmac[1], + llc->addr.sllc_dmac[2], llc->addr.sllc_dmac[3], + llc->addr.sllc_dmac[4], llc->addr.sllc_dmac[5], + llc->addr.sllc_dsap, + atomic_read(&s->wmem_alloc), + atomic_read(&s->rmem_alloc), s->state, + SOCK_INODE(s->socket)->i_uid); + if (llc->core_sk) + len += sprintf(buffer + len, "%-7d\n", + LLC_SK(llc->core_sk)->link); + else + len += sprintf(buffer + len, "no_link\n"); + /* Are we still dumping unwanted data then discard the record */ + pos = begin + len; + + if (pos < offset) { + len = 0; /* Keep dumping into the buffer start */ + begin = pos; + } + if (pos > offset + length) /* We have dumped enough */ + break; + } + read_unlock_bh(&llc_ui_sockets_lock); + + /* The data in question runs from begin to begin + len */ + *start = buffer + offset - begin; /* Start of wanted data */ + len -= offset - begin; /* Remove unwanted header data from length */ + if (len > length) + len = length; /* Remove unwanted tail data from length */ + return len; +} +#endif /* CONFIG_PROC_FS */ + +static struct net_proto_family llc_ui_family_ops = { + family: PF_LLC, + create: llc_ui_create, +}; + +static struct proto_ops SOCKOPS_WRAPPED(llc_ui_ops) = { + family: PF_LLC, + release: llc_ui_release, + bind: llc_ui_bind, + connect: llc_ui_connect, + socketpair: sock_no_socketpair, + accept: llc_ui_accept, + getname: llc_ui_getname, + poll: datagram_poll, + ioctl: llc_ui_ioctl, + listen: llc_ui_listen, + shutdown: llc_ui_shutdown, + setsockopt: llc_ui_setsockopt, + getsockopt: llc_ui_getsockopt, + sendmsg: llc_ui_sendmsg, + recvmsg: llc_ui_recvmsg, + mmap: sock_no_mmap, + sendpage: sock_no_sendpage, +}; + +#include +SOCKOPS_WRAP(llc_ui, PF_LLC); + +static char llc_ui_banner[] __initdata = + KERN_INFO "NET4.0 IEEE 802.2 User Interface SAPs, Jay Schulist, 2001\n"; + +int __init llc_ui_init(void) +{ + llc_ui_sap_last_autoport = LLC_SAP_DYN_START; + sock_register(&llc_ui_family_ops); + proc_net_create("llc", 0, llc_ui_get_info); + printk(llc_ui_banner); + return 0; +} + +void __exit llc_ui_exit(void) +{ + proc_net_remove("llc"); + sock_unregister(PF_LLC); +} Index: kernel-acme/net/llc/llc_stat.c diff -u /dev/null kernel-acme/net/llc/llc_stat.c:1.1.6.2 --- /dev/null Sat Dec 22 02:21:14 2001 +++ kernel-acme/net/llc/llc_stat.c Tue Dec 11 00:26:46 2001 @@ -0,0 +1,199 @@ +/* + * llc_stat.c - Implementation of LLC station component state machine + * transitions + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include + +/* ------------------- COMMON STATION STATE transitions ------------------ */ + +/* dummy last-transition indicator; common to all state transition groups */ +/* last entry for this state */ +/* all members are zeros, .bss zeroes it */ +static struct llc_station_state_trans llc_stat_state_trans_n; + +/* ------------------------ DOWN STATE transitions ----------------------- */ + +/* state transition for LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK event */ +static llc_station_action_t llc_stat_down_state_actions_1[] = { + llc_station_ac_start_ack_timer, + llc_station_ac_set_retry_cnt_0, + llc_station_ac_set_xid_r_cnt_0, + llc_station_ac_send_null_dsap_xid_c, + NULL +}; + +static struct llc_station_state_trans llc_stat_down_state_trans_1 = { + llc_stat_ev_enable_with_dup_addr_check, + LLC_STATION_STATE_DUP_ADDR_CHK, + llc_stat_down_state_actions_1 +}; + +/* state transition for LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK event */ +static llc_station_action_t llc_stat_down_state_actions_2[] = { + llc_station_ac_report_status, /* STATION UP */ + NULL +}; + +static struct llc_station_state_trans llc_stat_down_state_trans_2 = { + llc_stat_ev_enable_without_dup_addr_check, + LLC_STATION_STATE_UP, + llc_stat_down_state_actions_2 +}; + +/* array of pointers; one to each transition */ +static struct llc_station_state_trans *llc_stat_dwn_state_trans[] = { + &llc_stat_down_state_trans_1, + &llc_stat_down_state_trans_2, + &llc_stat_state_trans_n +}; + +/* ------------------------- UP STATE transitions ------------------------ */ +/* state transition for LLC_STATION_EV_DISABLE_REQ event */ +static llc_station_action_t llc_stat_up_state_actions_1[] = { + llc_station_ac_report_status, /* STATION DOWN */ + NULL +}; + +static struct llc_station_state_trans llc_stat_up_state_trans_1 = { + llc_stat_ev_disable_req, LLC_STATION_STATE_DOWN, + llc_stat_up_state_actions_1 +}; + +/* state transition for LLC_STATION_EV_RX_NULL_DSAP_XID_C event */ +static llc_station_action_t llc_stat_up_state_actions_2[] = { + llc_station_ac_send_xid_r, + NULL +}; + +static struct llc_station_state_trans llc_stat_up_state_trans_2 = { + llc_stat_ev_rx_null_dsap_xid_c, LLC_STATION_STATE_UP, + llc_stat_up_state_actions_2 +}; + +/* state transition for LLC_STATION_EV_RX_NULL_DSAP_TEST_C event */ +static llc_station_action_t llc_stat_up_state_actions_3[] = { + llc_station_ac_send_test_r, + NULL +}; + +static struct llc_station_state_trans llc_stat_up_state_trans_3 = { + llc_stat_ev_rx_null_dsap_test_c, LLC_STATION_STATE_UP, + llc_stat_up_state_actions_3 +}; + +/* array of pointers; one to each transition */ +static struct llc_station_state_trans *llc_stat_up_state_trans [] = { + &llc_stat_up_state_trans_1, + &llc_stat_up_state_trans_2, + &llc_stat_up_state_trans_3, + &llc_stat_state_trans_n +}; + +/* ---------------------- DUP ADDR CHK STATE transitions ----------------- */ +/* state transition for LLC_STATION_EV_RX_NULL_DSAP_0_XID_R_XID_R_CNT_EQ + * event */ +static llc_station_action_t llc_stat_dupaddr_state_actions_1[] = { + llc_station_ac_inc_xid_r_cnt_by_1, + NULL +}; + +static struct llc_station_state_trans llc_stat_dupaddr_state_trans_1 = { + llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq, + LLC_STATION_STATE_DUP_ADDR_CHK, + llc_stat_dupaddr_state_actions_1 +}; + +/* state transition for LLC_STATION_EV_RX_NULL_DSAP_1_XID_R_XID_R_CNT_EQ + * event */ +static llc_station_action_t llc_stat_dupaddr_state_actions_2[] = { + llc_station_ac_report_status, /* DUPLICATE ADDRESS FOUND */ + NULL +}; + +static struct llc_station_state_trans llc_stat_dupaddr_state_trans_2 = { + llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq, + LLC_STATION_STATE_DOWN, + llc_stat_dupaddr_state_actions_2 +}; + +/* state transition for LLC_STATION_EV_RX_NULL_DSAP_XID_C event */ +static llc_station_action_t llc_stat_dupaddr_state_actions_3[] = { + llc_station_ac_send_xid_r, + NULL +}; + +static struct llc_station_state_trans llc_stat_dupaddr_state_trans_3 = { + llc_stat_ev_rx_null_dsap_xid_c, LLC_STATION_STATE_DUP_ADDR_CHK, + llc_stat_dupaddr_state_actions_3 +}; + +/* state transition for LLC_STATION_EV_ACK_TMR_EXP_LT_RETRY_CNT_MAX_RETRY + * event */ +static llc_station_action_t llc_stat_dupaddr_state_actions_4[] = { + llc_station_ac_start_ack_timer, + llc_station_ac_inc_retry_cnt_by_1, + llc_station_ac_set_xid_r_cnt_0, + llc_station_ac_send_null_dsap_xid_c, + NULL +}; + +static struct llc_station_state_trans llc_stat_dupaddr_state_trans_4 = { + llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry, + LLC_STATION_STATE_DUP_ADDR_CHK, + llc_stat_dupaddr_state_actions_4 +}; + +/* state transition for LLC_STATION_EV_ACK_TMR_EXP_EQ_RETRY_CNT_MAX_RETRY + * event */ +static llc_station_action_t llc_stat_dupaddr_state_actions_5[] = { + llc_station_ac_report_status, /* STATION UP */ + NULL +}; + +static struct llc_station_state_trans llc_stat_dupaddr_state_trans_5 = { + llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry, + LLC_STATION_STATE_UP, + llc_stat_dupaddr_state_actions_5 +}; + +/* state transition for LLC_STATION_EV_DISABLE_REQ event */ +static llc_station_action_t llc_stat_dupaddr_state_actions_6[] = { + llc_station_ac_report_status, /* STATION DOWN */ + NULL +}; + +static struct llc_station_state_trans llc_stat_dupaddr_state_trans_6 = { + llc_stat_ev_disable_req, LLC_STATION_STATE_DOWN, + llc_stat_dupaddr_state_actions_6 +}; + +/* array of pointers; one to each transition */ +static struct llc_station_state_trans *llc_stat_dupaddr_state_trans[] = { + &llc_stat_dupaddr_state_trans_6, /* Request */ + &llc_stat_dupaddr_state_trans_4, /* Timer */ + &llc_stat_dupaddr_state_trans_5, + &llc_stat_dupaddr_state_trans_1, /* Receive frame */ + &llc_stat_dupaddr_state_trans_2, + &llc_stat_dupaddr_state_trans_3, + &llc_stat_state_trans_n +}; + +struct llc_station_state llc_station_state_table[LLC_NBR_STATION_STATES] = { + { LLC_STATION_STATE_DOWN, llc_stat_dwn_state_trans }, + { LLC_STATION_STATE_DUP_ADDR_CHK, llc_stat_dupaddr_state_trans }, + { LLC_STATION_STATE_UP, llc_stat_up_state_trans } +}; Index: kernel-acme/net/netbeui/Makefile diff -u /dev/null kernel-acme/net/netbeui/Makefile:1.1.12.1 --- /dev/null Sat Dec 22 02:21:24 2001 +++ kernel-acme/net/netbeui/Makefile Thu Nov 29 20:36:56 2001 @@ -0,0 +1,22 @@ +# +# Makefile for the Linux NETBEUI layer. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definition is now in the main makefile... + +# We only get in/to here if CONFIG_NETBEUI = 'y' or 'm' + +O_TARGET := netbeui.o + +obj-y := llc_supp.o af_netb.o config.o dextab.o dgram_serve.o \ + name_serve.o nb_common.o proc.o query_serve.o session_serve.o \ + sock_dgram.o sock_name.o sock_session.o status_serve.o + +ifeq ($(CONFIG_NETBEUI),m) + obj-m += $(O_TARGET) +endif + +include $(TOPDIR)/Rules.make Index: kernel-acme/net/netbeui/af_netb.c diff -u /dev/null kernel-acme/net/netbeui/af_netb.c:1.1.12.4 --- /dev/null Sat Dec 22 02:21:24 2001 +++ kernel-acme/net/netbeui/af_netb.c Fri Dec 21 02:12:16 2001 @@ -0,0 +1,113 @@ +/* + * af_netb.c - Contains functions that supply socket system calls for NetBEUI + * protocol stack which their names has a 'netbeui_' prefix, and + * also some utility functions that their names has a 'nbso_' + * prefix. + * Notes: + * - VRP in comments is the acronym of "Value Result Parameter" + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct proto_ops nbso_name_proto_ops; +extern struct proto_ops nbso_dgram_proto_ops; +extern struct proto_ops nbso_session_proto_ops; + +/* Socket System Calls */ +/** + * netbeui_create - Creates a NetBEUI socket. + * @sock: pointer to socket created by system before calling this function + * @protocol: integer that have protocol specific meaning, we don't use it + * + * Creates a NetBEUI socket. + * Returns 0 if operation was successful, -ESOCKTNOSUPPORT if specified + * socket type isn't supported and -ENOMEM for out of memory condition. + */ +static int netbeui_create(struct socket *sock, int protocol) +{ + struct proto_ops *prot; + struct sock *sk; + struct netbeui_opt *nb; + int rc = 0; + + MOD_INC_USE_COUNT; + switch (sock->type) { + case SOCK_STREAM: + prot = &nbso_session_proto_ops; break; + case SOCK_DGRAM: + prot = &nbso_dgram_proto_ops; break; + case SOCK_RAW: + prot = &nbso_name_proto_ops; break; + case SOCK_SEQPACKET: + default: + rc = -ESOCKTNOSUPPORT; + goto err_notsupport; + } + sk = sk_alloc(PF_NETBEUI, GFP_KERNEL, 1, NULL); + if (!sk) + goto err_sk; + nb = kmalloc(sizeof(*nb), GFP_KERNEL); + if (!nb) + goto err_nb; + memset(nb, 0, sizeof(*nb)); + sock_init_data(sock, sk); + sock->ops = prot; + NB_SK(sk) = nb; + sk->state = NBSO_INIT; +out: return rc; +err_nb: sk_free(sk); +err_sk: rc = -ENOMEM; +err_notsupport: + MOD_DEC_USE_COUNT; + goto out; +} + +/* Socket family declarations */ +static struct net_proto_family netbeui_family_ops = { + family: PF_NETBEUI, + create: netbeui_create, +}; + +/** + * nbso_init - initializes NetBEUI socket interface + * + * Initializes socket interface for servicing. This function is called + * in start of NetBEUI module installation in kernel memory. + * Returns 0 if operation was successful, negative if some fault occurs. + */ +int nbso_init(void) +{ + return sock_register(&netbeui_family_ops); +} + +/** + * nbso_exit - prepares socket interface for termination + * + * Prepares socket interface for termination of NetBEUI module operation. + * Returns 0 if operation was successful, negative if some fault occurs. + */ +int nbso_exit(void) +{ + return sock_unregister(netbeui_family_ops.family); +} Index: kernel-acme/net/netbeui/config.c diff -u /dev/null kernel-acme/net/netbeui/config.c:1.1.12.1 --- /dev/null Sat Dec 22 02:21:24 2001 +++ kernel-acme/net/netbeui/config.c Thu Nov 29 20:36:56 2001 @@ -0,0 +1,408 @@ +/* + * config.c - Contains functions that configure or query NetBEUI parameters + * from API tools such as ioctl/setsockopt/getsockopt. + * Notes: + * - VRP in comments is the acronym of "Value Result Parameter" + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* Holds NetBIOS configurable parameters */ +config_t netbios_config = { + NETBEUI_DFLT_LINK_INACT_TMOUT, + NETBEUI_DFLT_TX_TMOUT, + NETBEUI_DFLT_TX_COUNT, + NETBEUI_DFLT_RSRC_TMOUT, + NETBEUI_DFLT_DATA_ACK_TMOUT +}; + +/* + * Function: nbcs_update_netbios_config + * Updates NetBIOS parameters with new values while considers special + * cases. + * Parameters: + * newcfg: pointer to config_t which contains new values for NetBIOS + * parameters. + * Returns: none + * Notes: + * - Since most NetBIOS parameters are tuned automatically both in LLC + * and NetBEUI, this implementation contains only a subset. + * - Setting value of parameter to zero means using NetBIOS defaults + * - Two parameters "resource_timeout" and "data_ack_timeout" are added + * by this implementation. + */ +static void nbcs_update_netbios_config(config_t *newcfg) +{ + /* Setting INACT TMOUT */ + if (!newcfg->inactivity_timeout) + netbios_config.inactivity_timeout = + NETBEUI_DFLT_LINK_INACT_TMOUT; + else if (newcfg->inactivity_timeout > NETBEUI_MAX_LINK_INACT_TMOUT) + netbios_config.inactivity_timeout = + NETBEUI_MAX_LINK_INACT_TMOUT; + else + netbios_config.inactivity_timeout = newcfg->inactivity_timeout; + + /* Setting TX TMOUT */ + if (!newcfg->transmit_timeout) + netbios_config.transmit_timeout = NETBEUI_DFLT_TX_TMOUT; + else if (newcfg->transmit_timeout > NETBEUI_MAX_TX_TMOUT) + netbios_config.transmit_timeout = NETBEUI_MAX_TX_TMOUT; + else + netbios_config.transmit_timeout = newcfg->transmit_timeout; + + /* Setting TX COUNT */ + if (!newcfg->transmit_count) + netbios_config.transmit_count = NETBEUI_DFLT_TX_COUNT; + else if (newcfg->transmit_count > NETBEUI_MAX_TX_COUNT) + netbios_config.transmit_count = NETBEUI_MAX_TX_COUNT; + else + netbios_config.transmit_count = newcfg->transmit_count; + + /* Setting RSRC TMOUT */ + if (!newcfg->resource_timeout) + netbios_config.resource_timeout = NETBEUI_DFLT_RSRC_TMOUT; + else if (newcfg->resource_timeout > NETBEUI_MAX_RSRC_TMOUT) + netbios_config.resource_timeout = NETBEUI_MAX_RSRC_TMOUT; + else + netbios_config.resource_timeout = newcfg->resource_timeout; + + /* Setting DATA ACK TMOUT */ + if (!newcfg->data_ack_timeout) + netbios_config.data_ack_timeout = NETBEUI_DFLT_DATA_ACK_TMOUT; + else if (newcfg->data_ack_timeout > NETBEUI_MAX_DATA_ACK_TMOUT) + netbios_config.data_ack_timeout = NETBEUI_MAX_DATA_ACK_TMOUT; + else + netbios_config.data_ack_timeout = newcfg->data_ack_timeout; +} + +/* + * Function: nbcs_setsockopt + * Sets SOL_NETBEUI layer options provided by setsockopt system call. + * Parameters: + * sock : pointer to socket structure + * optname: option code + * optval : pointer to new value of parameter (option) + * optlen : length of option value in bytes. + * Returns: + * 0 : if new value for option set successfully + * -EOPNOTSUPP : if option is not supported on socket type + * -ENOTPROTOOPT: if NetBEUI layer does not support the option. + * Notes: + * - Refer to Implementation documents for a complete description of + * NetBEUI layer options accessible from setsockopt. + * - user buffer is checked in upper layer. + */ +int nbcs_setsockopt(struct socket *sock, int optname, void *optval, int optlen) +{ + struct sock *sk = sock->sk; + int rc = -ENOPROTOOPT; + + if (optname == SO_URGENTACK) { + rc = -ENOTCONN; + if (NB_SK(sk)->u.st.session) { + __u8 urg_ack; + + rc = -EFAULT; + if (get_user(urg_ack, (__u8 *)optval)) + goto out; + rc = 0; + NB_SK(sk)->u.st.session->urgent_ack = urg_ack; + } + } else if (optname == SO_NBPARAM) { + config_t tmp_config; + + rc = -EINVAL; + if (optlen != sizeof(netbios_config)) + goto out; + rc = -EFAULT; + if (copy_from_user((void *)&tmp_config, optval, optlen)) + goto out; + rc = 0; + nbcs_update_netbios_config(&tmp_config); + } +out: return rc; +} + +/* + * Function: nbcs_getsockopt + * Gets SOL_NETBEUI layer options requested by getsockopt system call. + * Parameters: + * sock : pointer to socket structure + * optname: option code + * optval : (VRP) pointer to buffer to save value of parameter (option) + * optlen : (VRP) pointer length of option value in bytes. + * Returns: + * 0 : if value of option is moved to optval successfully + * -EOPNOTSUPP : if option is not supported on socket type + * -ENOTPROTOOPT: if NetBEUI layer does not support the option. + * Notes: + * - Refer to Implementation documents for a complete description of + * NetBEUI layer options accessible from setsockopt. + * - user buffer is checked in upper layer. + */ +int nbcs_getsockopt(struct socket *sock, int optname, void *optval, int *optlen) +{ + struct sock *sk = sock->sk; + int len, rc = -EFAULT; + + if (get_user(len, (int *)optlen)) + goto out; + if (optname == SO_URGENTACK) { + rc = -EOPNOTSUPP; + if (!NB_SK(sk)->u.st.session) + goto out; + len = MIN(len, sizeof(NB_SK(sk)->u.st.session->urgent_ack)); + rc = -EFAULT; + if (copy_to_user(optval, + (void *)&NB_SK(sk)->u.st.session->urgent_ack, + len) || put_user(len, (int *)optlen)) + goto out; + rc = 0; + } else if (optname == SO_NBPARAM) { + len = MIN(len, sizeof(netbios_config)); + rc = -EFAULT; + if (copy_to_user(optval, (void *)&netbios_config, len) || + put_user(len, (int *)optlen)) + goto out; + rc = 0; + } else + rc = -ENOPROTOOPT; +out: return rc; +} + +/* + * Function: nbcs_purge_links + * Disconnects links on a specific network device (if exist). + * Parameters: + * dev : pointer to device that links on it must be disconnect. + * flag: type of unbinding that specified by user. The + * NETBEUI_UNBIND_FLAG_SAFE flag means that protocol stack unbinds + * from the device only no links exist on it. + * Returns: int + * zero : if command be performed successfully. + * negative: if command fails. error codes that bubble to user are + * dependent to cmd. + * -EISCONN: the device has some links as yet, but the + * NETBEUI_UNBIND_FLAG_SAFE flag is specified. + */ +static int nbcs_purge_links(struct net_device *dev, unsigned char flag) +{ + int i, count, rc = 0; + dextab_t *ltbl = nbll_get_link_table(); + + spin_lock_bh(<bl->lock); + count = ltbl->count; + for (i = ltbl->reserved; count; i++, count--) { + link_t *nb_link = ltbl->addr[i]; + + if (nb_link->dev == dev) { + if (flag == NETBEUI_UNBIND_FLAG_DROP) + nbll_drop_link(nb_link->link); + else { /* NETBEUI_UNBIND_FLAG_SAFE */ + rc = -EISCONN; + goto out; + } + } + } +out: spin_unlock_bh(<bl->lock); + return rc; +} + +static int nbcs_config_bind(struct netbeui_cfg *usp) +{ + char name[IFNAMSIZ]; + struct net_device *dev; + unsigned char reserved; + int i, rc = -EFAULT; + + if (get_user(reserved, &usp->reserved)) + goto out; + rc = -EINVAL; + if (reserved) + goto out; + rc = -EFAULT; + if (copy_from_user(name, usp->nif_name, IFNAMSIZ)) + goto out; + rc = -ENOSPC; + write_lock_bh(&netbeui_adapters.lock); + if (netbeui_adapters.count == NETBEUI_MAX_ADAPTERS) + goto unlock_adapters; + rc = 0; + for (i = 0; i < netbeui_adapters.count; i++) + if (!strcmp(netbeui_adapters.dev[i]->name, name)) + goto unlock_adapters; /* It binds already */ + read_lock_bh(&dev_base_lock); + for (dev = dev_base; dev; dev = dev->next) { + if (strcmp(dev->name, name)) + continue; + if (nbcm_apt_dev(dev)) { + dev_hold(dev); + netbeui_adapters.dev[netbeui_adapters.count] = dev; + netbeui_adapters.count++; + dev_mc_add(dev, netbeui_funcaddr(dev), + dev->addr_len, 0); + goto unlock_dev_base; + } else { + rc = -EOPNOTSUPP; + goto unlock_dev_base; + } + } + rc = -ENODEV; +unlock_dev_base: + read_unlock_bh(&dev_base_lock); +unlock_adapters: + write_unlock_bh(&netbeui_adapters.lock); +out: return rc; +} + +static int nbcs_config_unbind(struct netbeui_cfg *usp) +{ + char name[IFNAMSIZ]; + unsigned char reserved, flag; + int i, rc = -EFAULT; + + if (get_user(reserved, &usp->reserved)) + goto out; + rc = -EINVAL; + if (reserved) + goto out; + rc = -EFAULT; + if (copy_from_user(name, usp->nif_name, IFNAMSIZ) || + get_user(flag, &usp->flag)) + goto out; + write_lock_bh(&netbeui_adapters.lock); + for (i = 0; i < netbeui_adapters.count; i++) { + if (strcmp(netbeui_adapters.dev[i]->name, name)) + continue; + rc = nbcs_purge_links(netbeui_adapters.dev[i], flag); + if (rc) + goto unlock; + dev_mc_delete(netbeui_adapters.dev[i], + netbeui_funcaddr(netbeui_adapters.dev[i]), + netbeui_adapters.dev[i]->addr_len, 0); + dev_put(netbeui_adapters.dev[i]); + netbeui_adapters.count--; + if (i < netbeui_adapters.count) + netbeui_adapters.dev[i] = + netbeui_adapters.dev[netbeui_adapters.count]; + netbeui_adapters.dev[netbeui_adapters.count] = NULL; + rc = 0; + goto unlock; + } + rc = -ENODEV; +unlock: write_unlock_bh(&netbeui_adapters.lock); +out: return rc; +} + +/* + * Function: nbcs_config + * Performs configuration actions on the NetBEUI via NBIOCCONFIG ioctl + * command. + * Parameters: + * usp: pointer to 'struct netbeui_cfg' that contains command and its + * arguments. + * Returns: int + * zero : if command is performed successfully. + * negative: if command fails. error codes that bubble to user are + * dependent to usp->command. + * -EOPNOTSUPP: the command is not valid. + */ +static int nbcs_config(struct netbeui_cfg *usp) +{ + unsigned short command; + int lnn, snn, rc = -EFAULT; + + if (get_user(command, &usp->command)) + goto out; + switch (command) { + case NETBEUI_CFGCMD_NIF_UNBIND: + rc = nbcs_config_unbind(usp); + break; + case NETBEUI_CFGCMD_NIF_BIND: + rc = nbcs_config_bind(usp); + break; + case NETBEUI_CFGCMD_DROP_SESS: + if (get_user(lnn, &usp->ln_num) || + get_user(snn, &usp->sn_num)) + break; + rc = -EINVAL; + if (lnn < 0 || lnn >= NETBEUI_MAX_LINKS || + snn < 1 || snn >= NETBEUI_MAX_SESSIONS) + break; + rc = nbss_drop_session(lnn, snn); + break; + case NETBEUI_CFGCMD_DROP_LINK: + if (get_user(lnn, &usp->ln_num)) + break; + rc = -EINVAL; + if (lnn < 0 || lnn >= NETBEUI_MAX_LINKS) + break; + rc = nbll_drop_link(lnn); + break; + default: + rc = -EOPNOTSUPP; + break; + } +out: return rc; +} + +/* + * Function: nbcs_ioctl + * Provides NetBEUI level requests of ioctl() system call. + * Parameters: + * cmd: code of command that must perform. + * arg: pointer to appropriate data structure, related to command. + * Returns: int + * zero : if command be performed successfully. + * negative: if command fails. error codes that bubble to user are + * dependent to cmd. + * -EOPNOTSUPP: the command is not valid. + */ +int nbcs_ioctl(unsigned int cmd, void *arg) +{ + int len, rc = -EOPNOTSUPP; + + switch (cmd) { + case NBIOCGSTATUS: { + struct netbeui_status *usp = arg; + + rc = -EFAULT; + if (get_user(len, &usp->buff_len)) + break; + rc = -EINVAL; + if (len < NETBEUI_MIN_STATUS_BUFF_LEN) + break; + rc = nbst_obtain_status(usp->called_name, + usp->status_buff, + &usp->buff_len); + break; + } + case NBIOCCONFIG: { + struct netbeui_cfg *usp = arg; + + rc = -EACCES; + if (!capable(CAP_NET_ADMIN)) + break; + rc = nbcs_config(usp); + break; + } + } + return rc; +} Index: kernel-acme/net/netbeui/dextab.c diff -u /dev/null kernel-acme/net/netbeui/dextab.c:1.1.12.1 --- /dev/null Sat Dec 22 02:21:24 2001 +++ kernel-acme/net/netbeui/dextab.c Thu Nov 29 20:36:56 2001 @@ -0,0 +1,244 @@ +/* + * dextab.c - Contains functions that implement a dynamically expandable table. + * The abstraction includes a data structure with a table of + * addresses which expands in order of two. The table never shrinks. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include + +/* + * Function: dextab_init + * Initializes dextab_t structure + * Parameters: + * tbl : pointer to dextab_t to be initialized + * reserved: number of entries to reserve from head of dextab. This value + * instructs other functions not to use those entries. + * max_size: maximum number of entries the can hold. + * Returns: none + * Note: + * - There are two ways to initialize a dextab: + * 1- Staticly initializating when defining dextab_t + * 2- calling dextab_init + */ +void dextab_init(dextab_t *tbl, int reserved, int max_size) +{ + tbl->addr = NULL; + tbl->size = 0; + tbl->reserved = reserved; + tbl->max_size = max_size; + tbl->count = 0; + spin_lock_init(&tbl->lock); +} + +/* + * Function: dextab_expand + * Expands table array of pointers in order of two. The old entries + * contents are safely kept in their place. + * Parameters: + * tbl : pointer to dextab_t to be expanded + * Returns: + * 0 : If table expanded successfully. + * non-zero: if table entry count has reached maximum size determined + * in initialization steps and if memory allocation failed. + * Don't grab tbl->lock, dextab_add_insert_entry already does this + */ +static int dextab_expand(dextab_t *tbl) +{ + int new_size; + void **new_addr; + int rc = -1; + + new_size = !tbl->size ? 16 : (tbl->size * 2); + /* Table size should not exceed maximum table size */ + if (new_size > tbl->max_size) { + if (tbl->size < tbl->max_size) + new_size = tbl->max_size; + else + goto out; + } + new_addr = kmalloc(new_size * sizeof(void *), GFP_ATOMIC); + if (!new_addr) + goto out; + /* Copy previous data from old area to new one */ + memset(new_addr, 0, new_size * sizeof(void *)); + if (tbl->addr) { + memcpy(new_addr, tbl->addr, tbl->size * sizeof(void *)); + kfree(tbl->addr); + } + tbl->addr = new_addr; + tbl->size = new_size; + rc = 0; +out: return rc; +} + +/* + * Function: dextab_add_insert_entry + * This is a back-end function which depending on its arguments creates + * an entry or puts a pre-allocated entry into dextab. The front ends + * are macros defined in header files. + * Parameters: + * tbl : pointer to dextab_t to insert element into + * entry_size: size of entry to add. if non-zero value passed, the memory + * is allocated with entry_size bytes. + * entry : address of entry to insert into table + * Returns: + * >=0 : uopn successfull insertion into table, this is the index + * of entry in table. + * <0 : unsuccessful insertion + * Note: + * - The entry_size and entry are exclusive arguments and entry_size + * precedes entry in decisions. + * - Add means allocate and insert entry, which is usually indicated by + * setting entry_size to non-zero value. + * - Insert means insert a pre-allocated entry, which is usually indicated + * by setting entry_size to zero and passing an address in entry. + */ +int __dextab_add_insert_entry(dextab_t *tbl, int entry_size, void *entry) +{ + int index, rc = -1; + + /* If you can find a free slot in table add entry there */ + for (index = tbl->reserved; index < tbl->size; index++) { + if (tbl->addr[index]) + continue; + tbl->addr[index] = entry_size > 0 ? + kmalloc(entry_size, GFP_ATOMIC) : entry; + if (tbl->addr[index]) { + tbl->count++; + rc = index; + } + goto out; + } + /* Try to expand table then retry again */ + if (!dextab_expand(tbl)) { + rc = __dextab_add_insert_entry(tbl, entry_size, entry); + goto out; + } + /* Could not expand table return error */ + rc = -1; +out: return rc; +} + +int dextab_add_insert_entry(dextab_t *tbl, int entry_size, void *entry) +{ + int rc = -1; + + spin_lock_bh(&tbl->lock); + rc = __dextab_add_insert_entry(tbl, entry_size, entry); + spin_unlock_bh(&tbl->lock); + return rc; +} + +/* + * Function: dextab_remove_delete_index + * This is a back-end function which depending on its arguments removes + * destructs an entry from dextab. The front ends are macros defined in + * header files. + * Parameters: + * tbl : pointer to dextab_t to remove element from + * entry_index: index of entry in table + * flag : removal or deletion flag. Values are: + * - DEXTAB_FREE_ENTRY + * - DEXTAB_NOFREE_ENTRY (otherwise) + * Returns: none + * Note: + * - The flag value is checked against DEXTAB_FREE_ENTRY + * - Remove means delete entry from table and free its memory, This is + * indicated by setting qflag DEXTAB_FREE_ENTRY + * - Delete means delete entry from memory, this is indicated by setting + * qflag to everything other than DEXTAB_FREE_ENTRY usually + * DEXTAB_NOFREE_ENTRY + */ +void __dextab_remove_delete_index(dextab_t *tbl, int entry_index, int flag) +{ + if (entry_index < tbl->size && entry_index >= tbl->reserved) + if (tbl->addr[entry_index]) { + if (flag == DEXTAB_FREE_ENTRY) + kfree(tbl->addr[entry_index]); + tbl->addr[entry_index] = NULL; + tbl->count--; + } +} + +void dextab_remove_delete_index(dextab_t *tbl, int entry_index, int flag) +{ + spin_lock_bh(&tbl->lock); + __dextab_remove_delete_index(tbl, entry_index, flag); + spin_unlock_bh(&tbl->lock); +} + +/* + * Function: dextab_entry_index + * Returns index of an entry in table using its address. + * Parameters: + * tbl : pointer to dextab_t to find entry in + * entry: address of entry to find in table + * Returns: + * >= 0: index of entry found in table + * < 0 : if entry not found in table + */ +int dextab_entry_index(dextab_t *tbl, void *entry) +{ + int index; + + spin_lock_bh(&tbl->lock); + for (index = tbl->reserved; index < tbl->size; index++) + if (tbl->addr[index] == entry) + break; + if (index >= tbl->size) + index = -1; + spin_unlock_bh(&tbl->lock); + return index; +} + +/* + * Function: dextab_count_entries + * returns count of entries in dextab + * Parameters: + * tbl : pointer to dextab_t to count its entries + * Returns: + * >0 : count of entries in table + */ +inline int __dextab_count_entries(dextab_t *tbl) +{ + return tbl->count; +} + +inline int dextab_count_entries(dextab_t *tbl) +{ + int rc; + + spin_lock_bh(&tbl->lock); + rc = __dextab_count_entries(tbl); + spin_unlock_bh(&tbl->lock); + return rc; +} + +/* + * Function: dextab_destruct + * housekeep a dextab, deallocates memories, .... + * Parameters: + * tbl: pointer to dextab_t to destruct + * Returns: none + */ +void dextab_destruct(dextab_t *tbl) +{ + spin_lock_bh(&tbl->lock); + if (tbl->addr) + kfree(tbl->addr); + spin_unlock_bh(&tbl->lock); + dextab_init(tbl, tbl->reserved, tbl->max_size); +} Index: kernel-acme/net/netbeui/dgram_serve.c diff -u /dev/null kernel-acme/net/netbeui/dgram_serve.c:1.1.12.1 --- /dev/null Sat Dec 22 02:21:24 2001 +++ kernel-acme/net/netbeui/dgram_serve.c Thu Nov 29 20:36:56 2001 @@ -0,0 +1,598 @@ +/* + * dgram_serve.c - Contains functions that supply DATAGRAM service for NetBEUI + * protocol stack, and also some utility functions. + * + * Notes: + * - VRP in comments is the acronym of "Value Result Parameter" + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef spin_trylock_bh +#define spin_trylock_bh(lock) ({ int __r; local_bh_disable(); \ + __r = spin_trylock(lock); \ + if (!__r) local_bh_enable(); __r; }) +#endif + +unsigned int dgbc_mtu; /* DataGram BroadCast Maximum Transfer Unit */ + +static struct { + spinlock_t lock; + name_dgrms_t *obc; /* One Behind Cache */ + name_dgrms_t *normal_list; + name_dgrms_t *star_list; +} nbdg_names = { + lock: SPIN_LOCK_UNLOCKED, +}; + +/* Internal NBDG functions */ +/* + * Function: nbdg_find_name + * Finds sightly name_dgrms structure address depend on its name in the + * normal_list. + * + * Parameters: + * name : pointer to name that must find its structure address. + * + * Returns: name_dgrms_t * + * non NULL : address of related name_dgrms structure. + * NULL : means requested name not exist in normal_list. + */ +static inline name_dgrms_t *nbdg_find_name (char *name) +{ + name_dgrms_t *curr; + + for (curr = nbdg_names.normal_list; curr; curr = curr->next) + if (!memcmp(curr->name, name, NETBEUI_NAME_LEN)) + break; + return curr; +} + +/* + * Function: nbdg_find_such_frame + * Finds another frame in 'frameq' that has same "frame type" and + * "source name" with 'skb'. + * + * Parameters: + * skb : pointer to sk_buff that contains sightly frame. + * + * Returns: struct sk_buff * + * non NULL : address of appropriate sk_buff. + * NULL : if no such frame exist in frameq. + */ +static struct sk_buff *nbdg_find_such_frame(struct sk_buff *skb) +{ + char source_name[NETBEUI_NAME_LEN]; + dgram_t *hdrp = (dgram_t *)skb->data; + int frame_type = hdrp->command; + struct sk_buff_head *frameq = skb->list; + + memcpy(source_name, hdrp->source_name, NETBEUI_NAME_LEN); + skb = skb->next; + while (skb != (struct sk_buff *)frameq) { + hdrp = (dgram_t *)skb->data; + + if (hdrp->command == frame_type) + if (!memcmp(hdrp->source_name, source_name, + NETBEUI_NAME_LEN)) + return skb; + skb = skb->next; + } + return NULL; +} + +/* + * Function: nbdg_enqueue_name + * Enqueues a name_dgrms structure at begin of 'list' queue. it guards + * code from race conditions by Lock/UnLock 'nbdg_names' structure. + * + * Parameters: + * namep : pointer to name_dgrms structure that must be inserted into + * the list. + * list : pointer to a pointer that points to first member of list. + * + * Returns: none + */ +static void nbdg_enqueue_name(name_dgrms_t *namep, name_dgrms_t **list) +{ + spin_lock_bh(&nbdg_names.lock); + namep->prev = NULL; + namep->next = *list; + *list = namep; + if (namep->next) + namep->next->prev = namep; + namep->list = list; + spin_unlock_bh(&nbdg_names.lock); +} + +/* + * Function: nbdg_dequeue_name + * Dequeues a name_dgrms structure from 'list' queue. it guards code + * from race conditions by Lock/UnLock 'nbdg_names' structure. + * + * Parameters: + * namep : pointer to name_dgrms structure that must be removed from + * its list. + * + * Returns: none + */ +static void nbdg_dequeue_name(name_dgrms_t *namep) +{ + spin_lock_bh(&nbdg_names.lock); + if (namep->next) + namep->next->prev = namep->prev; + if (namep->prev) + namep->prev->next = namep->next; + else + *namep->list = namep->next; + spin_unlock_bh(&nbdg_names.lock); +} + +/* + * Exported NBDG functions + */ +/* + * Function: nbdg_set_dgbc_mtu + * Tunes the 'dgbc_mtu' global variable up to correct value. this function + * is called at begin of protocol stack installation in kernel space, and + * also must be called each time 'netbeui_adapters.dev[]' array altered. + * + * Parameters: none + * + * Returns: none + */ +void nbdg_set_dgbc_mtu(void) +{ + int i, tmp; + + read_lock(&netbeui_adapters.lock); + if (!netbeui_adapters.dev[0]) + goto out; + tmp = netbeui_adapters.dev[0]->mtu; + for (i = 1; i < NETBEUI_MAX_ADAPTERS && netbeui_adapters.dev[i]; i++) + tmp = MIN(tmp, netbeui_adapters.dev[i]->mtu); + dgbc_mtu = tmp - LLCMAC_UIB_HEADLEN() - NETBEUI_UILEN; +out: read_unlock(&netbeui_adapters.lock); +} + +/* + * Function: nbdg_remove_unwanted_dgf + * Removes frames in frame queue that contain up to 'len' bytes of data. + * user program can uses this function by call ioctl() with SIOCRUWDGF + * command. because we have not any mechanism in NetBEUI to recognize + * message boundaries, this is user (program) that recognizes them and + * announce us that Maximum 'len' bytes of remainder data is not + * beneficial and can be removed. 'len' == 0 means that we must remove all + * of such frames from queue. + * + * Parameters: + * namep : pointer to name_dgrms structure that operation perform on its + * frameq. + * len : maximum length which upper layer knows that is not usable. + * + * Returns: int + * 0 : this function always succeed. + */ +int nbdg_remove_unwanted_dgf(name_dgrms_t *namep, int len) +{ + struct sk_buff *skb = namep->curr_skb, *such_skb; + if (!skb) + return 0; /* We are at begin of a message boundary now */ + namep->curr_skb = NULL; + if (len) { + len -= skb->len; + while (len > 0) { + such_skb = nbdg_find_such_frame(skb); + skb_unlink(skb); + kfree_skb(skb); + if (!such_skb) + return 0; + skb = such_skb; + len -= skb->len; + } + } else /* Remove all of such frames */ + while ((such_skb = nbdg_find_such_frame(skb))) { + skb_unlink(skb); + kfree_skb(skb); + skb = such_skb; + } + skb_unlink(skb); + kfree_skb(skb); + return 0; +} + +/* + * Function: nbdg_register_peername + * Registers a remote name for a local name. it causes that received + * frames only from specified remote name be acceptable. broadcasted frames + * will be accepted only if 'remote_name[0]' is equal to '*'. + * + * Parameters: + * namep : pointer to name_dgrms structure that remote name registers + * for it. + * remote_name : pointer to remote name that must be registered. + * + * Returns: none + */ +void nbdg_register_peername(name_dgrms_t *namep, char *remote_name) +{ + if (remote_name[0] == '*') { + if (namep->list != &nbdg_names.star_list) { + nbdg_dequeue_name(namep); + nbdg_enqueue_name(namep, &nbdg_names.star_list); + } + } else + if (namep->list != &nbdg_names.normal_list) { + nbdg_dequeue_name(namep); + nbdg_enqueue_name(namep, &nbdg_names.normal_list); + } + namep->conn_name = remote_name; + namep->connected = 1; +} + +/* + * Function: nbdg_deregister_peername + * Deregisters a registered name for a local name. it causes that received + * frames which are broadcasted or have our name in dest_name field of + * their NetBIOS header, be acceptable. + * + * Parameters: + * namep : pointer to name_dgrms structure that must deregister its + * attached name. + * + * Returns: none + */ +void nbdg_deregister_peername(name_dgrms_t *namep) +{ + if (namep->conn_name[0] == '*') { + nbdg_dequeue_name(namep); + nbdg_enqueue_name(namep, &nbdg_names.normal_list); + } + namep->connected = 0; +} + +/* + * Function: nbdg_add_name + * Creates a name_dgrms structure and adds it to normal_list. + * + * Parameters: + * local_name : pointer to name that must add its structure to normal_list. + * wq : pointer to a pointer that points to dependent wait_queue. + * namep : (VRP) pointer to a pointer buffer that in successful return + * contains address of related name_dgrms structure in list. + * + * Returns: int + * 0 : if operation is performed successfully. + * negative: if a fault occurs. + * -ENOMEM : Out of memory condition. + */ +int nbdg_add_name(char *local_name, wait_queue_head_t *wq, name_dgrms_t **namep) +{ + name_dgrms_t *new = kmalloc(sizeof(name_dgrms_t), GFP_KERNEL); + + if (!new) + return -ENOMEM; + memset(new, 0, sizeof(*new)); + skb_queue_head_init(&new->frameq); + memcpy(new->name, local_name, NETBEUI_NAME_LEN); + new->waitq = wq; + init_waitqueue_head(new->waitq); + nbdg_enqueue_name(new, &nbdg_names.normal_list); + *namep = new; + return 0; +} + +/* + * Function: nbdg_del_name + * Removes a name_dgrms structure from its list. + * + * Parameters: + * namep : pointer to name_dgrms structure that must deleted. + * + * Returns: none + */ +void nbdg_del_name(name_dgrms_t *namep) +{ + spin_lock_bh(&nbdg_names.lock); + if (nbdg_names.obc == namep) + nbdg_names.obc = NULL; + spin_unlock_bh(&nbdg_names.lock); + nbdg_dequeue_name(namep); + skb_queue_purge(&namep->frameq); + kfree(namep); +} + +/* + * Function: nbdg_receive_ready + * Answers to the question "Do in transport layer exist any queued + * received data for this name ?" + * + * Parameters: + * namep : pointer to name_dgrms structure that question is about it. + * + * Returns: int + * 0 : means "OK, exist some data". + * -1 : means "NO, not exist any queued received data as yet". + */ +int nbdg_receive_ready(name_dgrms_t *namep) +{ + return skb_queue_empty(&namep->frameq) ? -1 : 0 /* OK! */; +} + +/* + * Function: nbdg_send + * Sends datagrams to the sightly destination(s). + * + * Parameters: + * local_name : pointer to name that must copied to source_name field of + * NetBIOS header of all sent frames. + * dest_name : pointer to name that must copied to dest_name field of + * NetBIOS header of all sent frames (target name). + * dest_type : type of destination of frames. + * buff : pointer to buffer that contains data that must be sent. + * bufflen : length of data buffer. + * + * Returns: int + * positive : number of bytes that was sent. + * negative : if a fault occurs. + * -ENOMEM: Out of memory condition. + */ +int nbdg_send(struct sock *sk, char *local_name, char *dest_name, + name_type_t dest_type, struct iovec *iov, int len, int noblock) +{ + int rc, + fskbl, + offset = 0, + bytes_put = 0; + dgram_t hdr; + struct sk_buff *skb; + unsigned char *datap; + + if (dest_name[0] == '*') + hdr.command = NETBEUI_DATAGRAM_BROADCAST; + else { + hdr.command = NETBEUI_DATAGRAM; + memcpy(hdr.dest_name, dest_name, NETBEUI_NAME_LEN); + } + hdr.length = NETBEUI_UILEN; + hdr.delimiter = NETBEUI_DELIMITER; + memcpy(hdr.source_name, local_name, NETBEUI_NAME_LEN); + fskbl = CALC_DG_SKBLEN(NETBEUI_MAC_B_HEADLEN, dgbc_mtu + NETBEUI_UILEN); + skb = sock_alloc_send_skb(sk, fskbl, noblock, &rc); + if (!skb) + return -ENOMEM; + skb_reserve(skb, LLCMAC_UIB_HEADLEN()); + memcpy(skb_put(skb, sizeof(hdr)), &hdr, sizeof(hdr)); + + if (len > dgbc_mtu) { + datap = skb_put(skb, dgbc_mtu); + do { + rc = memcpy_fromiovecend(datap, iov, offset, dgbc_mtu); + if (rc) + goto out; + offset += dgbc_mtu; + bytes_put += dgbc_mtu; + len -= dgbc_mtu; + rc = nbll_uisend(NULL, skb); + if (rc) + goto out; + } while (len > dgbc_mtu); /* FIXME: > or >= ? */ + } + if (len) { + skb_trim(skb, sizeof(hdr)); + rc = memcpy_fromiovecend(skb_put(skb, len), iov, offset, len); + if (rc) + goto out; + bytes_put += len; + + rc = nbll_uisend(NULL, skb); + if (rc) + goto out; + } + rc = bytes_put; +out: kfree_skb(skb); + return rc; +} + +/* + * Function: nbdg_receive + * Copies data that received and queued into user data buffer. + * + * Parameters: + * namep : pointer to name_dgrms that we want receive data that + * queued for it. + * source_name : (VRP) pointer to a name buffer. if this parameter is not + * NULL at return the name buffer will be filled with message + * sender name. + * dest_name : (VRP) pointer to a name buffer. if this parameter is not + * NULL at return the name buffer will be filled with message + * destination name. + * buff : (VRP) pointer to data buffer. at return this buffer + * contains data that received. + * bufflen : indicates Maximum no of bytes that user wants to receive. + * nonblock : an integer that if be set to non-zero value means that + * no waiting (sleeping, blocking & ...) acceptable during + * operation. + * + * Returns: int + * positive : no of bytes that was received. + * negative : if a fault occurs. + * -EWOULDBLOCK: user requests non-blocking operation, but + * operation would block. + * -ERESTARTSYS: interrupted system call. + */ +int nbdg_receive(name_dgrms_t *namep, char *source_name, char *dest_name, + char *buff, int bufflen, int nonblock) +{ + int bytes_gotten = 0; + char *datap; + dgram_t *hdrp; + struct sk_buff *skb; + + while (skb_queue_empty(&namep->frameq)) + if (nonblock) + return -EWOULDBLOCK; + else { + interruptible_sleep_on(namep->waitq); + if (signal_pending(current)) + return -ERESTARTSYS; + } + skb = namep->curr_skb; + if (!skb) { + skb = namep->curr_skb = skb_peek(&namep->frameq); + skb->len -= sizeof(dgram_t); + } + hdrp = (dgram_t *)skb->data; + datap = (char *)(skb->tail - skb->len); + if (source_name) + memcpy(source_name, hdrp->source_name, NETBEUI_NAME_LEN); + if (dest_name) { + if (hdrp->command == NETBEUI_DATAGRAM) { + if (copy_to_user(dest_name, hdrp->dest_name, + NETBEUI_NAME_LEN)) + return -EFAULT; + } else + if (put_user('*', dest_name)) + return -EFAULT; + } + while (bufflen) { + int len = MIN(bufflen, skb->len); + + if (copy_to_user(buff, datap, len)) + return -EFAULT; + buff += len; + bufflen -= len; + datap += len; + skb->len -= len; + bytes_gotten += len; + + if (!skb->len) { /* sk_buff copied completely */ + struct sk_buff *such_skb = nbdg_find_such_frame(skb); + + skb_unlink(skb); + kfree_skb(skb); + namep->curr_skb = such_skb; + if (!such_skb) /* No any such frame */ + return bytes_gotten; + skb = such_skb; + hdrp = (dgram_t *)skb->data; + skb->len -= sizeof(dgram_t); + datap = (char *)(hdrp + sizeof(dgram_t)); + } + } + return bytes_gotten; +} + +/* + * Function: nbdg_get_datagram + * Takes a NETBEUI_DATAGRAM frame from 'llc supplementary' and place it on + * appropriate frame queues. + * + * Parameters: + * skb: pointer to sk_buff that contains NETBEUI_DATAGRAM frame. + * + * Returns: none + */ +void nbdg_get_datagram(struct sk_buff *skb) +{ + dgram_t *hdrp; + name_dgrms_t *namep; + + if (!spin_trylock_bh(&nbdg_names.lock)) + goto drop; + /* Place a copy of the skb in frame queue of all star_list's members */ + for (namep = nbdg_names.star_list; namep; namep = namep->next) { + struct sk_buff *new_skb = skb_clone(skb, GFP_ATOMIC); + + if (!new_skb) + continue; + skb_queue_tail(&namep->frameq, new_skb); + wake_up_interruptible(namep->waitq); + } + hdrp = (dgram_t *)skb->data; + + if (nbdg_names.obc && /* If One Behind Cache is not empty and ... */ + !memcmp(nbdg_names.obc->name, hdrp->dest_name, NETBEUI_NAME_LEN)) + namep = nbdg_names.obc; + else { + namep = nbdg_find_name(hdrp->dest_name); + if (!namep) /* No registered name for this sk_buff */ + goto unlock_drop; + nbdg_names.obc = namep; + } + if (namep->connected) + /* To force short circuiting by compiler */ + if (!memcmp(namep->conn_name, hdrp->source_name, + NETBEUI_NAME_LEN)) + /* Not connected to this source_name */ + goto unlock_drop; + /* Now we find the apposite name */ + skb_queue_tail(&namep->frameq, skb); + spin_unlock_bh(&nbdg_names.lock); + wake_up_interruptible(namep->waitq); +out: return; +unlock_drop: + spin_unlock_bh(&nbdg_names.lock); +drop: kfree_skb(skb); + goto out; +} + +/* + * Function: nbdg_get_datagram_broadcast + * Takes a NETBEUI_DATAGRAM_BROADCAST frame from 'llc supplementary' and + * place it on appropriate frame queues. + * + * Parameters: + * skb: pointer to sk_buff that contains NETBEUI_DATAGRAM_BROADCAST frame. + * + * Returns: none + */ +void nbdg_get_datagram_broadcast(struct sk_buff *skb) +{ + name_dgrms_t *namep; + struct sk_buff *new_skb; + + barrier(); + if (!spin_trylock_bh(&nbdg_names.lock)) + goto drop; + /* Place a copy of skb in frame queue of all star_list's members */ + for (namep = nbdg_names.star_list; namep; namep = namep->next) { + new_skb = skb_clone(skb, GFP_ATOMIC); + if (!new_skb) + continue; + skb_queue_tail(&namep->frameq, new_skb); + wake_up_interruptible(namep->waitq); + } + for (namep = nbdg_names.normal_list; namep; namep = namep->next) { + if (namep->connected) + /* To force short circuiting by compiler */ + if (memcmp(namep->conn_name, + ((dgram_t *)skb->data)->source_name, + NETBEUI_NAME_LEN)) + /* Not connected to this source_name */ + continue; + new_skb = skb_clone(skb, GFP_ATOMIC); + if (!new_skb) + continue; + skb_queue_tail(&namep->frameq, new_skb); + wake_up_interruptible(namep->waitq); + } + spin_unlock_bh(&nbdg_names.lock); +drop: kfree_skb(skb); +} Index: kernel-acme/net/netbeui/llc_supp.c diff -u /dev/null kernel-acme/net/netbeui/llc_supp.c:1.1.12.2 --- /dev/null Sat Dec 22 02:21:24 2001 +++ kernel-acme/net/netbeui/llc_supp.c Fri Nov 30 01:54:56 2001 @@ -0,0 +1,1465 @@ +/* + * llc_supp.c - Contains three category of functions + * 1- functions that implement Link Service State Machine + * 2- functions that simplify LLC interface layer services + * 3- dispatching functions + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#define __KERNEL_SYSCALLS__ +#include +#include +#include +#include +#include +#include + +static void nbll_timer_function(unsigned long input); +/* These functions are Link State Transition handlers */ +static int nbll_conn_indicate_in_initial(link_t *nb_link); +static int nbll_conn_request_in_connwait(link_t *nb_link); +static int nbll_dummy_conn_in_initial(link_t *nb_link); +static int nbll_conn_confirm_in_connwait(link_t *nb_link); +static int nbll_conn_indicate_in_connwait(link_t *nb_link); +static int nbll_conn_reject_in_connwait(link_t *nb_link); +static int nbll_disc_request_in_connwait(link_t *nb_link); +static int nbll_reset_indicate_in_up(link_t *nb_link); +static int nbll_session_alive_in_up(link_t *nb_link); +static int nbll_disc_request_in_up(link_t *nb_link); +static int nbll_disc_indicate_in_up(link_t *nb_link); + +static int autobind; +MODULE_PARM(autobind, "i"); +MODULE_PARM_DESC(autobind, "Autobinds all multicast interfaces"); + +/* Contains hardcoded NetBIOS Frame Header length */ +u8 nb_cmd_hdr_len[] = { + 0x2C, 0x2C, 0x2C, 0x2C, 0x00, 0x00, 0x00, 0x2C, + 0x2C, 0x2C, 0x2C, 0x00, 0x00, 0x2C, 0x2C, 0x2C, + 0x00, 0x00, 0x00, 0x2C, 0x0E, 0x0E, 0x0E, 0x0E, + 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x00, 0x00, 0x0E +}; + +/* + * LLC is not re-entrant service to upper layer (NetBEUI) + * This flag, set upon entering LLC code, prevents NetBEUI to re-enter the + * code when its timers fire. + */ +volatile int llc_in_progress = 0; + +/* This is the communication medium between LLC and NetBEUI */ +static struct llc_sap *netbeui_sap; + +/* This is a list of adapters NetBEUI is bound to. */ +struct nb_adapters netbeui_adapters = { + lock: RW_LOCK_UNLOCKED, +}; + +/* LLC links to other network nodes */ +static dextab_t link_table = { + max_size: NETBEUI_MAX_LINKS, + lock: SPIN_LOCK_UNLOCKED +}; + +#define link_table_entry(i) ((link_t *)link_table.addr[i]) + +/* Link service state machine definition */ +typedef int (*link_event_handler_t)(link_t *); + +struct event_struct { + link_state_t next_state; + link_event_handler_t event_handler; +}; + +static struct event_struct link_state_table[3][9] = { + /* NETBEUI_LINK_INITIAL */ +{ +{ NETBEUI_LINK_UP, + nbll_conn_indicate_in_initial }, /* NETBEUI_LINK_CONN_INDICATE */ +{ -1, NULL }, /* NETBEUI_LINK_CONN_REQUEST */ +{ NETBEUI_LINK_CONNWAIT, + nbll_dummy_conn_in_initial }, /* NETBEUI_LINK_DUMMY_CONN */ +{ -1, NULL }, /* NETBEUI_LINK_CONN_CONFIRM */ +{ -1, NULL }, /* NETBEUI_LINK_CONN_REJ */ +{ -1, NULL }, /* NETBEUI_LINK_RESET_INDICATE */ +{ -1, NULL }, /* NETBEUI_LINK_SESSION_ALIVE */ +{ -1, NULL }, /* NETBEUI_LINK_DISC_REQUEST */ +{ -1, NULL } /* NETBEUI_LINK_DISC_INDICATE */ +}, + /* NETBEUI_LINK_CONNWAIT */ +{ +{ NETBEUI_LINK_UP, + nbll_conn_indicate_in_connwait }, /* NETBEUI_LINK_CONN_INDICATE */ +{ NETBEUI_LINK_CONNWAIT, + nbll_conn_request_in_connwait }, /* NETBEUI_LINK_CONN_REQUEST */ +{ -1, NULL }, /* NETBEUI_LINK_DUMMY_CONN */ +{ NETBEUI_LINK_UP, + nbll_conn_confirm_in_connwait }, /* NETBEUI_LINK_CONN_CONFIRM */ +{ NETBEUI_LINK_INITIAL, + nbll_conn_reject_in_connwait }, /* NETBEUI_LINK_CONN_REJ */ +{ -1, NULL }, /* NETBEUI_LINK_RESET_INDICATE */ +{ -1, NULL }, /* NETBEUI_LINK_SESSION_ALIVE */ +{ NETBEUI_LINK_INITIAL, + nbll_disc_request_in_connwait }, /* NETBEUI_LINK_DISC_REQUEST */ +{ -1, NULL } /* NETBEUI_LINK_DISC_INDICATE */ +}, + /* NETBEUI_LINK_UP */ +{ +{ -1, NULL }, /* NETBEUI_LINK_CONN_INDICATE */ +{ -1, NULL }, /* NETBEUI_LINK_CONN_REQUEST */ +{ -1, NULL }, /* NETBEUI_LINK_DUMMY_CONN */ +{ -1, NULL }, /* NETBEUI_LINK_CONN_CONFIRM */ +{ -1, NULL }, /* NETBEUI_LINK_CONN_REJ */ +{ NETBEUI_LINK_UP, + nbll_reset_indicate_in_up }, /* NETBEUI_LINK_RESET_INDICATE */ +{ NETBEUI_LINK_UP, + nbll_session_alive_in_up }, /* NETBEUI_LINK_SESSION_ALIVE */ +{ NETBEUI_LINK_INITIAL, + nbll_disc_request_in_up }, /* NETBEUI_LINK_DISC_REQUEST */ +{ NETBEUI_LINK_INITIAL, + nbll_disc_indicate_in_up } /* NETBEUI_LINK_DISC_INDICATE */ +} +}; +/* + * LLC interface functions + * Data-out functions + */ +/* + * Function: nbll_isend_link + * This is the lowest level LLC interface function in sending and I-Frame + * It prepares a LLC frame structure, considers LLC re-entrancy problems + * and decides on LLC return value to handle many special cases. + * Parameters: + * rdev : pointer to struct net_device or adapter the frame is sent to + * This parameter is designed to minimize critical regions + * llc_handle: LLC handle of remote machine (is a pointer to LLC data) + * skb : the pointer to sk_buff containing data to send + * qflag : queuing flag. NetBEUI links control flow of data to LLC + * layer using a skb queue. Depending on the situation we + * are in, an unsuccessful try in delivering frame to LLC + * should queue the frame for later trials. This flag controls + * how this function should queue the skb. + * 0 : queue unsuccessful skb in tail and return 0 + * other: queue unsuccessful skb in head and return + * non-zero + * Returns: + * 0 : if LLC accepts the frame or frame is queue in Link for + * later trial + * qflag<> 0 : if queues frame for later trial + * non-zero : any other error value returned by LLC + * Notes: + * - Any modification to this function highly affects the whole system + * + * - A special race condition is an interrupt occurred when LLC returns + * from sap_request to NetBEUI. To cover it a critical region is created + * before LLC return statement in LLC code and is destroyed after + * sap_request statement in NetBEUI code. This is why you may see + * wonderful save and restore flag calls in the code. + * + * acme: with all the locking changes I think that this race is gone + * so, for now I'll get rid of all this 'wonderful' save and restore + */ +static int nbll_isend_link(struct net_device *rdev, struct sock *llc_handle, + struct sk_buff *skb, unsigned char link, + int qflag) +{ + union llc_u_prim_data prim_data; + struct llc_prim_if_block prim; + int rc; + + prim.data = &prim_data; + skb->protocol = htons(ETH_P_802_2); + if (!memcmp(rdev->name, "tr", 2)) + skb->protocol = htons(ETH_P_TR_802_2); + skb->dev = rdev; + skb->mac.raw = skb->head; + prim_data.data.pri = 0; + prim_data.data.sk = llc_handle; + prim_data.data.skb = skb; + prim.sap = netbeui_sap; + prim.prim = LLC_DATA_PRIM; +restart: + llc_in_progress = 1; + barrier(); + rc = netbeui_sap->req(&prim); + llc_in_progress = 0; + barrier(); + switch (rc) { + case 0: + goto out; + case -ERESTART: + goto restart; + case -EBUSY: { + link_t *nb_link = link_table_entry(link); + + if (!nb_link) { + kfree_skb(skb); + rc = -ECONNABORTED; + goto out; + } + nb_link->llc_busy = 1; + if (!qflag) + __skb_queue_tail(&nb_link->skbq, skb); + else + __skb_queue_head(&nb_link->skbq, skb); + rc = qflag; + goto out; + } + } + kfree_skb(skb); +out: return rc; +} + +/* + * Function: nbll_free_link + * Does a complete housekeeping for a link including queue/table/... + * Parameters: + * nb_link : pointer to link_t to destruct + * Returns: none + */ +static inline void nbll_free_link(link_t *nb_link) +{ + skb_queue_purge(&nb_link->skbq); + dextab_destruct(&nb_link->session_table); + kfree(nb_link); +} + +/* used by session_serve.c as well, so cannot be static */ +inline void nbll_link_put(link_t *nb_link) +{ + if (atomic_dec_and_test(&nb_link->refcnt)) + nbll_free_link(nb_link); +} + +static inline void nbll_link_hold(link_t *nb_link) +{ + atomic_inc(&nb_link->refcnt); +} + +/** + * nbll_isend - sends I-Frames on a LLC connection + * @link: An integer containing link number in link table + * @skb: pointer to sk_buff containing data to send + * + * This is the interface routine that actually tries to send I-Frames + * on an LLC connection. + * Returns: + * 0: if LLC accepts frame or it is queued for later trial + * -ECONNABORTED: If connection is aborted by remote peer + * -ENOMEM : If cannot allocate a skb + * non-zero: any other error value returned by LLC + * Notes: + * - Since I intended to call this function freely in upper layer codes, + * it contains a critical region checking LINK consistency + */ +int nbll_isend(int link, struct sk_buff *skb) +{ + link_t *nb_link = NULL; + struct net_device *link_dev; + struct sock *link_llc_handle; + int rc = -EINVAL; + + spin_lock_bh(&link_table.lock); + if (link > link_table.count) { + spin_unlock_bh(&link_table.lock); + goto freeskb; + } + nb_link = link_table_entry(link); + rc = -ECONNABORTED; + if (!nb_link) { + spin_unlock(&link_table.lock); + goto freeskb; + } + nbll_link_hold(nb_link); + spin_unlock_bh(&link_table.lock); + rc = 0; + if (nb_link->llc_busy == 1) { + __skb_queue_tail(&nb_link->skbq, skb); + goto out; + } + nb_link->iactivity++; + link_dev = nb_link->dev; + link_llc_handle = nb_link->llc_handle; + rc = nbll_isend_link(link_dev, link_llc_handle, skb, link, 0); +out: nbll_link_put(nb_link); + return rc; +freeskb: + kfree_skb(skb); + goto out; +} + +/* + * Function: nbll_uisend_mac + * This is the lowest level LLC interface function in sending and UI-Frame + * Parameters: + * remote_mac: pointer to MAC address of destination node or NetBIOS + * functional address of device the frame is sent to. + * skb : pointer to sk_buff containing data to send + * Returns: + * 0 : if LLC accepts frame + * -ENOMEM : If cannot allocate a skb + * non-zero: any other error value returned by LLC + */ +static int nbll_uisend_mac(unsigned char *remote_mac, struct sk_buff *skb) +{ + union llc_u_prim_data prim_data; + struct llc_prim_if_block prim; + + prim.data = &prim_data; + skb->protocol = htons(ETH_P_802_2); + if (!memcmp(skb->dev->name, "tr", 2)) + skb->protocol = htons(ETH_P_TR_802_2); + + prim_data.udata.saddr.lsap = LLC_SAP_NETBEUI; + memcpy(prim_data.udata.saddr.mac, skb->dev->dev_addr, + skb->dev->addr_len); + prim_data.udata.daddr.lsap = LLC_SAP_NETBEUI; + memcpy(prim_data.udata.daddr.mac, remote_mac, skb->dev->addr_len); + prim_data.udata.skb = skb; + prim.sap = netbeui_sap; + prim.prim = LLC_DATAUNIT_PRIM; + return netbeui_sap->req(&prim); +} + +/* + * Function: nbll_uisend + * This is the interface routine that actually tries to send UI-Frames + * on an LLC connection. + * Parameters: + * remote_mac: pointer to MAC address of destination system or NULL + * to indicate broadcast to all NICs NetBEUI is bound to + * skb : pointer to sk_buff containing data to send + * Returns: + * 0 : if LLC accepts frame + * -ENOMEM : If cannot allocate a skb + * or cannot create a copy from skb. + * non-zero: any other error value returned by LLC + */ +int nbll_uisend(unsigned char *remote_mac, struct sk_buff *skb) +{ + int i, rc = -ENOMEM; + + /* If datagram has a destination */ + if (remote_mac) { + rc = nbll_uisend_mac(remote_mac, skb); + goto out; + } + /* Datagram is to be broadcasted to all interfaces */ + read_lock(&netbeui_adapters.lock); + for (i = 0; i < NETBEUI_MAX_ADAPTERS && netbeui_adapters.dev[i]; i++) { + struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); + + if (!skb2) + goto out; + skb2->dev = netbeui_adapters.dev[i]; + nbll_uisend_mac(netbeui_funcaddr(skb2->dev), skb2); + } + rc = 0; +out: read_unlock(&netbeui_adapters.lock); + return rc; +} + +/* + * Link service state machine functions + * Implementing general functions + */ +/* + * Function: nbll_alloc_link + * Allocates and Initializes a link_t structure + * Parameters: none + * Returns: + * NULL : if can not allocate link_t structure + * non-NULL: if link_t is allocated and initialized + * Note: + * - Link timer is initialized but not started + * - The call to memset does implicitly initialize all fields. Those + * fields that need explicit non-zero initialization are manipulated + * afterwards. + */ +static link_t *nbll_alloc_link(void) +{ + link_t *nb_link = kmalloc(sizeof(*nb_link), GFP_ATOMIC); + + if (!nb_link) + goto out; + /* Implicitly initialize all fields */ + memset(nb_link, 0, sizeof(*nb_link)); + nb_link->state = NETBEUI_LINK_INITIAL; + nb_link->link = -1; + dextab_init(&nb_link->session_table, 1, NETBEUI_MAX_SESSIONS); + skb_queue_head_init(&nb_link->skbq); + init_waitqueue_head(&nb_link->waitq); + init_timer(&nb_link->timer); + nb_link->timer.data = (unsigned long)nb_link; + nb_link->timer.function = nbll_timer_function; + atomic_set(&nb_link->refcnt, 1); +out: return nb_link; +} + +/* + * Function: nbll_insert_link_into_table + * Inserts a previously allocated/initialized link into system link table + * Parameters: + * nb_link : pointer to link_t to insert + * Returns: none + * 0 : if nb_link is inserted into system link_table + * -ENOSPC : if link_table is full + */ +static int nbll_insert_link_into_table(link_t *nb_link) +{ + int link; + int rc = 0; + + nbll_link_hold(nb_link); + link = dextab_insert_entry(&link_table, nb_link); + if (link < 0) + rc = -ENOSPC; + else + nb_link->link = link; + nbll_link_put(nb_link); + return rc; +} + +/* + * Function: nbll_delete_link_from_table + * Deletes a link from system link table + * Parameters: + * nb_link : pointer to link_t to delete + * Returns: none + */ +static void nbll_delete_link_from_table(link_t *nb_link) +{ + nbll_link_hold(nb_link); + dextab_delete_index(&link_table, nb_link->link); + nb_link->link = -1; + nbll_link_put(nb_link); +} + +/* + * Function: nbll_find_link + * Finds a link in system link table to a remote node from its mac and + * the device we are connected via + * Parameters: + * dev : pointer to struct net_device we are connected to remote + * node via + * remote_mac: pointer to MAC address of remote node we are connected to + * Returns: + * NULL : if a corresponding link is not found + * non-NULL : the link_t address of corresponding link + */ +static link_t *nbll_find_link(struct net_device *dev, unsigned char *remote_mac) +{ + int index; + link_t *nb_link = NULL; + + spin_lock(&link_table.lock); + for (index = link_table.reserved; index < link_table.size; index++) { + nb_link = link_table_entry(index); + if (nb_link && nb_link->dev == dev && + !memcmp(nb_link->remote_mac, remote_mac, dev->addr_len)) + break; + } + if (nb_link) + nbll_link_hold(nb_link); + spin_unlock(&link_table.lock); + return nb_link; +} + +/* + * Function: nbll_request_llc_connect + * Prepares and sends a connection request to LLC layer. + * Parameters: + * nb_link : pointer to link_t structure prepared for this new connection + * A NetBEUI link_t is the counterpart of LLC connection struct. + * Returns: + * 0 : LLC accepted connection request + * non-zero: LLC rejected connection request + */ +static int nbll_request_llc_connect(link_t *nb_link) +{ + struct net_device *dev; + struct llc_prim_if_block prim; + union llc_u_prim_data prim_data; + int rc; + + nbll_link_hold(nb_link); + dev = nb_link->dev; + prim.data = &prim_data; + prim_data.conn.saddr.lsap = LLC_SAP_NETBEUI; + memcpy(prim_data.conn.saddr.mac, dev->dev_addr, dev->addr_len); + prim_data.conn.daddr.lsap = LLC_SAP_NETBEUI; + memcpy(prim_data.conn.daddr.mac, nb_link->remote_mac, + dev->addr_len); + prim_data.conn.dev = dev; + prim_data.conn.link = nb_link->link; + prim_data.conn.sk = NULL; + prim_data.conn.pri = 0; + prim.prim = LLC_CONN_PRIM; + prim.sap = netbeui_sap; + rc = netbeui_sap->req(&prim); + nbll_link_put(nb_link); + return rc; +} + +/* + * Function: nbll_request_llc_disconnect + * Prepares and sends a disconnection request to LLC layer. + * Parameters: + * nb_link : pointer to link_t structure responsible for this connection + * A NetBEUI link_t is the counterpart of LLC connection struct. + * Returns: + * 0 : LLC accepted disconnection request + * non-zero: LLC rejected disconnection request + * Note: + * - Currently LLC always accepts disconnection request. + */ +static int nbll_request_llc_disconnect(link_t *nb_link) +{ + struct llc_prim_if_block prim; + union llc_u_prim_data prim_data; + int rc; + + nbll_link_hold(nb_link); + prim.data = &prim_data; + prim_data.disc.sk = nb_link->llc_handle; + prim.prim = LLC_DISC_PRIM; + prim.sap = netbeui_sap; + rc = netbeui_sap->req(&prim); + nbll_link_put(nb_link); + return rc; +} + +/* + * Function: nbll_isend_session_alive + * Prepares a NetBIOS SESSION ALIVE frame and nbll_isends it to link + * Parameters: + * nb_link: pointer to link_t structure to send SESSION ALIVE to + * Returns: None + */ +static void nbll_isend_session_alive(link_t *nb_link) +{ + packet_t *hdr; + int llcmac_ihl, + session_packet_len = nb_cmd_hdr_len[NETBEUI_SESSION_ALIVE]; + struct sk_buff *skb; + + nbll_link_hold(nb_link); + llcmac_ihl = LLCMAC_I_HEADLEN(nb_link->dev); + skb = alloc_skb((session_packet_len + llcmac_ihl), GFP_ATOMIC); + if (!skb) + goto out; + skb_reserve(skb, llcmac_ihl); + skb->nh.raw = skb->h.raw = skb->data; + hdr = (packet_t *)skb_put(skb, session_packet_len); + hdr->length = session_packet_len; + hdr->delimiter = NETBEUI_DELIMITER; + hdr->command = NETBEUI_SESSION_ALIVE; + hdr->data1 = 0; + hdr->data2 = 0; + hdr->xmit_correlator = 0; + hdr->resp_correlator = 0; + hdr->dest_num = 0; + hdr->source_num = 0; + nbll_isend(nb_link->link, skb); +out: nbll_link_put(nb_link); +} + +/* + * Function: nbll_handle_event + * This is the heart of Link Service State Machine, which performs a + * transition from current state of link element to new state based + * on event occurred and link state table contents. + * Parameters: + * event : An integer of NETBEUI_LINK_* family that implies type of event + * nb_link : pointer to link_t structure which the event occurred on + * Returns: none + * Notes: + * - The state changes before actions be executed. This is due to + * non deterministic behavior of actions which may sleep the current + * process, thus stopping the function in the mid-way. + */ +static void nbll_handle_event(link_event_t event, link_t *nb_link) +{ + struct event_struct *ev; + + nbll_link_hold(nb_link); + ev = &link_state_table[nb_link->state][event]; + if (ev && ev->event_handler) { + link_state_t old_state = nb_link->state; + + nb_link->state = ev->next_state; + if (ev->event_handler(nb_link)) + nb_link->state = old_state; + } + nbll_link_put(nb_link); +} + +/* + * Function: nbll_timer_function + * This is the callback function triggered upon expiration of link + * inactivity timer. It just injects an event into state machine for + * its link. + * Parameters: + * input : pointer to link_t structure whose timer is expired. + * Returns: none + */ +static void nbll_timer_function(unsigned long input) +{ + link_t *nb_link = (link_t *)input; + + nbll_link_hold(nb_link); + nbll_handle_event(NETBEUI_LINK_SESSION_ALIVE, nb_link); + nbll_link_put(nb_link); +} + +/* + * Link service state machine functions + * Implementing transition functions + */ +/* + * Function: nbll_xxxx_in_ssss + * The section below contains functions that implement actions needed + * to legally transit from one state to another. + * Parameters: + * nb_link : pointer to link_t structure which the actions are to be + * applied to + * Returns: + * 0 : if all actions are done successfully + * non-zero: if one of actions failed + * Note: + * - For the sake of simplicity, the actions are automatically rollbacked + * in each function, if an action in transition fails. The design + * documents do not cover these parts of code. + */ +static int nbll_conn_indicate_in_initial(link_t *nb_link) +{ + int rc; + + nbll_link_hold(nb_link); + nb_link->status = nbll_insert_link_into_table(nb_link); + if (!nb_link->status) { + nb_link->timer.expires = jiffies + NETBEUI_INACTIVITY_TIMEOUT; + add_timer(&nb_link->timer); + } + rc = nb_link->status; + nbll_link_put(nb_link); + return rc; +} + +static int nbll_conn_request_in_connwait(link_t *nb_link) +{ + int rc = -1; + + nbll_link_hold(nb_link); + if (nbll_request_llc_connect(nb_link)) + goto out; + wait_event(nb_link->waitq, nb_link->state != NETBEUI_LINK_CONNWAIT); + rc = 0; +out: nbll_link_put(nb_link); + return rc; +} + +static int nbll_dummy_conn_in_initial(link_t *nb_link) +{ + int rc; + + nbll_link_hold(nb_link); + rc = nbll_insert_link_into_table(nb_link); + nbll_link_put(nb_link); + return rc; +} + +static int nbll_conn_confirm_in_connwait(link_t *nb_link) +{ + nbll_link_hold(nb_link); + nb_link->timer.expires = jiffies + NETBEUI_INACTIVITY_TIMEOUT; + add_timer(&nb_link->timer); + nb_link->status = 0; + wake_up(&nb_link->waitq); + nbll_link_put(nb_link); + return 0; +} + +static int nbll_conn_indicate_in_connwait(link_t *nb_link) +{ + nbll_link_hold(nb_link); + nb_link->timer.expires = jiffies + NETBEUI_INACTIVITY_TIMEOUT; + add_timer(&nb_link->timer); + nbll_link_put(nb_link); + return 0; +} + +static int nbll_conn_reject_in_connwait(link_t *nb_link) +{ + nbll_link_hold(nb_link); + nbll_delete_link_from_table(nb_link); + nb_link->status = -ECONNREFUSED; + wake_up(&nb_link->waitq); + nbll_link_put(nb_link); + return 0; +} + +static int nbll_disc_request_in_connwait(link_t *nb_link) +{ + nbll_link_hold(nb_link); + nbll_delete_link_from_table(nb_link); + nbll_link_put(nb_link); + return 0; +} + +static int nbll_reset_indicate_in_up(link_t *nb_link) +{ + int index; + + nbll_link_hold(nb_link); + for (index = nb_link->session_table.reserved; + index < nb_link->session_table.size; index++) { + session_t *session = (session_t *) + nb_link->session_table.addr[index]; + if (session) { + nbss_abort_session(session); + dextab_delete_index(&nb_link->session_table, + session->lsn); + } + } + del_timer(&nb_link->timer); + nb_link->iactivity = 0; + nb_link->timer.expires = jiffies + NETBEUI_INACTIVITY_TIMEOUT; + add_timer(&nb_link->timer); + nbll_link_put(nb_link); + return 0; +} + +static int nbll_session_alive_in_up(link_t *nb_link) +{ + nbll_link_hold(nb_link); + if (!nb_link->iactivity) + nbll_isend_session_alive(nb_link); + nb_link->iactivity = 0; + nb_link->timer.expires = jiffies + NETBEUI_INACTIVITY_TIMEOUT; + add_timer(&nb_link->timer); + nbll_link_put(nb_link); + return 0; +} + +static int nbll_disc_request_in_up(link_t *nb_link) +{ + nbll_link_hold(nb_link); + del_timer(&nb_link->timer); + nbll_request_llc_disconnect(nb_link); + nbll_delete_link_from_table(nb_link); + nbll_link_put(nb_link); + return 0; +} + +static int nbll_disc_indicate_in_up(link_t *nb_link) +{ + int index; + + nbll_link_hold(nb_link); + del_timer(&nb_link->timer); + + for (index = nb_link->session_table.reserved; + index < nb_link->session_table.size; index++) { + session_t *session = (session_t *) + nb_link->session_table.addr[index]; + if (session) { + nbss_abort_session(session); + dextab_delete_index(&nb_link->session_table, + session->lsn); + } + } + dextab_destruct(&nb_link->session_table); + nbll_delete_link_from_table(nb_link); + nbll_link_put(nb_link); + return 0; +} + +/* + * Link service state machine functions + * Implementing interface functions + */ +/* + * Function: get_disconnect_indicate + * Accepts a connection indication from LLC layer. If it can establish + * a link anyway, generates an event on link element, otherwise requests + * LLC to disconnect (! this is LLC rule) + * Parameters: + * prim: pointer to primary interface block type, the LLC communication + * data structure. This is a union with different fields with + * different meaning for different purposes. + * Returns: none + */ +static void nbll_get_connect_indicate(struct llc_prim_if_block *prim) +{ + struct llc_prim_conn *prim_data = &prim->data->conn; + link_t *nb_link = nbll_find_link(prim_data->dev, prim_data->saddr.mac); + + if (!nb_link) { + nb_link = nbll_alloc_link(); + if (nb_link) + nbll_link_hold(nb_link); + } + if (nb_link) { + nb_link->llc_handle = prim_data->sk; + nb_link->dev = prim_data->dev; + memcpy(nb_link->remote_mac, prim_data->saddr.mac, + nb_link->dev->addr_len); + nbll_handle_event(NETBEUI_LINK_CONN_INDICATE, nb_link); + } + if (!nb_link || nb_link->state == NETBEUI_LINK_INITIAL) { + /* Request link disconnection */ + prim->data->disc.sk = prim_data->sk; + prim->prim = LLC_DISC_PRIM; + prim->sap = netbeui_sap; + netbeui_sap->req(prim); + if (nb_link) + nbll_link_put(nb_link); + } else { + prim->prim = LLC_CONN_PRIM; + prim->sap = netbeui_sap; + prim_data->link = nb_link->link; + netbeui_sap->resp(prim); + } + if (nb_link) + nbll_link_put(nb_link); +} + +/* + * Function: nbll_get_connect_confirm + * Accepts a connection confirm for a previously requested connection from + * LLC layer. The LLC may confirm a connection request positively or + * negatively. + * Parameters: + * prim : pointer to primary interface block type, the LLC communication + * data structure. This is a union with different fields with + * different meaning for different purposes. + * Returns: none + */ +static void nbll_get_connect_confirm(struct llc_prim_if_block *prim) +{ + struct llc_prim_conn *prim_data = &prim->data->conn; + link_t *nb_link = link_table_entry(prim_data->link); + + nbll_link_hold(nb_link); + if (prim_data->status == LLC_STATUS_CONN) { + nb_link->llc_handle = prim_data->sk; + nbll_handle_event(NETBEUI_LINK_CONN_CONFIRM, nb_link); + } else + nbll_handle_event(NETBEUI_LINK_CONN_REJ, nb_link); + nbll_link_put(nb_link); +} + +/* + * Function: nbll_get_data_confirm + * Accepts a data confirm from LLC layer, according to a -EBUSY return + * value on latest try to send I-Frame to a LLC connection. This primitive + * informs NetBEUI to flush its link queue to LLC connection. + * Parameters: + * prim: pointer to primary interface block type, the LLC communication + * data structure. This is a union with different fields with + * different meaning for different purposes. + * Returns: + * 0 : if all queue contents are flushed successfully. + * non-Zero: if LLC does not accept all entries and queue has more entries + * to flush. + * Note: + * - Since this function is raised via LLC, the return value has special + * meaning to both NetBEUI and LLC to sync their flags. The llc_busy + * flag in NetBEUI link demonstrates existence of skbs in link queue + * ready to send to LLC layer. + */ +static int nbll_get_data_confirm(struct llc_prim_if_block *prim) +{ + struct llc_prim_data *prim_data = &prim->data->data; + link_t *nb_link = link_table_entry(prim_data->link); + struct sk_buff *skb; + int rc = -EBUSY; + + printk(KERN_INFO __FUNCTION__ ": enter\n"); + nbll_link_hold(nb_link); + while ((skb = __skb_dequeue(&nb_link->skbq)) != NULL) + if (nbll_isend_link(nb_link->dev, nb_link->llc_handle, + skb, prim_data->link, 1) == 1) + goto out; + rc = nb_link->llc_busy = 0; +out: nbll_link_put(nb_link); + return rc; +} + +/* + * Function: nbll_get_disconnect_indicate + * Accepts a disconnection indication for a connection from LLC layer. + * Parameters: + * prim: pointer to primary interface block type, the LLC communication + * data structure. This is a union with different fields with + * different meaning for different purposes. + * Returns: none + */ +static void nbll_get_disconnect_indicate(struct llc_prim_if_block *prim) +{ + link_t *nb_link = link_table_entry(prim->data->disc.link); + nbll_link_hold(nb_link); + nbll_handle_event(NETBEUI_LINK_DISC_INDICATE, nb_link); + nbll_link_put(nb_link); + nbll_link_put(nb_link); +} + +/* + * Function: nbll_get_disconnect_confirm + * Accepts a disconnection confirm for a previous disconnect request, from + * LLC layer. + * Parameters: + * prim: pointer to primary interface block type, the LLC communication + * data structure. This is a union with different fields with + * different meaning for different purposes. + * Returns: none + * Note: + * - Currently LLC does not generate a disconnection confirm. Both NetBEUI + * and LLC assume that a disconnection request is always satisfied. + */ +static void nbll_get_disconnect_confirm(struct llc_prim_if_block *prim) +{ + /* Nothing to do, we do not wait for disconnection confirmation */ +} + +/* + * Function: nbll_get_reset_indicate + * Accepts a reset indication for a connection from LLC layer. + * Parameters: + * prim: pointer to primary interface block type, the LLC communication + * data structure. This is a union with different fields with + * different meaning for different purposes. + * Returns: none + * Note: + * - LLC reset indication means close all sessions on link and reset + * link parameters. Just the link itself remains UP and RUNNING. + */ +static void nbll_get_reset_indicate(struct llc_prim_if_block *prim) +{ + link_t *nb_link = link_table_entry(prim->data->res.link); + + nbll_link_hold(nb_link); + nbll_handle_event(NETBEUI_LINK_RESET_INDICATE, nb_link); + nb_link->llc_busy = 0; + nb_link->iactivity = 0; + skb_queue_purge(&nb_link->skbq); + nbll_link_put(nb_link); +} + +/* + * Function: get_link_table + * returns a pointer to NetBEUI link table. The proc support code uses + * the link table to map its contents to /proc/sys/netbeui entry. + * Parameters: none + * Returns: + * non-NULL: pointer to NetBEUI link table + */ +dextab_t *nbll_get_link_table(void) +{ + return &link_table; +} + +link_t *nbll_get_link(int link) +{ + link_t *nb_link = NULL; + + spin_lock(&link_table.lock); + if (link <= link_table.size) + nb_link = link_table_entry(link); + if (nb_link) + nbll_link_hold(nb_link); + spin_unlock(&link_table.lock); + return nb_link; +} + +/* + * Function: nbll_attach_session + * This is a sophisticated interface to session service module, which + * attaches (links) a session to a link. Depending on the existence and + * state of the link, it interacts with LLC and manipulates link session + * table to content the request. + * Parameters: + * session : pointer to session_t structure to add to session table of + * link + * dev : pointer to device structure the link to remote node is on + * remote_mac: pointer to MAC address of remote node the link is to + * Returns: + * 0 : if session is successfully added to link session table + * -ENOSPC : if link session table has no space to add session + * -ENOMEM : if can not allocate memory for creating new link + * -EHOSTUNREACH: if LLC connection request for a new link failed. + */ +int nbll_attach_session(session_t *session, struct net_device *dev, + unsigned char *remote_mac) +{ + link_t *nb_link = nbll_find_link(dev, remote_mac); + int session_no; + int rc; + + /* If a link exists previously and is up or requested within an + interrupt */ + if (nb_link) { + session_no = dextab_insert_entry(&nb_link->session_table, + session); + rc = -ENOSPC; + if (session_no < 0) + goto plink; + session = (session_t *)nb_link->session_table.addr[session_no]; + session->link = nb_link->link; + session->lsn = session_no; + rc = 0; + goto plink; + } + /* Request for link (dummy) */ + nb_link = nbll_alloc_link(); + rc = -ENOMEM; + if (!nb_link) + goto out; + nbll_link_hold(nb_link); + nb_link->llc_handle = 0; + nb_link->dev = dev; + memcpy(nb_link->remote_mac, remote_mac, dev->addr_len); + nbll_handle_event(NETBEUI_LINK_DUMMY_CONN, nb_link); + rc = -EHOSTUNREACH; + if (nb_link->state == NETBEUI_LINK_INITIAL) { + nbll_link_put(nb_link); + goto plink; + } + rc = nbll_attach_session(session, dev, remote_mac); +plink: nbll_link_put(nb_link); +out: return rc; +} + +/* + * Function: nbll_link_session + * This is a joke !!!!! + * NetBEUI connection request has two steps NAME QUERY and LLC CONNECTION + * establishment. To overcome some traditional limits in total session + * count new implementations add a NAME FIND step before the other two + * steps, thus letting the other two be used interchangeably. + * Unfortunately Microsoft implementations force using NAME QUERY before + * LLC CONNECTION. To overcome the problem we first put a link into + * CONNWAIT, attach a session to it and first issue NAME QUERY then + * request LLC CONNECTION. This function does the actual LLC connection + * request on the dummy link. + * Parameters: + * link : an integer representing link number in link table + * Returns: + * 0 : if dummy link is now established successfully. + * -ECONNRESET : if dummy link is reset + * -EHOSTUNREACH: if LLC connection establishment failed. + */ +int nbll_link_session(int link) +{ + link_t *nb_link; + int rc = -ECONNRESET; + + spin_lock(&link_table.lock); + nb_link = link_table_entry(link); + if (!nb_link) { + spin_unlock(&link_table.lock); + goto out; + } + nbll_link_hold(nb_link); + spin_unlock(&link_table.lock); + nbll_handle_event(NETBEUI_LINK_CONN_REQUEST, nb_link); + rc = -EHOSTUNREACH; + if (nb_link->state == NETBEUI_LINK_INITIAL) { + nbll_link_put(nb_link); + goto plink; + } + rc = 0; +plink: nbll_link_put(nb_link); +out: return rc; +} + +/* + * Function: nbll_detach_session + * Detaches a session from its link session table. If the session was the + * last session link, it tries to drop the link to free resources. + * Parameters: + * link : an integer representing link number in link table + * session_no: an integer representing session number in link session table + * Returns: none + */ +void nbll_detach_session(int link, unsigned char session_no) +{ + session_t *session; + link_t *nb_link; + + spin_lock(&link_table.lock); + nb_link = link_table_entry(link); + if (!nb_link) { + spin_unlock(&link_table.lock); + goto out; + } + nbll_link_hold(nb_link); + spin_unlock(&link_table.lock); + session = (session_t *)nb_link->session_table.addr[session_no]; + if (session) + session->lsn = 0; + __dextab_delete_index(&nb_link->session_table, session_no); + if (dextab_count_entries(&nb_link->session_table) > 0) + goto plink; + nbll_handle_event(NETBEUI_LINK_DISC_REQUEST, nb_link); + nbll_link_put(nb_link); +plink: nbll_link_put(nb_link); +out:; +} + +/* + * Function: nbll_drop_link + * Drops a specified link with its sessions. + * Parameters: + * link: an integer representing link number in link table. + * Returns: int + * zero : if the link dropped successfully. + * negative: if operation fails. + * -EINVAL: the link number is invalid. + * Notes: + * - Only called from user context, in config.c, ioctl path + */ +int nbll_drop_link(int link) +{ + link_t *nb_link = nbll_get_link(link); + dextab_t *sn_tbl; + int i, sn_cnt, rc = -EINVAL; + + if (!nb_link) /* Invalid link number */ + goto out; + sn_tbl = &nb_link->session_table; + spin_lock_bh(&sn_tbl->lock); + rc = 0; + sn_cnt = sn_tbl->count; + for (i = sn_tbl->reserved; sn_cnt; i++) { + session_t *sn = sn_tbl->addr[i]; + + if (sn) { + nbll_detach_session(link, i); + nbss_abort_session(sn); + sn_cnt--; + } + } + spin_unlock_bh(&sn_tbl->lock); + nbll_link_put(nb_link); +out: return rc; +} + +/* + * LLC interface functions + * Data-in functions + */ +/* + * Function: nbll_disconnect_all_links + * Generates disconnection event on all NetBEUI links. + * Parameters: none + * Returns: none + */ +static void nbll_disconnect_all_links(void) +{ + int index; + link_t *nb_link; + + spin_lock(&link_table.lock); + for (index = link_table.reserved; index < link_table.size; index++) { + nb_link = link_table_entry(index); + spin_unlock(&link_table.lock); + if (nb_link) { + nbll_handle_event(NETBEUI_LINK_DISC_REQUEST, nb_link); + nbll_link_put(nb_link); + } + spin_lock(&link_table.lock); + } + spin_unlock(&link_table.lock); +} + +/* + * Function: nbll_deliver_packet + * While checking input I-Frame consistency, routes frame to session + * service interface. Since manipulating I-Frames is always the + * responsibility of session service, the dispatching mechanism is + * implemented there. + * Parameters: + * skb : sk_buff which holds actual data + * prim_data: pointer to LLC primitive data description. + * Returns: none + * Notes: + * - Imagine struct llc_prim_if_block is the function that LLC calls in + * NetBEUI code and union llc_u_prim_data as argument to this function. + * - This function is a barrier for ill frames with anomalous content. + */ +static void nbll_deliver_packet(struct sk_buff *skb, + struct llc_prim_data *prim_data) +{ + int command = ((packet_t *)(skb->data))->command; + link_t *nb_link = link_table_entry(prim_data->link); + session_t *session; + + nbll_link_hold(nb_link); + /* Sanity check if command length and code is valid, all checks should + * be done! */ + /* It checks ill netbios headers, and prevents memory faults */ + if (skb->len < NETBEUI_MIN_COMMAND_LEN || + command > NETBEUI_MAX_COMMAND_CODE || + skb->len < nb_cmd_hdr_len[command] || + ((packet_t *)skb->data)->delimiter != NETBEUI_DELIMITER || + ((packet_t *)skb->data)->dest_num >= nb_link->session_table.size) + goto err; + nb_link->iactivity++; + session = (session_t *) + nb_link->session_table.addr[((packet_t *)skb->data)->dest_num]; + if (!session || command == NETBEUI_SESSION_ALIVE) + goto err; + nbss_deliver_frame(session, skb); +out: nbll_link_put(nb_link); + return; +err: kfree_skb(skb); + goto out; +} + +/* + * Function: nbll_deliver_datagram + * The UI-Frame dispatcher + * While checking input UI-Frame consistency, routes frame to final + * destination in name service, session service and datagram distribution. + * Due to different destinations the dispatching mechanism for UI-Frames is + * implemented here in this function. + * Parameters: + * skb : sk_buff which holds actual data + * prim_data: pointer to LLC primitive data description. + * Returns: none + */ +static void nbll_deliver_datagram(struct sk_buff *skb, + struct llc_prim_unit_data *prim_data) +{ + int command = ((dgram_t *)(skb->data))->command; + + /* Sanity check if command length and code is valid, all checks + * should be done !!! */ + /* It checks ill netbios headers, and prevents memory faults */ + if (skb->len < NETBEUI_MIN_COMMAND_LEN || + command > NETBEUI_MAX_COMMAND_CODE || + skb->len < nb_cmd_hdr_len[command] || + ((dgram_t *)skb->data)->delimiter != NETBEUI_DELIMITER) + goto fskb; + /* Token Ring support */ + skb->cb[0] = prim_data->lfb; + + switch (command) { + case NETBEUI_ADD_GROUP_NAME_QUERY: + nbns_get_add_name_query(skb, prim_data->saddr.mac, + NETBEUI_NAME_GROUP); + break; + case NETBEUI_ADD_NAME_QUERY: + nbns_get_add_name_query(skb, prim_data->saddr.mac, + NETBEUI_NAME_UNIQUE); + break; + case NETBEUI_ADD_NAME_RESPONSE: + nbns_get_add_name_response(skb, prim_data->saddr.mac); + break; + case NETBEUI_NAME_IN_CONFLICT: + nbns_get_name_conflict(skb); + break; + case NETBEUI_NAME_QUERY: + nbss_get_name_query(skb, prim_data->saddr.mac); + break; + case NETBEUI_NAME_RECOGNIZED: + nbqs_get_name_recognized(skb, prim_data->saddr.mac); + break; + case NETBEUI_DATAGRAM: + nbdg_get_datagram(skb); + break; + case NETBEUI_DATAGRAM_BROADCAST: + nbdg_get_datagram_broadcast(skb); + break; + case NETBEUI_STATUS_QUERY: + nbst_get_status_query(skb, prim_data->saddr.mac); + break; + case NETBEUI_STATUS_RESPONSE: + nbst_get_status_response(skb, prim_data->saddr.mac); + break; + case NETBEUI_TERMINATE_TRACE: + case NETBEUI_TERMINATE_TRACE2: + goto fskb; + } +out: return; +fskb: kfree_skb(skb); + goto out; +} + +/** + * netbeui_indicate - The callback for LLC indicate primitive dispatching + * @prim: primary interface block type, the LLC comm data structure. + * + * It dispatches LLC primitive to Link Service State Machine interfaces. + * Note: LLC flow control indication is not generated. We have used data + * request/confirm to control flow. Think if it is a misconception or is + * accepted anyway. + */ +static int netbeui_indicate(struct llc_prim_if_block *prim) +{ + struct sk_buff *skb = NULL; + + switch (prim->prim) { + case LLC_DATAUNIT_PRIM: + skb = prim->data->udata.skb; + nbll_deliver_datagram(skb, &prim->data->udata); + break; + case LLC_CONN_PRIM: + nbll_get_connect_indicate(prim); + break; + case LLC_DATA_PRIM: + skb = prim->data->data.skb; + nbll_deliver_packet(skb, &prim->data->data); + break; + case LLC_DISC_PRIM: + nbll_get_disconnect_indicate(prim); + break; + case LLC_RESET_PRIM: + nbll_get_reset_indicate(prim); + break; + case LLC_FLOWCONTROL_PRIM: + break; + } + return 0; +} + +/** + * netbeui_confirm - callback for LLC confirm primitive. + * @prim: primary interface block type, the LLC comm data structure. + * + * The callback for LLC confirm primitive dispatching. It dispatches LLC + * primitive to Link Service State Machine interfaces. + * Note: LLC reset confirm is not generated, since we never generate + * reset request + */ +static int netbeui_confirm(struct llc_prim_if_block *prim) +{ + int status = 0; + + switch (prim->prim) { + case LLC_CONN_PRIM: + nbll_get_connect_confirm(prim); break; + case LLC_DATA_PRIM: + status = nbll_get_data_confirm(prim); break; + case LLC_DISC_PRIM: + nbll_get_disconnect_confirm(prim); break; + case LLC_RESET_PRIM: break; + } + return status; +} + +static char banner[] __initdata = + KERN_INFO "NetBEUI 2.0 by Procom, 1997, Arnaldo C. Melo, 2001\n"; +static char err_sap[] __initdata = + KERN_ERR "Error opening NetBIOS SAP 0x%X on LLC.\n"; +static char err_socket[] __initdata = + KERN_ERR "Error registering NetBEUI socket.\n"; +static char err_proc[] __initdata = + KERN_INFO "Error registering NetBEUI proc entries.\n"; + +/** + * netbeui_init - The starting point of NetBEUI module. + * + * Since NetBEUI is distributed as a module, netbeui_init does all initial + * steps itself. Returns 0 if module initialized successfully, non-zero + * if a step in initialization failed (mostly opening LLC sap) + */ +static int __init netbeui_init(void) +{ + int rc = 0; + + printk(banner); + netbeui_sap = llc_sap_open(netbeui_indicate, netbeui_confirm, + LLC_SAP_NETBEUI); + if (!netbeui_sap) { + printk(err_sap); + goto err; + } + write_lock(&netbeui_adapters.lock); + netbeui_adapters.autobind = autobind; + if (autobind) { + int i = 0; + struct net_device *dev; + + read_lock(&dev_base_lock); + for (dev = dev_base; dev && i < NETBEUI_MAX_ADAPTERS; + dev = dev->next) + if (nbcm_apt_dev(dev)) { + dev_hold(dev); + netbeui_adapters.dev[i++] = dev; + dev_mc_add(dev, netbeui_funcaddr(dev), + dev->addr_len, 0); + } + read_unlock(&dev_base_lock); + netbeui_adapters.count = i; + } + nbns_init_name_number_1(netbeui_adapters.dev); + write_unlock(&netbeui_adapters.lock); + nbdg_set_dgbc_mtu(); + + if (nbso_init()) { + printk(err_socket); + goto err_sap; + } + if (netbeui_proc_init()) { + printk(err_proc); + goto err_nbso; + } + nbst_init_status(); +out: return rc; +err_nbso: + nbso_exit(); +err_sap: + llc_sap_close(netbeui_sap); +err: rc = -1; + goto out; +} + +static char err_exit[] __exitdata = + KERN_ERR "Error unregistering NetBEUI socket.\n"; + +/** + * netbeui_exit - The ending point of NetBEUI module. + * + * Since NetBEUI is distributed as a module, netbeui_exit does all + * housekeeping steps itself + */ +static void __exit netbeui_exit(void) +{ + int i; + + nbll_disconnect_all_links(); + read_lock(&netbeui_adapters.lock); + for (i = 0; i < netbeui_adapters.count; i++) { + dev_mc_delete(netbeui_adapters.dev[i], + netbeui_funcaddr(netbeui_adapters.dev[i]), + netbeui_adapters.dev[i]->addr_len, 0); + dev_put(netbeui_adapters.dev[i]); + } + read_unlock(&netbeui_adapters.lock); + if (nbso_exit()) + printk(err_exit); + netbeui_proc_clean(); + llc_sap_close(netbeui_sap); +} +module_init(netbeui_init); +module_exit(netbeui_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Procom, 1997, Arnaldo C. Melo, 2001"); +MODULE_DESCRIPTION("NetBEUI 2.0"); Index: kernel-acme/net/netbeui/name_serve.c diff -u /dev/null kernel-acme/net/netbeui/name_serve.c:1.1.12.1 --- /dev/null Sat Dec 22 02:21:24 2001 +++ kernel-acme/net/netbeui/name_serve.c Thu Nov 29 20:36:57 2001 @@ -0,0 +1,898 @@ +/* + * name_serve.c - Contains functions that implement NetBIOS Name Service + * + * Notes: + * - Two intermixed structures hold local name table a dextab_t that is + * used for assigning numbers to names and implicit name rule checking + * and a unidirectional linked list which is used for name search. every + * name entry may be found in both data structures. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include + +static void nbns_timer_function(unsigned long input); + +/* These functions are Name State Transition handlers */ +static int nbns_add_name_in_initial(name_t *nb_name); +static int nbns_retry_timeout_in_all(name_t *nb_name); +static int nbns_response_timeout_in_addwait(name_t *nb_name); +static int nbns_add_name_response1_in_addwait(name_t *nb_name); +static int nbns_add_name_query_in_addwait(name_t *nb_name); +static int nbns_response_timeout_in_collided(name_t *nb_name); +static int nbns_add_name_response2_in_collided(name_t *nb_name); +static int nbns_add_name_query_in_acquired(name_t *nb_name); +static int nbns_name_conflict_in_acquired(name_t *nb_name); +static int nbns_remove_name_in_acquired(name_t *nb_name); + +static void nbns_handle_event(name_event_t event, name_t *nb_name); +static unsigned short int nbns_correlator; +#define nbns_next_correlator() (++nbns_correlator) + +/* We need to have two paths to access names from dextab and linked-list */ +static name_t *name_list; +static rwlock_t name_list_lock = RW_LOCK_UNLOCKED; +dextab_t name_table = { + reserved: 2, + max_size: NETBEUI_MAX_NAMES, + lock: SPIN_LOCK_UNLOCKED +}; +static name_t name_number_1; + +#define name_table_entry(i) ((name_t *)name_table.addr[i]) + +/* Name Service State Machine definition */ +typedef int (* name_event_handler_t)(name_t *); + +struct event_struct { + name_state_t next_state; + name_event_handler_t event_handler; +}; +static struct event_struct name_state_table[4][8] = { + /* NETBEUI_NAME_INITIAL */ +{ +{ NETBEUI_NAME_ADDWAIT, + nbns_add_name_in_initial }, /* NETBEUI_NAME_ADD_NAME */ +{ -1, NULL }, /* NETBEUI_NAME_RETRY_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_NAME_RESPONSE_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_NAME_ADD_NAME_RESPONSE1 */ +{ -1, NULL }, /* NETBEUI_NAME_ADD_NAME_RESPONSE2 */ +{ -1, NULL }, /* NETBEUI_NAME_ADD_NAME_QUERY */ +{ -1, NULL }, /* NETBEUI_NAME_NAME_CONFLICT */ +{ -1, NULL } /* NETBEUI_NAME_REMOVE_NAME */ +}, + /* NETBEUI_NAME_ADDWAIT */ +{ +{ -1, NULL }, /* NETBEUI_NAME_ADD_NAME */ +{ NETBEUI_NAME_ADDWAIT, + nbns_retry_timeout_in_all }, /* NETBEUI_NAME_RETRY_TIMEOUT */ +{ NETBEUI_NAME_ACQUIRED, + nbns_response_timeout_in_addwait }, /* NETBEUI_NAME_RESPONSE_TIMEOUT */ +{ NETBEUI_NAME_COLLIDED, + nbns_add_name_response1_in_addwait }, /* NETBEUI_NAME_ADD_NAME_RESPONSE1 */ +{ -1, NULL }, /* NETBEUI_NAME_ADD_NAME_RESPONSE2 */ +{NETBEUI_NAME_ADDWAIT, + nbns_add_name_query_in_addwait }, /* NETBEUI_NAME_ADD_NAME_QUERY */ +{ -1, NULL }, /* NETBEUI_NAME_NAME_CONFLICT */ +{ -1, NULL } /* NETBEUI_NAME_REMOVE_NAME */ +}, + /* NETBEUI_NAME_COLLIDED */ +{ +{ -1, NULL }, /* NETBEUI_NAME_ADD_NAME */ +{ NETBEUI_NAME_COLLIDED, + nbns_retry_timeout_in_all }, /* NETBEUI_NAME_RETRY_TIMEOUT */ +{ NETBEUI_NAME_INITIAL, + nbns_response_timeout_in_collided }, /* NETBEUI_NAME_RESPONSE_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_NAME_ADD_NAME_RESPONSE1 */ +{ NETBEUI_NAME_INITIAL, + nbns_add_name_response2_in_collided }, /* NETBEUI_NAME_ADD_NAME_RESPONSE2 */ +{ -1, NULL }, /* NETBEUI_NAME_ADD_NAME_QUERY */ +{ -1, NULL }, /* NETBEUI_NAME_NAME_CONFLICT */ +{ -1, NULL } /* NETBEUI_NAME_REMOVE_NAME */ +}, + /* NETBEUI_NAME_ACQUIRED */ +{ +{ -1, NULL }, /* NETBEUI_NAME_ADD_NAME */ +{ -1, NULL }, /* NETBEUI_NAME_RETRY_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_NAME_RESPONSE_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_NAME_ADD_NAME_RESPONSE1 */ +{ -1, NULL }, /* NETBEUI_NAME_ADD_NAME_RESPONSE2 */ +{ NETBEUI_NAME_ACQUIRED, + nbns_add_name_query_in_acquired }, /* NETBEUI_NAME_ADD_NAME_QUERY */ +{ NETBEUI_NAME_ACQUIRED, + nbns_name_conflict_in_acquired }, /* NETBEUI_NAME_NAME_CONFLICT */ +{ NETBEUI_NAME_INITIAL, + nbns_remove_name_in_acquired }, /* NETBEUI_NAME_REMOVE_NAME */ +} +}; + +/* NAME_NUMBER_1 assignment and interface functions */ +/* + * Function: nbns_dev_name_number_1 + * Returns the name number of built by device MAC address + * Parameters: + * dev: pointer to device structure to build its NAME_NUMBER_1 + * Returns: + * non-NULL: pointer to NAME_NUMBER_1 built by device MAC address + * Note: + * NAME_NUMBER_1 is defined as (16-n) bytes zero concatenated by (n) + * bytes of MAC address, where n is size of MAC address in bytes. + */ +unsigned char *nbns_dev_name_number_1(struct net_device *dev) +{ + static char dev_name_number_1[NETBEUI_NAME_LEN]; + int zero_count = NETBEUI_NAME_LEN - dev->addr_len; + + memset(dev_name_number_1, 0, zero_count); + memcpy(dev_name_number_1 + zero_count, dev->dev_addr, dev->addr_len); + return dev_name_number_1; +} + +/* + * Function: nbns_validate_name + * Checks a NetBIOS name validity according to NetBIOS name rules. + * Parameters: + * name: pointer to NetBIOS name + * Returns: + * 0 : if name is a valid NetBIOS name + * non-zero: if name is not a valid NetBIOS name + */ +int nbns_validate_name(char *name) +{ + return (!memcmp(name, "IBM", 3) || + memchr(name, '\0', NETBEUI_NAME_LEN - 1)) ? -1 : 0; +} + +/* + * Function: nbns_init_name_number_1 + * Finds a correct value for NAME_NUMBER_1 + * Parameters: + * adapters: list of adapters the NetBEUI is bound to + * Returns: None + * Notes: + * - A NetBEUI implementation should provide a unique NAME_NUMBER_1. + * Since our implementations supports both multiple interface and + * loopback device, we need to decide on the device that is used + * for generating NAME_NUMBER_1. + */ +void nbns_init_name_number_1(struct net_device *adapters[]) +{ + name_number_1.type = NETBEUI_NAME_UNIQUE; + name_number_1.state = NETBEUI_NAME_ACQUIRED; + name_number_1.name_number = 1; + + if (adapters[0] && !(adapters[0]->flags & IFF_LOOPBACK)) { + memcpy(name_number_1.name, nbns_dev_name_number_1(adapters[0]), + NETBEUI_NAME_LEN); + goto out; + } + if (adapters[1]) { + memcpy(name_number_1.name, nbns_dev_name_number_1(adapters[1]), + NETBEUI_NAME_LEN); + goto out; + } + if (adapters[0]) { + memcpy(name_number_1.name, "LOOPBACK DEVICE ", + NETBEUI_NAME_LEN); + goto out; + } + name_number_1.name_number = -1; +out:; +} + +/* + * Function: nbns_name_number_1 + * The Name Service interface access routine for NAME_NUMBER_1 + * Parameters: None + * Returns: + * non-NULL: pointer to name_t structure that holds NAME_NUMBER_1 + */ +name_t *nbns_name_number_1(void) +{ + return name_number_1.name_number == 1 ? &name_number_1 : NULL; +} + +/* + * Name service state machine functions + * Implementing general functions + */ +/* + * Function: nbns_alloc_skb + * allocates a sk_buff that suits Name Service framing needs + * Parameters: + * data_len: number of data bytes that the calling routine intends + * to put in skb + * Returns: + * NULL : if can not allocate memory for skb + * non-NULL: pointer to skb allocated with data_len bytes space for data + */ +static struct sk_buff *nbns_alloc_skb(int mac_hlen, int data_len) +{ + struct sk_buff *skb = alloc_skb(CALC_DG_SKBLEN(mac_hlen, data_len), + GFP_ATOMIC); + if (!skb) + goto out; + skb_reserve(skb, LLCMAC_UI_HEADLEN(mac_hlen)); + skb->nh.raw = skb->h.raw = skb->data; + skb_put(skb, data_len); + skb->dev = NULL; +out: return skb; +} + +/* + * Function: nbns_alloc_name + * Allocates a name_t structure and does completely initialize all fields + * Parameters: None + * Returns: + * NULL : if can not allocate memory for name_t or its sk_buff + * non-NULL: pointer to name_t + * Notes: + * - An skb is attached to each new name for name registration purposes + * - Name timer is initialized but not started. + * - The call to memset does implicitly initialize all fields. Those fields + * that need explicit non-zero initialization are manipulated afterwards. + */ +static name_t *nbns_alloc_name(void) +{ + name_t *nb_name = kmalloc(sizeof(*nb_name), GFP_ATOMIC); + + if (!nb_name) + goto out; + /* Implicitly initialize all fields */ + memset(nb_name, 0, sizeof(*nb_name)); + init_timer(&nb_name->timer); + nb_name->timer.data = (unsigned long)nb_name; + nb_name->timer.function = nbns_timer_function; + init_waitqueue_head(&nb_name->waitq); + atomic_set(&nb_name->refcnt, 1); + /* Allocate name skb */ + nb_name->skb = nbns_alloc_skb(NETBEUI_MAC_B_HEADLEN, + nb_cmd_hdr_len[NETBEUI_ADD_NAME_QUERY]); + if (!nb_name->skb) { + kfree(nb_name); + nb_name = NULL; + } +out: return nb_name; +} + +/* + * Function: nbns_free_name + * Deallocates memory used for name_t and its sk_buff + * Parameters: + * nb_name: pointer to name_t memory to be freed + * Returns: None + */ +static void __nbns_free_name(name_t *nb_name) +{ + kfree_skb(nb_name->skb); + kfree(nb_name); +} + +static void nbns_free_name(name_t *nb_name) +{ + nbns_handle_event(NETBEUI_NAME_REMOVE_NAME, nb_name); + __nbns_free_name(nb_name); +} + +inline void nbns_name_hold(name_t *nb_name) +{ + atomic_inc(&nb_name->refcnt); +} + +inline void nbns_name_put(name_t *nb_name) +{ + if (atomic_dec_and_test(&nb_name->refcnt)) + nbns_free_name(nb_name); +} + +/* + * Function: nbns_add_name_to_table + * Inserts a previously allocated/initialized name_t into system local name + * table and local name list. + * Parameters: + * nb_name: pointer to name_t to insert + * Returns: + * 0 : if name is successfully inserted into name table + * -ENOSPC: if local name table is full + */ +static int nbns_add_name_to_table(name_t *nb_name) +{ + /* Allocate a name table entry */ + int name_number = dextab_insert_entry(&name_table, nb_name); + + if (name_number <= 1) + return -ENOSPC; + nb_name->name_number = name_number; + /* Add name to name list */ + write_lock_bh(&name_list_lock); + nb_name->next = name_list; + name_list = nb_name; + write_unlock_bh(&name_list_lock); + return 0; +} + +/* + * Function: nbns_remove_name_from_table + * Removes a name from system local name table. + * Parameters: + * nb_name: pointer to name_t to remove + * Returns: None + */ +static void nbns_remove_name_from_table(name_t *nb_name) +{ + name_t *entry; + name_t *prev_entry = NULL; + + dextab_delete_entry(&name_table, nb_name); + write_lock_bh(&name_list_lock); + entry = name_list; + while (entry) { + if (entry == nb_name) { + if (prev_entry) + prev_entry->next = entry->next; + else + name_list = entry->next; + break; + } + prev_entry = entry; + entry = entry->next; + } + write_unlock_bh(&name_list_lock); +} + +/* + * Function: nbns_find_correlator + * Finds a name in local name list, which has a specific NetBIOS name + * and has transmitted frames with a specific correlator + * Parameters: + * correlator: a sixteen bit integer which contains the response + * correlator of input frame. It should be matched against + * xmit correlator of frames sent by the element. + * name : pointer to NetBIOS name that the requested element should + * have + * Returns: + * NULL : if no name_t element found with the requested characteristics + * non-NULL: pointer to matching name_t with requested characteristics + * Notes: + * - This routine is useful for relating incoming response frames with + * name elements that have transmitted requests to remote nodes. + */ +static name_t *nbns_find_correlator(unsigned short correlator, char *name) +{ + name_t *nb_name; + + read_lock_bh(&name_list_lock); + nb_name = name_list; + while (nb_name) + if (nb_name->resp_correlator == correlator && + nb_name->state != NETBEUI_NAME_ACQUIRED && + !memcmp(nb_name->name, name, NETBEUI_NAME_LEN)) + break; + else + nb_name = nb_name->next; + if (nb_name) + nbns_name_hold(nb_name); + read_unlock_bh(&name_list_lock); + return nb_name; +} + +/* + * Function: nbns_boradcast_add_name_query + * Prepares a NetBIOS ADD NAME QUERY frame and nbll_uisends it to network + * Parameters: + * nb_name: pointer to name_t structure which the frame should be built for + * Returns: + * 0 : if frame is successfully broadcasted to network + * non-zero: if frame transmission encountered an error (usually at NDI + * layer) + * Notes: + * - Since ADD NAME QUERY frames are retransmitted in timed intervals, it + * is considered to build frame once, but transmit it multiple times. + * having built frames in each retransmission does generate multiple + * correlators and does frustrate processing responses. + */ +static int nbns_broadcast_add_name_query(name_t *nb_name) +{ + if (!nb_name->retries) { + dgram_t *hdr = (dgram_t *)nb_name->skb->data; + + hdr->length = nb_cmd_hdr_len[NETBEUI_ADD_NAME_QUERY]; + hdr->delimiter = NETBEUI_DELIMITER; + hdr->command = nb_name->type == NETBEUI_NAME_UNIQUE ? + NETBEUI_ADD_NAME_QUERY : + NETBEUI_ADD_GROUP_NAME_QUERY; + hdr->data1 = 0; + hdr->data2 = 0; + hdr->xmit_correlator = 0; + hdr->resp_correlator = nb_name->resp_correlator = + nbns_next_correlator(); + memset(hdr->dest_name, 0, NETBEUI_NAME_LEN); + memcpy(hdr->source_name, nb_name->name, NETBEUI_NAME_LEN); + } + return nbll_uisend(NULL, nb_name->skb); +} + +/* + * Function: nbns_broadcast_name_in_conflict + * Prepares a NetBIOS NAME IN CONFLICT frame and nbll_uisends it to network + * Parameters: + * nb_name: pointer to name_t structure which the frame should be built for + * Returns: + * 0 : if frame is successfully broadcasted to network + * non-zero: if frame transmission encountered an error (usually at NDI + * layer) + */ +static int nbns_broadcast_name_in_conflict(name_t *nb_name) +{ + dgram_t *hdr = (dgram_t *)nb_name->skb->data; + + hdr->length = nb_cmd_hdr_len[NETBEUI_NAME_IN_CONFLICT]; + hdr->delimiter = NETBEUI_DELIMITER; + hdr->command = NETBEUI_NAME_IN_CONFLICT; + hdr->data1 = hdr->data2 = 0; + hdr->xmit_correlator = hdr->resp_correlator = 0; + memcpy(hdr->dest_name, nb_name->name, NETBEUI_NAME_LEN); + memcpy(hdr->source_name, nbns_name_number_1()->name, NETBEUI_NAME_LEN); + return nbll_uisend(NULL, nb_name->skb); +} + +/* + * Function: nbns_unicast_add_name_response + * Prepares a NetBIOS ADD NAME RESPONSE frame and nbll_uisends it to + * network + * Parameters: + * nb_name: pointer to name_t structure which the frame should be built for + * Returns: + * 0 : if frame is successfully broadcasted to network + * non-zero: if frame transmission encountered an error (usually at NDI + * layer) or it can not allocate memory for frame. + * Note: + * - The lack of memory and inability to send response frame may cause a + * name to conflict on network. This is simply the case on a heavily + * loaded server, however since the query is retransmitted multiple times + * we hope the server would be able to defend its name at least once. In + * addition if an administrator finds the case he can increase either + * retransmissions or timeouts for all nodes on network. + */ +static int nbns_unicast_add_name_response(name_t *nb_name) +{ + dgram_t *hdr; + struct sk_buff *skb = nbns_alloc_skb(MAC_HEADLEN(nb_name->dev), + nb_cmd_hdr_len[NETBEUI_ADD_NAME_RESPONSE]); + if (!skb) + return -ENOMEM; + hdr = (dgram_t *)skb->data; + hdr->length = nb_cmd_hdr_len[NETBEUI_ADD_NAME_RESPONSE]; + hdr->delimiter = NETBEUI_DELIMITER; + hdr->command = NETBEUI_ADD_NAME_RESPONSE; + hdr->data1 = nb_name->state == NETBEUI_NAME_ACQUIRED ? 0 : 1; + hdr->data2 = nb_name->type; + hdr->xmit_correlator = nb_name->xmit_correlator; + hdr->resp_correlator = 0; + memcpy(hdr->source_name, nb_name->name, NETBEUI_NAME_LEN); + memcpy(hdr->dest_name, nb_name->name, NETBEUI_NAME_LEN); + skb->dev = nb_name->dev; + return nbll_uisend(nb_name->remote_mac, skb); +} + +/* + * Function: nbns_handle_event + * This is the heart of Name Service State Machine, which performs a + * transition from current state of name element to new state based + * on event occurred and name state table contents. + * Parameters: + * event : An integer of NETBEUI_NAME_* family that implies type of event + * nb_name: pointer to name_t structure which the event occurred on + * Returns: None + * Notes: + * - The state changes before actions be executed. This is due to + * non deterministic behavior of actions which may sleep the current + * process, thus stopping the function in the mid-way. + */ +static void nbns_handle_event(name_event_t event, name_t *nb_name) +{ + struct event_struct *ev = &name_state_table[nb_name->state][event]; + + if (ev && ev->event_handler) { + unsigned char old_state = nb_name->state; + + nb_name->state = ev->next_state; + if (ev->event_handler(nb_name)) + nb_name->state = old_state; + } +} + +/* + * Function: nbns_timer_function + * This is the callback function triggered upon expiration of name + * retransmittion timer. It just injects an event into state machine for + * its link. + * Parameters: + * input: pointer to name_t structure whose timer is expired. + * Returns: None + */ +static void nbns_timer_function(unsigned long input) +{ + name_t *nb_name = (name_t *)input; + + if (nb_name->retries < NETBEUI_TRANSMIT_COUNT) + nbns_handle_event(NETBEUI_NAME_RETRY_TIMEOUT, nb_name); + else + nbns_handle_event(NETBEUI_NAME_RESPONSE_TIMEOUT, nb_name); +} + +/* + * Name service state machine functions + * Implementing transition functions + */ +/* + * Function: nbns_xxxx_in_ssss + * The section below contains functions that implement actions needed + * to legally transit from one state to another. + * Parameters: + * nb_name: pointer to name_t structure which the actions are to be + * applied to + * Returns: + * 0 : if all actions are done successfully + * non-zero: if one of actions failed + * Note: + * - For the sake of simplicity, the actions are automatically rollbacked + * in each function, if an action in transition fails. The design + * documents do not cover these parts of code. + */ +static int nbns_add_name_in_initial(name_t *nb_name) +{ + int rc = -1; + + nb_name->retries = 0; + nb_name->status = nbns_broadcast_add_name_query(nb_name); + if (nb_name->status) + goto out; + nb_name->status = nbns_add_name_to_table(nb_name); + if (nb_name->status) + goto out; + rc = 0; + nb_name->retries++; + nb_name->timer.expires = jiffies + NETBEUI_TRANSMIT_TIMEOUT; + add_timer(&nb_name->timer); + sleep_on(&nb_name->waitq); +out: return rc; +} + +static int nbns_retry_timeout_in_all(name_t *nb_name) +{ + nb_name->timer.expires = jiffies + NETBEUI_TRANSMIT_TIMEOUT; + add_timer(&nb_name->timer); + + if (nbns_broadcast_add_name_query(nb_name)) + return -1; + nb_name->retries++; + return 0; +} + +static int nbns_response_timeout_in_addwait(name_t *nb_name) +{ + wake_up(&nb_name->waitq); + return 0; +} + +static int nbns_add_name_response1_in_addwait(name_t *nb_name) +{ + nb_name->status = -EADDRINUSE; + return 0; +} + +static int nbns_add_name_query_in_addwait(name_t *nb_name) +{ + return nbns_unicast_add_name_response(nb_name) ? -1 : 0; +} + +static int nbns_response_timeout_in_collided(name_t *nb_name) +{ + wake_up(&nb_name->waitq); + nbns_remove_name_from_table(nb_name); + return 0; +} + +static int nbns_add_name_response2_in_collided(name_t *nb_name) +{ + nbns_broadcast_name_in_conflict(nb_name); + del_timer(&nb_name->timer); + wake_up(&nb_name->waitq); + nbns_remove_name_from_table(nb_name); + return 0; +} + +static int nbns_add_name_query_in_acquired(name_t *nb_name) +{ + return nbns_unicast_add_name_response(nb_name) ? -1 : 0; +} + +static int nbns_name_conflict_in_acquired(name_t *nb_name) +{ + nb_name->conflicted = 1; + return 0; +} + +static int nbns_remove_name_in_acquired(name_t *nb_name) +{ + nbns_remove_name_from_table(nb_name); + return 0; +} + +/* + * Name service state machine functions + * Implementing interface functions + */ +/* + * Function: nbns_add_name + * Adds a name to local name table after checking network (being + * permitted). + * Parameters: + * name : pointer to 16 byte NetBIOS name + * type : type of NetBIOS name that is NETBEUI_NAME_GROUP, + * NETBEUI_NAME_UNIQUE + * out_name: pointer to name_t structure built for that name. Since this + * a result argument, its value depends on function return value + * if return value specifies successful operation then this + * argument contains a valid pointer. + * Returns: + * 0 : if name successfully registered into local name table + * -EINVAL : if name is not a valid NetBIOS name + * -EADDRINUSE: if name is registered either in local name table or + * on another machine in network. + * -ENOMEM : if memory allocation for name element name_t fails + * others : any other error value reported by LLC or system. + */ +int nbns_add_name(char *name, name_type_t type, name_t **out_name) +{ + name_t *nb_name; + int rc = -EINVAL; + + if (nbns_validate_name(name)) + goto out; + rc = -EADDRINUSE; + nb_name = nbns_find_name(name); + if (nb_name) + goto out_put; + nb_name = nbns_alloc_name(); + rc = -ENOMEM; + if (!nb_name) + goto out; + *out_name = NULL; + nb_name->state = NETBEUI_NAME_INITIAL; + nb_name->type = type; + memcpy(nb_name->name, name, NETBEUI_NAME_LEN); + nbns_handle_event(NETBEUI_NAME_ADD_NAME, nb_name); + if (nb_name->state != NETBEUI_NAME_ACQUIRED) { + rc = nb_name->status ? : -1; + __nbns_free_name(nb_name); + goto out; + } + rc = 0; + *out_name = nb_name; + nbns_name_hold(nb_name); +out: return rc; +out_put: + nbns_name_put(nb_name); + goto out; +} + +/* + * Function: nbns_find_name + * Finds a name with a specific 16 bytes NetBIOS name in local name table. + * Parameters: + * name: pointer to 16 bytes NetBIOS name to be located in local name table + * Returns: + * NULL : if NetBIOS name not found in local name table + * non-NULL: pointer to name_t element found in local name table. + */ +name_t *nbns_find_name(char *name) +{ + name_t *nb_name; + + read_lock_bh(&name_list_lock); + nb_name = name_list; + while (nb_name) { + if (!memcmp(nb_name->name, name, NETBEUI_NAME_LEN)) + break; + nb_name = nb_name->next; + } + if (nb_name) + nbns_name_hold(nb_name); + read_unlock_bh(&name_list_lock); + return nb_name; +} + +/* + * Function: nbns_del_name + * Removes a name_t element from local name table and local name list, + * using its NetBIOS name. + * Parameters: + * nb_name: pointer to name_t element to remove from local name table + * Returns: None + * Notes: + * - Removing the name_t is a multi-pass mechanism depending on the value + * of name use count. A name is actually removed from local name table + * when its use count reaches zero. + */ +void nbns_del_name(name_t *nb_name) +{ + if (nb_name->name_number != 1) + nbns_name_put(nb_name); +} + +/* + * Function: nbns_del_identifier + * Removes a name_t element from local name table and local name list, + * using its identification number. + * Parameters: + * id: id or number of the name to remove from local name table + * Returns: None + * Notes: + * - Refer to notes section of nbns_del_name comment + * - The identification number is a notion used in sock_name. Every + * SOCK_NAME type socket assigns a unique identifier to all the name + * it registers, which lets not to keep another table of registered + * names in socket data structures. The value is simple memory address + * of socket and is assigned directly from SOCK_NAME codes. + * - Multiple names may have similar identifier. + */ +void nbns_del_identifier(unsigned long id) +{ + name_t *nb_name; + int index; + + for (index = name_table.reserved; index < name_table.size; index++) { + nb_name = name_table_entry(index); + if (nb_name && nb_name->identifier == id) + nbns_del_name(nb_name); + } +} + +/* + * Function: nbns_get_add_name_query + * Accepts an ADD NAME QUERY frame and generates an event for Name + * Service State Machine. + * Parameters: + * skb : pointer to sk_buff that holds the frame + * remote_mac: pointer to MAC address of remote node, whom sent the frame + * type : the flag indicates the type of query: + * NETBEUI_NAME_GROUP indicates ADD GROUP NAME QUERY + * NETBEUI_NAME_UNIQUE indicates ADD NAME QUERY + * Returns: none + */ +void nbns_get_add_name_query(struct sk_buff *skb, unsigned char *remote_mac, + int type) +{ + dgram_t *hdr = (dgram_t *)skb->data; + name_t *nb_name = nbns_find_name(hdr->source_name); + + /* If name not found in name table or both are group names */ + if (!nb_name) + goto out; + if ((skb->dev->flags & IFF_LOOPBACK) || + (nb_name->type == NETBEUI_NAME_GROUP && type == NETBEUI_NAME_GROUP)) + goto out_put; + memcpy(nb_name->remote_mac, remote_mac, skb->dev->addr_len); + nb_name->dev = skb->dev; + nb_name->xmit_correlator = hdr->resp_correlator; + nbns_handle_event(NETBEUI_NAME_ADD_NAME_QUERY, nb_name); +out_put: + nbns_name_put(nb_name); +out: kfree_skb(skb); +} + +/* + * Function: nbns_get_add_name_response + * Accepts an ADD NAME RESPONSE frame and generates an event for Name + * Service State Machine. + * Parameters: + * skb : pointer to sk_buff that holds the frame + * remote_mac: pointer to MAC address of remote node, whom sent the frame + * Returns: none + */ +void nbns_get_add_name_response(struct sk_buff *skb, unsigned char *remote_mac) +{ + dgram_t *hdr = (dgram_t *)skb->data; + name_t *nb_name = nbns_find_correlator(hdr->xmit_correlator, + hdr->dest_name); + /* If it does not match a query */ + if (!nb_name) + goto out; + /* The name registration query got a negative response */ + /* Test if it is a duplicate and already received */ + + if (nb_name->dev != skb->dev || + memcmp(nb_name->remote_mac, remote_mac, skb->dev->addr_len)) { + nb_name->dev = skb->dev; + memcpy(nb_name->remote_mac, remote_mac, skb->dev->addr_len); + nb_name->responses++; + if (nb_name->responses == 1) + nbns_handle_event(NETBEUI_NAME_ADD_NAME_RESPONSE1, + nb_name); + else + nbns_handle_event(NETBEUI_NAME_ADD_NAME_RESPONSE2, + nb_name); + } + nbns_name_put(nb_name); +out: kfree_skb(skb); +} + +/* + * Function: nbns_get_name_conflict + * Accepts a NAME CONFLICT frame and generates an event for Name + * Service State Machine. + * Parameters: + * skb: pointer to sk_buff that holds the frame + * Returns: None + * Notes: + * - The strategy chosen for manipulating NAME CONFLICT frames is to + * set a flag in name_t structure, which is available via /proc entry + * interface. + */ +void nbns_get_name_conflict(struct sk_buff *skb) +{ + name_t *nb_name = nbns_find_name(((dgram_t *)skb->data)->source_name); + + if (nb_name) { + nbns_handle_event(NETBEUI_NAME_NAME_CONFLICT, nb_name); + nbns_name_put(nb_name); + } + kfree_skb(skb); +} + +/* + * Function: nbns_get_link_table + * returns a pointer to NetBEUI name table. The proc support code uses + * the name table to map its contents to /proc/sys/netbeui entry. + * Parameters: None + * Returns: + * non-NULL: pointer to NetBEUI name table + */ +dextab_t *nbns_get_name_table(void) +{ + return &name_table; +} + +/* + * Function: nbns_get_name_list + * returns a pointer to NetBEUI name list. The status module uses + * the name list to prepare its status response. + * Parameters: None + * Returns: + * NULL : name list has no entry + * non-NULL: pointer to NetBEUI name list + */ +name_t *nbns_get_name_list(void) +{ + return name_list; +} + +/* + * Function: nbns_count_names + * returns number of entries in name table. The status module uses + * the this number to prepare its status response. + * Parameters: None + * Returns: + * zero : name table has no entry + * positive: number of entries in name table + */ +int nbns_count_names(void) +{ + return name_table.count; +} Index: kernel-acme/net/netbeui/nb_common.c diff -u /dev/null kernel-acme/net/netbeui/nb_common.c:1.1.12.1 --- /dev/null Sat Dec 22 02:21:25 2001 +++ kernel-acme/net/netbeui/nb_common.c Thu Nov 29 20:36:57 2001 @@ -0,0 +1,134 @@ +/* + * nb_common.c - Contains common in use functions for NetBEUI services. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include + +/* + * Function: netbeui_funcaddr + * Returns functional address of a network device. + * Parameters: + * dev : pointer to device that need to its functional address. + * Returns: char * + */ +char *netbeui_funcaddr(struct net_device *dev) +{ + char* rc = NETBIOS_FUNC_ADDR_4ETH; + + if (dev->type != ARPHRD_ETHER && dev->type != ARPHRD_EETHER && + dev->type != ARPHRD_LOOPBACK) { + if (dev->type == ARPHRD_IEEE802) + rc = NETBIOS_FUNC_ADDR_4TR; + else + rc = "\x00\x00\x00\x00\x00\x00"; + } + return rc; +} + +/* + * Function: nbcm_dev_supported + * Indicates that a network device is supported by us or not. + * Parameters: + * dev_type : device type that must check it. + * Returns: unsigned char + * 0 : device not supported by us. + * 1 : device supported by us. + */ +static unsigned char nbcm_dev_supported(unsigned int dev_type) +{ + return dev_type == ARPHRD_ETHER || dev_type == ARPHRD_EETHER || + dev_type == ARPHRD_IEEE802 || dev_type == ARPHRD_LOOPBACK; +} + +/* + * Function: nbcm_apt_dev + * Parameters: None + * Returns: unsigned char + */ +unsigned char nbcm_apt_dev(struct net_device *dev) +{ + return (dev->flags & IFF_LOOPBACK) || + ((dev->flags & IFF_MULTICAST) && nbcm_dev_supported(dev->type)); +} + +/* + * Function: MAC_HEADLEN + * Calculates the MAC header length of a device. + * Parameters: + * dev: pointer to device that we need to its MAC header length. + * Returns: int + * Always positive: MAC header length of the device. + * Note: + * if we do not recognize device type, the function returns ethernet + * MAC header length. + */ +int MAC_HEADLEN(struct net_device *dev) +{ + return dev->type == ARPHRD_IEEE802 ? sizeof(struct trh_hdr) : + sizeof(struct ethhdr); +} + +/* + * Function: LLCMAC_I_HEADLEN + * Calculates lengths of LLC header and MAC header together for 'I frames' + * on a specific device. + * Parameters: + * dev: pointer to device that calculation is performed for it. + * Returns: int + * Always positive : I frame's MAC + LLC header length of the device. + */ +inline int LLCMAC_I_HEADLEN(struct net_device *dev) +{ + return MAC_HEADLEN(dev) + NETBEUI_LLC_I_HEADLEN; +} + +/* + * Function: LLCMAC_UI_HEADLEN + * Calculates lengths of LLC header and MAC header together for UI frames. + * Parameters: + * mac_hlen : MAC header length for UI frames. + * Returns: int + * Always positive: UI frame's MAC + LLC header length of the device. + */ +inline int LLCMAC_UI_HEADLEN(int mac_hlen) +{ + return mac_hlen + NETBEUI_LLC_UI_HEADLEN; +} + +/* + * Function: LLCMAC_UIB_HEADLEN + * Calculates lengths of LLC header and MAC header together for + * broadcasted UI frames. + * Parameters: none + * Returns: int + * Always positive: broadcasted UI frame's MAC + LLC header length. + */ +inline int LLCMAC_UIB_HEADLEN(void) +{ + return NETBEUI_MAC_B_HEADLEN + NETBEUI_LLC_UI_HEADLEN; +} + +/* + * Function: CALC_DG_SKBLEN + * Calculates appropriate sk_buff length for sending UI frames. + * Parameters: + * mac_hlen : MAC header length. + * user_datalen: length of data that must put into sk_buff after + * MAC + LLC headers (including NetBIOS header). + * Returns: int + * Always positive: appropriate sk_buff length for sending UI frames. + */ +inline int CALC_DG_SKBLEN(int mac_hlen, int user_datalen) +{ + return LLCMAC_UI_HEADLEN(mac_hlen) + user_datalen; +} Index: kernel-acme/net/netbeui/proc.c diff -u /dev/null kernel-acme/net/netbeui/proc.c:1.1.12.1 --- /dev/null Sat Dec 22 02:21:25 2001 +++ kernel-acme/net/netbeui/proc.c Thu Nov 29 20:36:57 2001 @@ -0,0 +1,281 @@ +/* + * proc.c - Implements directory entries for NETBEUI names , links and + * sessions below proc filesystem in memory. + * Notes: + * - Proc file system for NETBEUI is created under /proc/net/netbeui. + * - There are two types of directory entries below netbeui under proc : + * Static directory entries which are created at module initialization + * into memory. Dynamic entries which are created at runtime like session + * entries per link. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define NETBEUI_PROJECT "Procom, 1997, Arnaldo C. Melo, 2001" +#define NETBEUI_RELEASE "2.0" + +static struct proc_dir_entry *proc_netbeui; + +static const char *netbeui_version = "NetBEUI version " NETBEUI_RELEASE " " + NETBEUI_PROJECT "\n"; + +static int netbeui_version_proc_get_info(char *buffer, char **start, + off_t offset, int count, int* eof, + void* data) +{ + return sprintf(buffer, netbeui_version); +} + +static int netbeui_adapters_proc_get_info(char *buffer, char **start, + off_t offset, int count, int *eof, + void* data) +{ + int i, l = 0; + int j = 0; + char *b; + + read_lock(&netbeui_adapters.lock); + for (i = 0, b = buffer; netbeui_adapters.dev[i]; i++, j += l, b += l) + l = sprintf(b, "%-*.*s %5u %02X:%02X:%02X:%02X:%02X:%02X\n", + IFNAMSIZ, IFNAMSIZ, netbeui_adapters.dev[i]->name, + netbeui_adapters.dev[i]->mtu, + netbeui_adapters.dev[i]->dev_addr[0], + netbeui_adapters.dev[i]->dev_addr[1], + netbeui_adapters.dev[i]->dev_addr[2], + netbeui_adapters.dev[i]->dev_addr[3], + netbeui_adapters.dev[i]->dev_addr[4], + netbeui_adapters.dev[i]->dev_addr[5]); + read_unlock(&netbeui_adapters.lock); + return j; +} + +static int netbeui_names_proc_get_info(char *buffer, char **start, off_t offset, + int count, int* eof, void* data) +{ + int i, len = 0; + dextab_t *name_table = nbns_get_name_table(); + + spin_lock_bh(&name_table->lock); + if (!name_table->count) + goto out; + len += sprintf(buffer, + "%-*.*s stt stu conflict nameNr users\n", + NETBEUI_NAME_LEN + 5, NETBEUI_NAME_LEN + 5, "name"); + for (i = name_table->reserved; i < name_table->size; ++i) { + unsigned char printable_name[NETBEUI_NAME_LEN + 10]; + unsigned char name_port; + name_t *name = name_table->addr[i]; + + if (!name) + continue; + memcpy(printable_name, name->name, NETBEUI_NAME_LEN + 1); + name_port = name->name[NETBEUI_NAME_LEN - 1]; + if (name_port < 0x20 || name_port >= 0x80) + sprintf(printable_name + NETBEUI_NAME_LEN - 1, + "<%2x>", name_port); + len += sprintf(buffer + len, + "%-*.*s %3d %3d %8u %6u %5u\n", + NETBEUI_NAME_LEN + 5, NETBEUI_NAME_LEN + 5, + printable_name, name->state, name->status, + name->conflicted, name->name_number, + atomic_read(&name->refcnt)); + } +out: spin_unlock_bh(&name_table->lock); + if (offset >= len) { + *start = buffer; + *eof = 1; + len = 0; + } else { + *start = buffer + offset; + if ((len -= offset) > count) + len = count; + else + *eof = 1; + } + return len; +} + +static int netbeui_sessions_proc_get_info(char *buffer, char **start, + off_t offset, int count, int* eof, + void* data) +{ + int i, len = 0; + dextab_t *link_table = nbll_get_link_table(); + + spin_lock_bh(&link_table->lock); + if (!link_table->count) + goto out; + len += sprintf(buffer, + "lk st su %-*.*s%-*.*slsn rsn ver nI " + "tr mtu oTotal iTotal\n", + NETBEUI_NAME_LEN - 1, NETBEUI_NAME_LEN - 1, + "localName", + NETBEUI_NAME_LEN - 1, NETBEUI_NAME_LEN - 1, + "remoteName"); + + for (i = link_table->reserved; i < link_table->size; ++i) { + int j; + link_t *link = link_table->addr[i]; + dextab_t *session_table; + + if (!link) + continue; + session_table = &link->session_table; + spin_lock_bh(&session_table->lock); + if (!session_table->count) + goto unlock_session_table; + for (j = session_table->reserved; + j < session_table->size; ++j) { + struct nb_session *session = session_table->addr[j]; + char* name = NULL; + + if (!session) + continue; + if (session->local_name) + name = (char *)&session->local_name->name; + len += sprintf(buffer + len, + "%2u %2d %2d %-*.*s%-*.*s%3u " + "%3u %3u %2u %2u %4u %8u %8u\n", + session->link, + session->state, session->status, + NETBEUI_NAME_LEN - 1, + NETBEUI_NAME_LEN - 1, + name, + NETBEUI_NAME_LEN - 1, + NETBEUI_NAME_LEN - 1, + session->remote_name, + session->lsn, session->rsn, + session->version, + session->nack_indicator, + session->tr_frame_lf, session->mtu, + session->o_total, session->i_total); + } +unlock_session_table: + spin_unlock_bh(&session_table->lock); + } +out: spin_unlock_bh(&link_table->lock); + if (offset >= len) { + *start = buffer; + *eof = 1; + len = 0; + } else { + *start = buffer + offset; + if ((len -= offset) > count) + len = count; + else + *eof = 1; + } + return len; +} + +static int netbeui_links_proc_get_info(char *buffer, char **start, off_t offset, + int count, int *eof, void *data) +{ + int i, len = 0; + dextab_t *table = nbll_get_link_table(); + + spin_lock_bh(&table->lock); + if (table->count) + len = sprintf(buffer, + "lk st su %-17.17s %-*.*s llcBusy frames\n", + "remoteMac", IFNAMSIZ, IFNAMSIZ, "remoteDevice"); + else + goto out; + for (i = table->reserved; i < table->size; ++i) { + link_t *link = table->addr[i]; + char *name = NULL; + + if (!link) + continue; + if (link->dev) + name = link->dev->name; + len += sprintf(buffer + len, + "%2u %2d %2d %02X:%02X:%02X:%02X:%02X:%02X " + "%-*.*s %7u %6u\n", + link->link, link->state, link->status, + link->remote_mac[0], link->remote_mac[1], + link->remote_mac[2], link->remote_mac[3], + link->remote_mac[4], link->remote_mac[5], + IFNAMSIZ, IFNAMSIZ, name, link->llc_busy, + skb_queue_len(&link->skbq)); + } +out: spin_unlock_bh(&table->lock); + if (offset >= len) { + *start = buffer; + *eof = 1; + len = 0; + } else { + *start = buffer + offset; + if ((len -= offset) > count) + len = count; + else + *eof = 1; + } + return len; +} + +int netbeui_proc_init(void) +{ + int rc = 0; + + proc_netbeui = proc_mkdir("netbeui", proc_net); + if (!proc_netbeui) + goto out_err; + if (!create_proc_read_entry("links", 0, proc_netbeui, + netbeui_links_proc_get_info, NULL)) + goto out_netbeui; + if (!create_proc_read_entry("sessions", 0, proc_netbeui, + netbeui_sessions_proc_get_info, NULL)) + goto out_links; + if (!create_proc_read_entry("names", 0, proc_netbeui, + netbeui_names_proc_get_info, NULL)) + goto out_sessions; + if (!create_proc_read_entry("version", 0, proc_netbeui, + netbeui_version_proc_get_info, NULL)) + goto out_names; + if (!create_proc_read_entry("adapters", 0, proc_netbeui, + netbeui_adapters_proc_get_info, NULL)) + goto out_version; +out: return rc; +out_version: + remove_proc_entry("version", proc_netbeui); +out_names: + remove_proc_entry("names", proc_netbeui); +out_sessions: + remove_proc_entry("sessions", proc_netbeui); +out_links: + remove_proc_entry("links", proc_netbeui); +out_netbeui: + remove_proc_entry("netbeui", proc_net); +out_err: + rc = -ENOMEM; + goto out; +} + +void netbeui_proc_clean(void) +{ + if (proc_netbeui) { + remove_proc_entry("links", proc_netbeui); + remove_proc_entry("sessions", proc_netbeui); + remove_proc_entry("names", proc_netbeui); + remove_proc_entry("version", proc_netbeui); + remove_proc_entry("adapters", proc_netbeui); + remove_proc_entry("netbeui", proc_net); + } +} Index: kernel-acme/net/netbeui/query_serve.c diff -u /dev/null kernel-acme/net/netbeui/query_serve.c:1.1.12.1 --- /dev/null Sat Dec 22 02:21:25 2001 +++ kernel-acme/net/netbeui/query_serve.c Thu Nov 29 20:36:57 2001 @@ -0,0 +1,778 @@ +/* + * query_serve.c - Contains functions that implement NetBIOS Query Service. + * It also implements a remote name cache which is intended + * to cache a mapping between NetBIOS name and MAC address. + * Notes: + * - VRP in comments is the acronym of "Value Result Parameter" + * - Remote name cache needs upper layer considerations which makes its + * impossible or hardly possible in other modules. Up to now only Session + * service uses this mechanism to speed-up connection establishment. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include + +static void nbqs_timer_function(unsigned long); + +/* These functions are Query State Transition handlers */ +static int nbqs_name_query_in_initial(query_t *nb_query); +static int nbqs_name_find_in_initial(query_t *nb_query); +static int nbqs_retry_timeout_in_all(query_t *nb_query); +static int nbqs_response_timeout_in_all(query_t *nb_query); +static int nbqs_name_recognized_in_qrywait(query_t *nb_query); +static int nbqs_name_recognized_in_findwait(query_t *nb_query); +static int nbqs_end_query_in_name_recognized(query_t *nb_query); + +static unsigned short int nbqs_correlator; +#define nbqs_next_correlator() (++nbqs_correlator) + +static query_t *query_list; +rwlock_t query_list_lock = RW_LOCK_UNLOCKED; + +/* Remote name cache definition */ +struct rnc_struct { + __u8 name[NETBEUI_NAME_LEN]; + __u8 mac[6]; + struct net_device *dev; + unsigned long int time_stamp; + struct rnc_struct *prev; + struct rnc_struct *next; +}; +typedef struct rnc_struct rnc_t; + +static rnc_t *rnc_list; +static int rnc_count; +static spinlock_t rnc_list_lock = SPIN_LOCK_UNLOCKED; + +/* Query Service State Machine definition */ +typedef int (* query_event_handler_t)(query_t *); + +struct event_struct { + query_state_t next_state; + query_event_handler_t event_handler; +}; + +static struct event_struct query_state_table[4][6] = { + /* NETBEUI_QUERY_INITIAL */ +{ +{ NETBEUI_QUERY_QRYWAIT, + nbqs_name_query_in_initial }, /* NETBEUI_QUERY_NAME_QUERY */ +{ NETBEUI_QUERY_FINDWAIT, + nbqs_name_find_in_initial }, /* NETBEUI_QUERY_NAME_FIND */ +{ -1, NULL }, /* NETBEUI_QUERY_RETRY_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_QUERY_RESPONSE_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_QUERY_NAME_RECOGNIZED */ +{ -1, NULL }, /* NETBEUI_QUERY_END_QURY */ +}, + /* NETBEUI_QUERY_QRYWAIT */ +{ +{ -1, NULL }, /* NETBEUI_QUERY_NAME_QUERY */ +{ -1, NULL }, /* NETBEUI_QUERY_NAME_FIND */ +{ NETBEUI_QUERY_QRYWAIT, + nbqs_retry_timeout_in_all }, /* NETBEUI_QUERY_RETRY_TIMEOUT */ +{ NETBEUI_QUERY_INITIAL, + nbqs_response_timeout_in_all }, /* NETBEUI_QUERY_RESPONSE_TIMEOUT */ +{ NETBEUI_QUERY_RECOGNIZED, + nbqs_name_recognized_in_qrywait }, /* NETBEUI_QUERY_NAME_RECOGNIZED */ +{ -1, NULL }, /* NETBEUI_QUERY_END_QURY */ +}, + /* NETBEUI_QUERY_FINDWAIT */ +{ +{ -1, NULL }, /* NETBEUI_QUERY_NAME_QUERY */ +{ -1, NULL }, /* NETBEUI_QUERY_NAME_FIND */ +{ NETBEUI_QUERY_FINDWAIT, + nbqs_retry_timeout_in_all }, /* NETBEUI_QUERY_RETRY_TIMEOUT */ +{ NETBEUI_QUERY_INITIAL, + nbqs_response_timeout_in_all }, /* NETBEUI_QUERY_RESPONSE_TIMEOUT */ +{ NETBEUI_QUERY_FINDWAIT, + nbqs_name_recognized_in_findwait }, /* NETBEUI_QUERY_NAME_RECOGNIZED */ +{ -1, NULL }, /* NETBEUI_QUERY_END_QURY */ +}, + /* NETBEUI_QUERY_RECOGNIZED */ +{ +{ -1, NULL }, /* NETBEUI_QUERY_NAME_QUERY */ +{ -1, NULL }, /* NETBEUI_QUERY_NAME_FIND */ +{ -1, NULL }, /* NETBEUI_QUERY_RETRY_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_QUERY_RESPONSE_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_QUERY_NAME_RECOGNIZED */ +{ NETBEUI_QUERY_INITIAL, + nbqs_end_query_in_name_recognized },/* NETBEUI_QUERY_END_QURY */ +} +}; +/* + * Query service state machine functions + * Implementing remote name cache + */ +/* + * Function: nbqs_remove_rnc + * Removes a rnc_t entry from remote name cache list rnc_list + * + * Parameters: + * nb_rnc : pointer to rnc_t entry to remove + * + * Returns: none + */ +static void __nbqs_remove_rnc(rnc_t *nb_rnc) +{ + if (nb_rnc->next) + nb_rnc->next->prev = nb_rnc->prev; + if (nb_rnc->prev) + nb_rnc->prev->next = nb_rnc->next; + else + rnc_list = nb_rnc->next; +} + +static inline void nbqs_remove_rnc(rnc_t *nb_rnc) +{ + spin_lock(&rnc_list_lock); + __nbqs_remove_rnc(nb_rnc); + spin_unlock(&rnc_list_lock); +} + +/* + * Function: nbqs_find_rnc + * Finds a rnc_t entry in remote name cache list for a specific NetBIOS + * 16 byte name. + * + * Parameters: + * name : NetBIOS name of remote node to find its rnc_t + * + * Returns: + * NULL : if no matching entry found in remote cache name list + * non-NULL: pointer to rnc_t in remote_cache name list + */ +static inline rnc_t *__nbqs_find_rnc(char *name) +{ + rnc_t *nb_rnc = rnc_list; + + while (nb_rnc) { + if (!memcmp(nb_rnc->name, name, NETBEUI_NAME_LEN)) { + nb_rnc->time_stamp = jiffies; + break; + } + nb_rnc = nb_rnc->next; + } + return nb_rnc; +} + +static inline rnc_t *nbqs_find_rnc(char *name) +{ + rnc_t *nb_rnc; + + spin_lock(&rnc_list_lock); + nb_rnc = __nbqs_find_rnc(name); + spin_unlock(&rnc_list_lock); + return nb_rnc; +} + +/* + * Function: nbqs_cleanup_rnc + * This routine will throw those cache entries who live in cache more + * than a specific time (measured in jiffies) . + * + * Parameters: none + * + * Returns: none + * + * Notes: + * - For the sake of efficiency, remote name cache list wont grow more + * than a specific size . Note that this is + * just a high water mark. Refer to nbqs_add_rnc + */ +static void __nbqs_cleanup_rnc(void) +{ + rnc_t *nb_rnc = rnc_list; + + while (nb_rnc) { + if (jiffies - nb_rnc->time_stamp > NETBEUI_QUERY_CACHE_LIVING_TIME) { + rnc_t *tmp_rnc = nb_rnc; + + nb_rnc = nb_rnc->next; + nbqs_remove_rnc(tmp_rnc); + kfree(tmp_rnc); + } else { + rnc_count++; + nb_rnc = nb_rnc->next; + } + } +} + +static inline void nbqs_cleanup_rnc(void) +{ + spin_lock(&rnc_list_lock); + __nbqs_cleanup_rnc(); + spin_unlock(&rnc_list_lock); +} + +/* + * Function: nbqs_add_rnc + * Adds/Updates an entry to remote name cache list + * + * Parameters: + * name : pointer to NetBIOS name of remote node + * dev : pointer to device structure node is connected via + * mac : pointer to MAC address of remote node + * + * Returns: none + * + * Notes: + * - If an rnc_t corresponding to NetBIOS name exists in cache it is + * updated else a new entry is created. + * - This routine handles cache grow beyond NETBEUI_QUERY_MAX_CACHE_ENTRIES + * but does not guarantee to preserve the entry count below the value + * - This routine does not guarantee adding memory since it may fail + * to allocate memory. This does not affect the system consistency. + */ +void nbqs_add_rnc(char *name, struct net_device *dev, unsigned char *mac) +{ + rnc_t *nb_rnc; + + spin_lock(&rnc_list_lock); + nb_rnc = __nbqs_find_rnc(name); + if (nb_rnc) { + memcpy(nb_rnc->mac, mac, 6); + nb_rnc->dev = dev; + nb_rnc->time_stamp = jiffies; + } + if (rnc_count >= NETBEUI_QUERY_MAX_CACHE_ENTRIES) + __nbqs_cleanup_rnc(); + nb_rnc = kmalloc(sizeof(rnc_t), GFP_KERNEL); + if (!nb_rnc) + goto out; + rnc_count++; + memcpy(nb_rnc->name, name, NETBEUI_NAME_LEN); + memcpy(nb_rnc->mac, mac, 6); + nb_rnc->dev = dev; + nb_rnc->time_stamp = jiffies; + if (rnc_list) { + rnc_list->prev = nb_rnc; + nb_rnc->next = rnc_list; + nb_rnc->prev = NULL; + rnc_list = nb_rnc; + } else { + rnc_list = nb_rnc; + nb_rnc->next = nb_rnc->prev = NULL; + } +out: spin_unlock(&rnc_list_lock); +} + +/* + * Function: nbqs_delete_rnc + * This is a wrapper to nbqs_remove_rnc which both remove entry from + * remote name cache and deallocates memory. + * + * Parameters: + * name : NetBIOS name of remote node to remove its rnc_t + * + * Returns: none + */ +void nbqs_delete_rnc(char *name) +{ + rnc_t *nb_rnc; + + spin_lock(&rnc_list_lock); + nb_rnc = __nbqs_find_rnc(name); + if (nb_rnc) { + __nbqs_remove_rnc(nb_rnc); + kfree(nb_rnc); + rnc_count--; + } + spin_unlock(&rnc_list_lock); +} + +/* + * Query service state machine functions + * Implementing general functions + */ +/* + * Function: nbqs_alloc_query + * Allocates a query_t structure and does completely initialize all fields + * + * Parameters: none + * + * Returns: + * NULL : if can not allocate memory for query_t or its sk_buff + * non-NULL: pointer to query_t + * + * Notes: + * - An skb is attached to each new query for query processing purposes + * - query timer is initialized but not started. + * - The call to memset does implicitly initialize all fields. Those + * fields that need explicit non-zero initialization are manipulated + * afterwards. + */ +static query_t *nbqs_alloc_query(void) +{ + int name_dgram_len; + query_t *nb_query = kmalloc(sizeof(*nb_query), GFP_KERNEL); + + if (!nb_query) + goto out; + /* Implicitly initialize all fields */ + memset(nb_query, 0, sizeof(*nb_query)); + init_timer(&nb_query->timer); + nb_query->timer.data = (unsigned long)nb_query; + nb_query->timer.function = nbqs_timer_function; + init_waitqueue_head(&nb_query->waitq); + + /* Allocate query skb */ + /* All commands use same length */ + name_dgram_len = nb_cmd_hdr_len[NETBEUI_NAME_QUERY]; + nb_query->skb = alloc_skb(CALC_DG_SKBLEN(NETBEUI_MAC_B_HEADLEN, + name_dgram_len), GFP_KERNEL); + if (!nb_query->skb) + goto err; + skb_reserve(nb_query->skb, LLCMAC_UIB_HEADLEN()); + nb_query->skb->nh.raw = nb_query->skb->h.raw = nb_query->skb->data; + skb_put(nb_query->skb, name_dgram_len); + nb_query->skb->dev = NULL; +out: return nb_query; +err: kfree(nb_query); + nb_query = NULL; + goto out; +} + +/* + * Function: nbqs_free_query + * Deallocates memory used for a query_t and its sk_buff + * + * Parameters: + * nb_query : pointer to query_t memory to be freed + * + * Returns: none + */ +static inline void nbqs_free_query(query_t *nb_query) +{ + kfree_skb(nb_query->skb); + kfree(nb_query); +} + +/* + * Function: nbqs_add_query_to_list + * Inserts a previously allocated/initialized query_t into query list + * + * Parameters: + * nb_query : pointer to query_t to insert + * + * Returns: + * 0 : always returns zero + */ +static inline int nbqs_add_query_to_list(query_t *nb_query) +{ + write_lock(&query_list_lock); + nb_query->next = query_list; + query_list = nb_query; + write_unlock(&query_list_lock); + return 0; +} + +/* + * Function: nbqs_remove_query_from_list + * Removes a query_t from query list + * + * Parameters: + * nb_query : pointer to query_t to remove + * + * Returns: none + */ +static void nbqs_remove_query_from_list(query_t *nb_query) +{ + query_t *entry, *prev_entry = NULL; + + write_lock(&query_list_lock); + entry = query_list; + while (entry) { + if (entry == nb_query) { + if (prev_entry) + prev_entry->next = entry->next; + else + query_list = entry->next; + break; + } + prev_entry = entry; + entry = entry->next; + } + write_unlock(&query_list_lock); +} + +/* + * Function: nbqs_find_correlator + * finds a query_t in query_list, which has transmitted frames with + * specific correlator. + * + * Parameters: + * correlator: a sixteen bit integer which contains the response + * correlator of input frame. It should be matched against + * xmit correlator of frames sent by the element. + * + * Returns: + * NULL : if no query_t element found with the requested + * characteristic. + * non-NULL : pointer to matching query_t with the requested + * characteristic. + */ +static query_t *nbqs_find_correlator(unsigned short correlator) +{ + query_t *nb_query; + + read_lock(&query_list_lock); + nb_query = query_list; + while (nb_query) { + if (nb_query->resp_correlator == correlator) + break; + nb_query = nb_query->next; + } + read_unlock(&query_list_lock); + return nb_query; +} + +/* + * Function: nbqs_boradcast_name_query + * Prepares a NetBIOS NAME QUERY frames and nbll_uisends it to network. + * + * Parameters: + * nb_query : pointer to query_t element which the frame should be built + * from + * + * Returns: + * 0 : if frame is successfully broadcasted to network + * non-zero : if frame transmission encountered an error (usually at NDI + * layer) + * + * Notes: + * - Since ADD NAME QUERY frames are retransmitted in timed intervals, it + * is considered to build frame once, but transmit it multiple times. + * having built frames in each retransmission does generate multiple + * correlators and does frustrate processing responses. + */ +static int nbqs_broadcast_name_query(query_t *nb_query) +{ + if (!nb_query->retries) { + dgram_t *hdr = (dgram_t *)nb_query->skb->data; + + hdr->length = nb_cmd_hdr_len[NETBEUI_NAME_QUERY]; + hdr->delimiter = NETBEUI_DELIMITER; + hdr->command = NETBEUI_NAME_QUERY; + hdr->data1 = 0; + if (nb_query->lsn > 0) + hdr->data2 = + NETBEUI_CALL_DATA2(nb_query->calling_name->type, + nb_query->lsn); + else + hdr->data2 = 0; + hdr->xmit_correlator = 0; + hdr->resp_correlator = + nb_query->resp_correlator = nbqs_next_correlator(); + memcpy(hdr->dest_name, nb_query->called_name, NETBEUI_NAME_LEN); + if (nb_query->lsn > 0) + memcpy(hdr->source_name, nb_query->calling_name->name, + NETBEUI_NAME_LEN); + else + memset(hdr->source_name, 0, NETBEUI_NAME_LEN); + } + return nbll_uisend(NULL, nb_query->skb); +} + +/* + * Function: nbqs_handle_event + * This is the heart of Query Service State Machine, which performs a + * transition from current state of query element to new state based + * on event occurred and query state table contents. + * + * Parameters: + * event : An integer of NETBEUI_QUERY_* family that implies type of + * event + * nb_name : pointer to query_t structure which the event occurred on + * + * Returns: none + * + * Notes: + * - The state changes before actions be executed. This is due to + * non deterministic behavior of actions which may sleep the current + * process, thus stopping the function in the mid-way. + */ +static void nbqs_handle_event(query_event_t event, query_t *nb_query) +{ + struct event_struct *ev = &query_state_table[nb_query->state][event]; + + if (ev && ev->event_handler) { + unsigned char old_state = nb_query->state; + + nb_query->state = ev->next_state; + if (ev->event_handler(nb_query)) + nb_query->state = old_state; + } +} + +/* + * Function: nbqs_timer_function + * This is the callback function triggered upon expiration of name + * retransmittion timer. It just injects an event into state machine for + * its link. + * + * Parameters: + * input : pointer to query_t structure whose timer is expired. + * + * Returns: none + */ +static void nbqs_timer_function(unsigned long input) +{ + query_t *nb_query = (query_t *)input; + + if (nb_query->retries < NETBEUI_TRANSMIT_COUNT) + nbqs_handle_event(NETBEUI_QUERY_RETRY_TIMEOUT, nb_query); + else + nbqs_handle_event(NETBEUI_QUERY_RESPONSE_TIMEOUT, nb_query); +} + +/* + * Query service state machine functions + * Implementing transition actions + */ +/* + * Function: nbqs_xxxx_in_ssss + * The section below contains functions that implement actions needed + * to legally transit from one state to another. + * + * Parameters: + * nb_query: pointer to query_t structure which the actions are to be + * applied to + * + * Returns: + * 0 : if all actions are done successfully + * non-zero: if one of actions failed + * + * Note: + * - For the sake of simplicity, the actions are automatically rollbacked + * in each function, if an action in transition fails. The design + * documents do not cover these parts of code. + */ +static int nbqs_name_query_in_initial(query_t *nb_query) +{ + nb_query->retries = nb_query->responses = 0; + + if (nbqs_broadcast_name_query(nb_query)) + return -ENOMEM; + nb_query->retries++; + nb_query->timer.expires = jiffies + NETBEUI_TRANSMIT_TIMEOUT; + add_timer(&nb_query->timer); + nbqs_add_query_to_list(nb_query); + sleep_on(&nb_query->waitq); + return 0; +} + +static int nbqs_name_find_in_initial(query_t *nb_query) +{ + nb_query->retries = nb_query->responses = nb_query->buff_ofs = 0; + + if (nbqs_broadcast_name_query(nb_query)) + return -ENOMEM; + nb_query->retries++; + nb_query->timer.expires = jiffies + NETBEUI_TRANSMIT_TIMEOUT; + add_timer(&nb_query->timer); + nbqs_add_query_to_list(nb_query); + sleep_on(&nb_query->waitq); + return 0; +} + +static int nbqs_retry_timeout_in_all(query_t *nb_query) +{ + nb_query->timer.expires = jiffies + NETBEUI_TRANSMIT_TIMEOUT; + add_timer(&nb_query->timer); + + if (nbqs_broadcast_name_query(nb_query)) + return -ENOMEM; + nb_query->retries++; + return 0; +} + +static int nbqs_response_timeout_in_all(query_t *nb_query) +{ + wake_up(&nb_query->waitq); + nbqs_remove_query_from_list(nb_query); + return 0; +} + +static int nbqs_name_recognized_in_qrywait(query_t *nb_query) +{ + del_timer(&nb_query->timer); + wake_up(&nb_query->waitq); + nbqs_remove_query_from_list(nb_query); + return 0; +} + +static int nbqs_name_recognized_in_findwait(query_t *nb_query) +{ + /* Here we should add the MAC header to buffer, considering + * unicity of resp */ + int i; + struct net_device *dev; + char *mac_buff = nb_query->mac_buff; + + for (i = 0; i < nb_query->buff_ofs; i++) { + dev = nb_query->dev_buff[i]; + + if (nb_query->dev == dev && + !memcmp(nb_query->remote_mac, mac_buff, dev->addr_len)) + return 0; + mac_buff += dev->addr_len; + } + if (nb_query->buff_ofs < nb_query->buff_len) { + dev = nb_query->dev; + nb_query->dev_buff[nb_query->buff_ofs] = dev; + memcpy(mac_buff, nb_query->remote_mac, dev->addr_len); + nb_query->buff_ofs++; + } + return 0; +} + +static int nbqs_end_query_in_name_recognized(query_t *nb_query) +{ + return 0; +} + +/* + * Query service state machine functions + * Implementing interface functions + */ +/* + * Function: nbqs_query_name + * Does the first step of session establishment process and determines + * remote session number, Largest Frame Bits and response correlator for + * further negotiations. + * + * Parameters: + * called_name : pointer to NetBIOS name of remote node + * calling_name : pointer to name_t element registered locally + * lsn : local session number + * rsn : (VRP) pointer to remote session number + * valid if return value is zero + * lfb : (VRP) pointer to Largest Frame Bits (for support of + * Token-Ring) + * xmit_correlator: (VRP) pointer to xmit correlator found in NAME RESPONSE + * valid if return value is zero + * + * Returns: + * 0 : if query was successful + * -EINVAL : if called_name is not a valid NetBIOS name + * -ENOMEM : if memory allocation for query_t element failed + * -ETIMEDOUT: if remote node did not respond + */ +int nbqs_query_name(char *called_name, name_t *calling_name, unsigned char lsn, + unsigned char *rsn, unsigned char *lfb, + unsigned short *xmit_correlator) +{ + query_t *nb_query; + + if (nbns_validate_name(called_name)) + return -EINVAL; + nb_query = nbqs_alloc_query(); + if (!nb_query) + return -ENOMEM; + nb_query->state = NETBEUI_QUERY_INITIAL; + nb_query->calling_name = calling_name; + memcpy(nb_query->called_name, called_name, NETBEUI_NAME_LEN); + nb_query->lsn = lsn; + nbqs_handle_event(NETBEUI_QUERY_NAME_QUERY, nb_query); + + if (nb_query->state != NETBEUI_QUERY_RECOGNIZED) { + nbqs_free_query(nb_query); + return -ETIMEDOUT; + } + *rsn = nb_query->rsn; + *lfb = nb_query->tr_lfb; + *xmit_correlator = nb_query->xmit_correlator; + nbqs_handle_event(NETBEUI_QUERY_END_QUERY, nb_query); + nbqs_free_query(nb_query); + return 0; +} + +/* + * Function: nbqs_find_name + * This is NAME FIND interface which determines MAC address of a remote + * node with a specific name. It also finds the device which connects + * the host with remote node. + * + * Parameters: + * called_name : pointer to NetBIOS name of remote node + * mac_buff : pointer to array of MAC buffers + * dev_buff : pointer to array of device pointers + * buff_len : maximum number of entries in mac_buff and dev_buff arrays + * + * Returns: + * >= 0 : count of dev_buff and mac_buff entries corresponding to + * to nodes which own called_name + * -EINVAL : if called_name is not a valid NetBIOS name + * -ENOMEM : if memory allocation for query_t element failed + * + * Notes: + * - This routines is the point in which RNC cache is used for NetBIOS + * name resolution. The consistency of cache contents depends on + * upper layers which insert/delete cache entries. + */ +int nbqs_find_name(char *called_name, char *mac_buff, + struct net_device **dev_buff, int buff_len) +{ + int names_found; + query_t *nb_query; + rnc_t *nb_rnc; + + if (nbns_validate_name(called_name)) + return -EINVAL; + nb_rnc = nbqs_find_rnc(called_name); + if (nb_rnc) { + *dev_buff = nb_rnc->dev; + memcpy(mac_buff, nb_rnc->mac, 6); + return 1; + } + nb_query = nbqs_alloc_query(); + if (!nb_query) + return -ENOMEM; + nb_query->state = NETBEUI_QUERY_INITIAL; + nb_query->calling_name = NULL; + memcpy(nb_query->called_name, called_name, NETBEUI_NAME_LEN); + nb_query->lsn = 0; + nb_query->mac_buff = mac_buff; + nb_query->dev_buff = dev_buff; + nb_query->buff_len = buff_len; + nbqs_handle_event(NETBEUI_QUERY_NAME_FIND, nb_query); + names_found = nb_query->buff_ofs; + nbqs_free_query(nb_query); + if (names_found > 0) + nbqs_add_rnc(called_name, *dev_buff, mac_buff); + return names_found; +} + +void nbqs_get_name_recognized(struct sk_buff *skb, unsigned char *remote_mac) +{ + dgram_t *dgram = (dgram_t *)skb->data; + unsigned short data2 = dgram->data2; + query_t *nb_query = nbqs_find_correlator(dgram->xmit_correlator); + + /* If it does not match a query */ + if (!nb_query) + goto out; + nb_query->rsn = NETBEUI_CALL_SS(data2); + nb_query->dev = skb->dev; + memcpy(nb_query->remote_mac, remote_mac, 6); + nb_query->xmit_correlator = dgram->resp_correlator; + nb_query->tr_lfb = skb->cb[0]; /* Token Ring support */ + nb_query->responses++; + /* We should also set mac_header */ + nbqs_handle_event(NETBEUI_QUERY_NAME_RECOGNIZED, nb_query); +out: kfree_skb(skb); +} Index: kernel-acme/net/netbeui/session_serve.c diff -u /dev/null kernel-acme/net/netbeui/session_serve.c:1.1.12.1 --- /dev/null Sat Dec 22 02:21:25 2001 +++ kernel-acme/net/netbeui/session_serve.c Thu Nov 29 20:36:57 2001 @@ -0,0 +1,2821 @@ +/* + * session_serve.c - Contains functions that implement NetBIOS Session Service + * + * Important Note: + * - Consider the following design issues when reading session service + * sources + * 1- Session Establishment, Session Termination and Session Data + * Output Stream are joined to from the Session States + * 2- Session Data Input Stream does is not implemented in State + * Machine model, it is simply a buffering and acknowledgement + * mechanism. + * Notes: + * - VRP in comments is the acronym of "Value Result Parameter" + * - Session Service is the most complicated service in NetBIOS. Numerous + * states and events used for session establishment, session data + * transfer and session termination need to much effort to overcome. + * Please read documentations before changing even a bit (!) in source + * codes. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define dprintk(format, a...) \ + printk(KERN_INFO __FUNCTION__ ": " format, ##a) + +extern int llc_in_progress; + +/* These functions are used for locking sessions to avoid race conditions */ +static void nbss_lock_session(session_t *session); +static int nbss_release_session(session_t *session); + +static void nbss_wait_timer_function(unsigned long input); +static void nbss_resource_timer_function(unsigned long input); + +/* These functions are Session Service State Transition handlers */ +static int nbss_event_abort_send_in_all(session_t *session); +static int nbss_event_call_in_initial(session_t *session); +static int nbss_event_listen_in_initial(session_t *session); + +static int nbss_event_confirm_in_callwait(session_t *session); +static int nbss_event_reject_in_callwait(session_t *session); +static int nbss_event_abort_in_callwait(session_t *session); + +static int nbss_event_connect_in_confwait(session_t *session); +static int nbss_event_timeout_in_confwait(session_t *session); +static int nbss_event_abort_in_confwait(session_t *session); + +static int nbss_event_confirm_in_listenwait(session_t *session); +static int nbss_event_reject_in_listenwait(session_t *session); + +static int nbss_event_connect_in_initwait(session_t *session); +static int nbss_event_timeout_in_initwait(session_t *session); +static int nbss_event_reject_in_initwait(session_t *session); +static int nbss_event_abort_in_initwait(session_t *session); + +static int nbss_event_hangup_in_connected(session_t *session); +static int nbss_event_first_middle_cont_in_connected(session_t *session); +static int nbss_event_first_middle_in_connected(session_t *session); +static int nbss_event_only_last_ack_in_connected(session_t *session); +static int nbss_event_only_last_in_connected(session_t *session); +static int nbss_event_resource_in_connected(session_t *session); +static int nbss_event_end_in_connected(session_t *session); +static int nbss_event_abort_in_connected(session_t *session); + +static int nbss_event_hangup_in_discwait(session_t *session); + +static int nbss_event_continue_in_contwait(session_t *session); +static int nbss_event_restart_in_contwait(session_t *session); +static int nbss_event_pause_in_contwait(session_t *session); +static int nbss_event_nonblock_in_contwait(session_t *session); + +static int nbss_event_restart_in_standwait(session_t *session); +static int nbss_event_pause2_in_standwait(session_t *session); + +static int nbss_event_data_acked_in_ackwait(session_t *session); +static int nbss_event_restart_in_ackwait(session_t *session); +static int nbss_event_pause_in_ackwait(session_t *session); +static int nbss_event_nonblock_in_ackwait(session_t *session); + +static int nbss_event_norm_retry_in_rsrcwait(session_t *session); +static int nbss_event_conn_retry_in_rsrcwait(session_t *session); + +static int nbss_event_first_middle_in_normal(session_t *session); +static int nbss_event_only_last_ack_in_normal(session_t *session); +static int nbss_event_only_last_in_normal(session_t *session); +static int nbss_event_pause_in_normal(session_t *session); +static int nbss_event_restart_in_normal(session_t *session); +static int nbss_event_resource_in_normal(session_t *session); +static int nbss_event_nonblock_in_normal(session_t *session); + +static unsigned short int nbss_correlator; +#define nbss_next_correlator() (++nbss_correlator) + +/* This is a list for pending session listened for incoming session + * establishment requests */ +static session_t *session_list; +static spinlock_t session_list_lock = SPIN_LOCK_UNLOCKED; + +/* Session service state machine definition */ +typedef int (*session_event_handler_t)(session_t *session); + +struct event_struct { + session_state_t next_state; + session_event_handler_t event_handler; +}; + +static struct event_struct session_state_table[12][23] = { + /* NETBEUI_SESS_INITIAL */ +{ +{ NETBEUI_SESS_CALLWAIT, + nbss_event_call_in_initial }, /* NETBEUI_SESS_CALL */ +{ NETBEUI_SESS_LISTENWAIT, + nbss_event_listen_in_initial }, /* NETBEUI_SESS_LISTEN */ +{ -1, NULL }, /* NETBEUI_SESS_CONFIRM */ +{ -1, NULL }, /* NETBEUI_SESS_REJ */ +{ -1, NULL }, /* NETBEUI_SESS_CONNECT */ +{ -1, NULL }, /* NETBEUI_SESS_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_SESS_ABORT */ +{ -1, NULL }, /* NETBEUI_SESS_HANGUP */ +{ -1, NULL }, /* NETBEUI_SESS_END */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE_CONT */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE */ +{ -1, NULL }, /* NETBEUI_SESS_CONTINUE */ +{ -1, NULL }, /* NETBEUI_SESS_NONBLOCK */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE2 */ +{ -1, NULL }, /* NETBEUI_SESS_RESTART */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST_ACK */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST */ +{ -1, NULL }, /* NETBEUI_SESS_DATA_ACKED */ +{ -1, NULL }, /* NETBEUI_SESS_RESOURCE */ +{ -1, NULL }, /* NETBEUI_SESS_CONN_RETRY */ +{ -1, NULL }, /* NETBEUI_SESS_NORM_RETRY */ +{ -1, NULL } /* NETBEUI_SESS_ABORT_SEND */ +}, + /* NETBEUI_SESS_CALLWAIT */ +{ +{ -1, NULL }, /* NETBEUI_SESS_CALL */ +{ -1, NULL }, /* NETBEUI_SESS_LISTEN */ +{ NETBEUI_SESS_CONFWAIT, + nbss_event_confirm_in_callwait },/* NETBEUI_SESS_CONFIRM */ +{ NETBEUI_SESS_INITIAL, + nbss_event_reject_in_callwait },/* NETBEUI_SESS_REJ */ +{ -1, NULL }, /* NETBEUI_SESS_CONNECT */ +{ -1, NULL }, /* NETBEUI_SESS_TIMEOUT */ +{ NETBEUI_SESS_INITIAL, + nbss_event_abort_in_callwait }, /* NETBEUI_SESS_ABORT */ +{ -1, NULL }, /* NETBEUI_SESS_HANGUP */ +{ -1, NULL }, /* NETBEUI_SESS_END */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE_CONT */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE */ +{ -1, NULL }, /* NETBEUI_SESS_CONTINUE */ +{ -1, NULL }, /* NETBEUI_SESS_NONBLOCK */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE2 */ +{ -1, NULL }, /* NETBEUI_SESS_RESTART */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST_ACK */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST */ +{ -1, NULL }, /* NETBEUI_SESS_DATA_ACKED */ +{ -1, NULL }, /* NETBEUI_SESS_RESOURCE */ +{ -1, NULL }, /* NETBEUI_SESS_CONN_RETRY */ +{ -1, NULL }, /* NETBEUI_SESS_NORM_RETRY */ +{ -1, NULL } /* NETBEUI_SESS_ABORT_SEND */ +}, + /* NETBEUI_SESS_CONFWAIT */ +{ +{ -1, NULL }, /* NETBEUI_SESS_CALL */ +{ -1, NULL }, /* NETBEUI_SESS_LISTEN */ +{ -1, NULL }, /* NETBEUI_SESS_CONFIRM */ +{ -1, NULL }, /* NETBEUI_SESS_REJ */ +{ NETBEUI_SESS_CONNECTED, + nbss_event_connect_in_confwait },/* NETBEUI_SESS_CONNECT */ +{ NETBEUI_SESS_INITIAL, + nbss_event_timeout_in_confwait },/* NETBEUI_SESS_TIMEOUT */ +{ NETBEUI_SESS_INITIAL, + nbss_event_abort_in_confwait }, /* NETBEUI_SESS_ABORT */ +{ -1, NULL }, /* NETBEUI_SESS_HANGUP */ +{ -1, NULL }, /* NETBEUI_SESS_END */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE_CONT */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE */ +{ -1, NULL }, /* NETBEUI_SESS_CONTINUE */ +{ -1, NULL }, /* NETBEUI_SESS_NONBLOCK */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE2 */ +{ -1, NULL }, /* NETBEUI_SESS_RESTART */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST_ACK */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST */ +{ -1, NULL }, /* NETBEUI_SESS_DATA_ACKED */ +{ -1, NULL }, /* NETBEUI_SESS_RESOURCE */ +{ -1, NULL }, /* NETBEUI_SESS_CONN_RETRY */ +{ -1, NULL }, /* NETBEUI_SESS_NORM_RETRY */ +{ -1, NULL } /* NETBEUI_SESS_ABORT_SEND */ +}, + /* NETBEUI_SESS_LISTENWAIT */ +{ +{ -1, NULL }, /* NETBEUI_SESS_CALL */ +{ -1, NULL }, /* NETBEUI_SESS_LISTEN */ +{ NETBEUI_SESS_INITWAIT, + nbss_event_confirm_in_listenwait },/* NETBEUI_SESS_CONFIRM */ +{ NETBEUI_SESS_INITIAL, + nbss_event_reject_in_listenwait },/* NETBEUI_SESS_REJ */ +{ -1, NULL }, /* NETBEUI_SESS_CONNECT */ +{ -1, NULL }, /* NETBEUI_SESS_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_SESS_ABORT */ +{ -1, NULL }, /* NETBEUI_SESS_HANGUP */ +{ -1, NULL }, /* NETBEUI_SESS_END */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE_CONT */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE */ +{ -1, NULL }, /* NETBEUI_SESS_CONTINUE */ +{ -1, NULL }, /* NETBEUI_SESS_NONBLOCK */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE2 */ +{ -1, NULL }, /* NETBEUI_SESS_RESTART */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST_ACK */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST */ +{ -1, NULL }, /* NETBEUI_SESS_DATA_ACKED */ +{ -1, NULL }, /* NETBEUI_SESS_RESOURCE */ +{ -1, NULL }, /* NETBEUI_SESS_CONN_RETRY */ +{ -1, NULL }, /* NETBEUI_SESS_NORM_RETRY */ +{ -1, NULL } /* NETBEUI_SESS_ABORT_SEND */ +}, + /* NETBEUI_SESS_INITWAIT */ +{ +{ -1, NULL }, /* NETBEUI_SESS_CALL */ +{ -1, NULL }, /* NETBEUI_SESS_LISTEN */ +{ -1, NULL }, /* NETBEUI_SESS_CONFIRM */ +{ NETBEUI_SESS_INITIAL, + nbss_event_reject_in_initwait },/* NETBEUI_SESS_REJ */ +{ NETBEUI_SESS_CONNECTED, + nbss_event_connect_in_initwait },/* NETBEUI_SESS_CONNECT */ +{ NETBEUI_SESS_LISTENWAIT, + nbss_event_timeout_in_initwait },/* NETBEUI_SESS_TIMEOUT */ +{ NETBEUI_SESS_LISTENWAIT, + nbss_event_abort_in_initwait }, /* NETBEUI_SESS_ABORT */ +{ -1, NULL }, /* NETBEUI_SESS_HANGUP */ +{ -1, NULL }, /* NETBEUI_SESS_END */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE_CONT */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE */ +{ -1, NULL }, /* NETBEUI_SESS_CONTINUE */ +{ -1, NULL }, /* NETBEUI_SESS_NONBLOCK */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE2 */ +{ -1, NULL }, /* NETBEUI_SESS_RESTART */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST_ACK */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST */ +{ -1, NULL }, /* NETBEUI_SESS_DATA_ACKED */ +{ -1, NULL }, /* NETBEUI_SESS_RESOURCE */ +{ -1, NULL }, /* NETBEUI_SESS_CONN_RETRY */ +{ -1, NULL }, /* NETBEUI_SESS_NORM_RETRY */ +{ -1, NULL } /* NETBEUI_SESS_ABORT_SEND */ +}, + /* NETBEUI_SESS_CONNECTED */ +{ +{ -1, NULL }, /* NETBEUI_SESS_CALL */ +{ -1, NULL }, /* NETBEUI_SESS_LISTEN */ +{ -1, NULL }, /* NETBEUI_SESS_CONFIRM */ +{ -1, NULL }, /* NETBEUI_SESS_REJ */ +{ -1, NULL }, /* NETBEUI_SESS_CONNECT */ +{ -1, NULL }, /* NETBEUI_SESS_TIMEOUT */ +{ NETBEUI_SESS_DISCWAIT, + nbss_event_abort_in_connected },/* NETBEUI_SESS_ABORT */ +{ NETBEUI_SESS_INITIAL, + nbss_event_hangup_in_connected },/* NETBEUI_SESS_HANGUP */ +{ NETBEUI_SESS_DISCWAIT, + nbss_event_end_in_connected }, /* NETBEUI_SESS_END */ +{ NETBEUI_SESS_CONTWAIT, + nbss_event_first_middle_cont_in_connected }, /* NETBEUI_SESS_FIRST_MIDDLE_CONT */ +{ NETBEUI_SESS_NORMAL, + nbss_event_first_middle_in_connected }, /* NETBEUI_SESS_FIRST_MIDDLE */ +{ -1, NULL }, /* NETBEUI_SESS_CONTINUE */ +{ -1, NULL }, /* NETBEUI_SESS_NONBLOCK */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE2 */ +{ -1, NULL }, /* NETBEUI_SESS_RESTART */ +{ NETBEUI_SESS_ACKWAIT, + nbss_event_only_last_ack_in_connected }, /* NETBEUI_SESS_ONLY_LAST_ACK */ +{ NETBEUI_SESS_CONNECTED, + nbss_event_only_last_in_connected },/* NETBEUI_SESS_ONLY_LAST */ +{ -1, NULL }, /* NETBEUI_SESS_DATA_ACKED */ +{ NETBEUI_SESS_RSRCWAIT, + nbss_event_resource_in_connected },/* NETBEUI_SESS_RESOURCE */ +{ -1, NULL }, /* NETBEUI_SESS_CONN_RETRY */ +{ -1, NULL }, /* NETBEUI_SESS_NORM_RETRY */ +{ -1, NULL } /* NETBEUI_SESS_ABORT_SEND */ +}, + /* NETBEUI_SESS_DISCWAIT */ +{ +{ -1, NULL }, /* NETBEUI_SESS_CALL */ +{ -1, NULL }, /* NETBEUI_SESS_LISTEN */ +{ -1, NULL }, /* NETBEUI_SESS_CONFIRM */ +{ -1, NULL }, /* NETBEUI_SESS_REJ */ +{ -1, NULL }, /* NETBEUI_SESS_CONNECT */ +{ -1, NULL }, /* NETBEUI_SESS_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_SESS_ABORT */ +{ NETBEUI_SESS_INITIAL, + nbss_event_hangup_in_discwait }, /* NETBEUI_SESS_HANGUP */ +{ -1, NULL }, /* NETBEUI_SESS_END */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE_CONT */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE */ +{ -1, NULL }, /* NETBEUI_SESS_CONTINUE */ +{ -1, NULL }, /* NETBEUI_SESS_NONBLOCK */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE2 */ +{ -1, NULL }, /* NETBEUI_SESS_RESTART */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST_ACK */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST */ +{ -1, NULL }, /* NETBEUI_SESS_DATA_ACKED */ +{ -1, NULL }, /* NETBEUI_SESS_RESOURCE */ +{ -1, NULL }, /* NETBEUI_SESS_CONN_RETRY */ +{ -1, NULL }, /* NETBEUI_SESS_NORM_RETRY */ +{ -1, NULL } /* NETBEUI_SESS_ABORT_SEND */ +}, + /* NETBEUI_SESS_CONTWAIT */ +{ +{ -1, NULL }, /* NETBEUI_SESS_CALL */ +{ -1, NULL }, /* NETBEUI_SESS_LISTEN */ +{ -1, NULL }, /* NETBEUI_SESS_CONFIRM */ +{ -1, NULL }, /* NETBEUI_SESS_REJ */ +{ -1, NULL }, /* NETBEUI_SESS_CONNECT */ +{ -1, NULL }, /* NETBEUI_SESS_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_SESS_ABORT */ +{ -1, NULL }, /* NETBEUI_SESS_HANGUP */ +{ -1, NULL }, /* NETBEUI_SESS_END */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE_CONT */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE */ +{ NETBEUI_SESS_NORMAL, + nbss_event_continue_in_contwait },/* NETBEUI_SESS_CONTINUE */ +{ NETBEUI_SESS_CONNECTED, + nbss_event_nonblock_in_contwait },/* NETBEUI_SESS_NONBLOCK */ +{ NETBEUI_SESS_STANDWAIT, + nbss_event_pause_in_contwait }, /* NETBEUI_SESS_PAUSE */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE2 */ +{ NETBEUI_SESS_NORMAL, + nbss_event_restart_in_contwait },/* NETBEUI_SESS_RESTART */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST_ACK */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST */ +{ -1, NULL }, /* NETBEUI_SESS_DATA_ACKED */ +{ -1, NULL }, /* NETBEUI_SESS_RESOURCE */ +{ -1, NULL }, /* NETBEUI_SESS_CONN_RETRY */ +{ -1, NULL }, /* NETBEUI_SESS_NORM_RETRY */ +{ NETBEUI_SESS_CONNECTED, + nbss_event_abort_send_in_all } /* NETBEUI_SESS_ABORT_SEND */ +}, + /* NETBEUI_SESS_STANDWAIT */ +{ +{ -1, NULL }, /* NETBEUI_SESS_CALL */ +{ -1, NULL }, /* NETBEUI_SESS_LISTEN */ +{ -1, NULL }, /* NETBEUI_SESS_CONFIRM */ +{ -1, NULL }, /* NETBEUI_SESS_REJ */ +{ -1, NULL }, /* NETBEUI_SESS_CONNECT */ +{ -1, NULL }, /* NETBEUI_SESS_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_SESS_ABORT */ +{ -1, NULL }, /* NETBEUI_SESS_HANGUP */ +{ -1, NULL }, /* NETBEUI_SESS_END */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE_CONT */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE */ +{ -1, NULL }, /* NETBEUI_SESS_CONTINUE */ +{ -1, NULL }, /* NETBEUI_SESS_NONBLOCK */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE */ +{ NETBEUI_SESS_STANDWAIT, + nbss_event_pause2_in_standwait },/* NETBEUI_SESS_PAUSE2 */ +{ NETBEUI_SESS_NORMAL, + nbss_event_restart_in_standwait },/* NETBEUI_SESS_RESTART */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST_ACK */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST */ +{ -1, NULL }, /* NETBEUI_SESS_DATA_ACKED */ +{ -1, NULL }, /* NETBEUI_SESS_RESOURCE */ +{ -1, NULL }, /* NETBEUI_SESS_CONN_RETRY */ +{ -1, NULL }, /* NETBEUI_SESS_NORM_RETRY */ +{ NETBEUI_SESS_CONNECTED, + nbss_event_abort_send_in_all } /* NETBEUI_SESS_ABORT_SEND */ +}, + /* NETBEUI_SESS_ACKWAIT */ +{ +{ -1, NULL }, /* NETBEUI_SESS_CALL */ +{ -1, NULL }, /* NETBEUI_SESS_LISTEN */ +{ -1, NULL }, /* NETBEUI_SESS_CONFIRM */ +{ -1, NULL }, /* NETBEUI_SESS_REJ */ +{ -1, NULL }, /* NETBEUI_SESS_CONNECT */ +{ -1, NULL }, /* NETBEUI_SESS_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_SESS_ABORT */ +{ -1, NULL }, /* NETBEUI_SESS_HANGUP */ +{ -1, NULL }, /* NETBEUI_SESS_END */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE_CONT */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE */ +{ -1, NULL }, /* NETBEUI_SESS_CONTINUE */ +{ NETBEUI_SESS_CONNECTED, + nbss_event_nonblock_in_ackwait },/* NETBEUI_SESS_NONBLOCK */ +{ NETBEUI_SESS_STANDWAIT, + nbss_event_pause_in_ackwait }, /* NETBEUI_SESS_PAUSE */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE2 */ +{ NETBEUI_SESS_NORMAL, + nbss_event_restart_in_ackwait },/* NETBEUI_SESS_RESTART */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST_ACK */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST */ +{ NETBEUI_SESS_CONNECTED, + nbss_event_data_acked_in_ackwait },/* NETBEUI_SESS_DATA_ACKED */ +{ -1, NULL }, /* NETBEUI_SESS_RESOURCE */ +{ -1, NULL }, /* NETBEUI_SESS_CONN_RETRY */ +{ -1, NULL }, /* NETBEUI_SESS_NORM_RETRY */ +{ NETBEUI_SESS_CONNECTED, + nbss_event_abort_send_in_all } /* NETBEUI_SESS_ABORT_SEND */ +}, + /* NETBEUI_SESS_RSRCAIT */ +{ +{ -1, NULL }, /* NETBEUI_SESS_CALL */ +{ -1, NULL }, /* NETBEUI_SESS_LISTEN */ +{ -1, NULL }, /* NETBEUI_SESS_CONFIRM */ +{ -1, NULL }, /* NETBEUI_SESS_REJ */ +{ -1, NULL }, /* NETBEUI_SESS_CONNECT */ +{ -1, NULL }, /* NETBEUI_SESS_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_SESS_ABORT */ +{ -1, NULL }, /* NETBEUI_SESS_HANGUP */ +{ -1, NULL }, /* NETBEUI_SESS_END */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE_CONT */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE */ +{ -1, NULL }, /* NETBEUI_SESS_CONTINUE */ +{ -1, NULL }, /* NETBEUI_SESS_NONBLOCK */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE2 */ +{ -1, NULL }, /* NETBEUI_SESS_RESTART */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST_ACK */ +{ -1, NULL }, /* NETBEUI_SESS_ONLY_LAST */ +{ -1, NULL }, /* NETBEUI_SESS_DATA_ACKED */ +{ -1, NULL }, /* NETBEUI_SESS_RESOURCE */ +{ NETBEUI_SESS_CONNECTED, + nbss_event_conn_retry_in_rsrcwait },/* NETBEUI_SESS_CONN_RETRY */ +{ NETBEUI_SESS_NORMAL, + nbss_event_norm_retry_in_rsrcwait },/* NETBEUI_SESS_NORM_RETRY */ +{ NETBEUI_SESS_CONNECTED, + nbss_event_abort_send_in_all } /* NETBEUI_SESS_ABORT_SEND */ +}, + /* NETBEUI_SESS_NORMAL */ +{ +{ -1, NULL }, /* NETBEUI_SESS_CALL */ +{ -1, NULL }, /* NETBEUI_SESS_LISTEN */ +{ -1, NULL }, /* NETBEUI_SESS_CONFIRM */ +{ -1, NULL }, /* NETBEUI_SESS_REJ */ +{ -1, NULL }, /* NETBEUI_SESS_CONNECT */ +{ -1, NULL }, /* NETBEUI_SESS_TIMEOUT */ +{ -1, NULL }, /* NETBEUI_SESS_ABORT */ +{ -1, NULL }, /* NETBEUI_SESS_HANGUP */ +{ -1, NULL }, /* NETBEUI_SESS_END */ +{ -1, NULL }, /* NETBEUI_SESS_FIRST_MIDDLE_CONT */ +{ NETBEUI_SESS_NORMAL, + nbss_event_first_middle_in_normal },/* NETBEUI_SESS_FIRST_MIDDLE */ +{ -1, NULL }, /* NETBEUI_SESS_CONTINUE */ +{ NETBEUI_SESS_CONNECTED, + nbss_event_nonblock_in_normal },/* NETBEUI_SESS_NONBLOCK */ +{ NETBEUI_SESS_STANDWAIT, + nbss_event_pause_in_normal }, /* NETBEUI_SESS_PAUSE */ +{ -1, NULL }, /* NETBEUI_SESS_PAUSE2 */ +{ NETBEUI_SESS_NORMAL, + nbss_event_restart_in_normal }, /* NETBEUI_SESS_RESTART */ +{ NETBEUI_SESS_ACKWAIT, + nbss_event_only_last_ack_in_normal },/* NETBEUI_SESS_ONLY_LAST_ACK */ +{ NETBEUI_SESS_CONNECTED, + nbss_event_only_last_in_normal },/* NETBEUI_SESS_ONLY_LAST */ +{ -1, NULL }, /* NETBEUI_SESS_DATA_ACKED */ +{ NETBEUI_SESS_RSRCWAIT, + nbss_event_resource_in_normal },/* NETBEUI_SESS_RESOURCE */ +{ -1, NULL }, /* NETBEUI_SESS_CONN_RETRY */ +{ -1, NULL }, /* NETBEUI_SESS_NORM_RETRY */ +{ NETBEUI_SESS_CONNECTED, + nbss_event_abort_send_in_all} /* NETBEUI_SESS_ABORT_SEND */ +} +}; + +/* Session service state machine functions */ +/* + * Function: nbss_free_session + * Deallocates memory used for session_t and does a complete housekeeping + * Parameters: + * session: pointer to session_t memory to be freed + * Returns: None + */ +static void nbss_free_session(session_t *session) +{ + skb_queue_purge(&session->back_log); + skb_queue_purge(&session->i_skbq); + kfree(session); +} + +static inline void session_put(session_t *session) +{ + if (atomic_dec_and_test(&session->refcnt)) + nbss_free_session(session); +} + +static inline void session_hold(session_t *session) +{ + atomic_inc(&session->refcnt); +} + +static inline void nbss_wait_event(session_t *session) +{ + set_current_state(TASK_UNINTERRUPTIBLE); + if (!nbss_release_session(session)) + wait_event(session->waitq, (!session->o_txed || + session->o_aborted)); + else + set_current_state(TASK_RUNNING); +} + +/* + * Function: NETBEUI_CALC_SESS_MTU + * Calculates MAXimum length of user data that can send through a + * session, and sets the 'mtu' field of it. + * Parameters: + * sn: pointer to session that calculation is for it. + * Returns: None + */ +static void NETBEUI_CALC_SESS_MTU(session_t *sn) +{ + session_hold(sn); + sn->mtu = sn->dev->type == ARPHRD_LOOPBACK ? 1500 : sn->dev->mtu; + if (sn->dev->type == ARPHRD_IEEE802) { /* Token Ring */ + __u16 dolfb; + + switch (sn->tr_frame_lf) { + case 0x00: dolfb = 516; break; + case 0x01: dolfb = 1470; break; + case 0x02: dolfb = 2052; break; + case 0x03: dolfb = 4399; break; + case 0x04: dolfb = 8130; break; + case 0x05: dolfb = 11407; break; + case 0x06: dolfb = 17749; break; + case 0x07: + default: dolfb = 0xFFFF; break; + } + if (sn->mtu > dolfb) + sn->mtu = dolfb; + } + sn->mtu = sn->mtu - sn->llcmac_ihl - NETBEUI_ILEN; + session_put(sn); +} + +/* + * Function: nbss_alloc_session + * Allocates a session_t structure and does completely initialize all + * fields + * Parameters: None + * Returns: + * NULL : if can not allocate memory for session_t + * non-NULL: pointer to session_t + * Notes: + * - Session timer is initialized but not started. + * - The call to memset does implicitly initialize all fields. Those + * fields that need explicit non-zero initialization are manipulated + * afterwards. + */ +static session_t *nbss_alloc_session(void) +{ + session_t *session = kmalloc(sizeof(*session), GFP_KERNEL); + + if (!session) + goto out; + /* Implicitly initialize all fields */ + memset(session, 0, sizeof(*session)); + init_timer(&session->timer); + session->timer.data = (unsigned long)session; + session->timer.function = nbss_wait_timer_function; + init_waitqueue_head(&session->waitq); + session->version = NETBEUI_VERSION_2xx; + session->nack_indicator = NETBEUI_NACK_ABLE; + skb_queue_head_init(&session->back_log); + skb_queue_head_init(&session->i_skbq); + session->o_receive_continue = 1; + session->i_rcvbuf = 0xFFFF; + atomic_set(&session->refcnt, 1); +out: return session; +} + +/* + * Function: nbss_ack_bytes + * Acknowledges reception of some bytes from input stream, by correctly + * setting control variables of session. + * Parameters: + * session: pointer to session_t whose bytes are to be acknowledged. + * Returns: None + * Notes: + * - This function is used in transition handlers. + * - It does not actually acknowledge byte, it simply justifies + * acknowledgement control variables. + */ +static void nbss_ack_bytes(session_t *session) +{ + unsigned short r_nacked; + + session_hold(session); + r_nacked = session->o_txed - session->r_acked; + session->o_size += r_nacked; + session->o_buff -= r_nacked; + session->o_acked += session->r_acked; + session->o_txed = session->r_acked = 0; + session_put(session); +} + +/* + * Function: nbss_sleep_on + * This is a process control routine and customized version of Linux + * kernel sleep_on for session operations. It works in conjunction + * with session locking facilities to provide a secure mechanism for + * process control. + * Parameters: + * session: pointer to session_t whose process is to be controlled + * state : Linux state parameter that describes how to sleep. Usually + * TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE are values passed + * for this argument. + * Returns: None + * Notes: + * - The only difference between nbss_sleep_on and sleep_on is in the + * decision made before schedule() which in nbss_sleep_on is determined + * by nbss_release_session(). The reason is in abrupt termination of a + * session while the sleeping procedure runs. This routines integrates + * conditions so that race conditions are avoided. + */ +static inline void nbss_sleep_on(session_t *session, int state) +{ + wait_queue_t wait; + + init_waitqueue_entry(&wait, current); + set_current_state(state); + add_wait_queue(&session->waitq, &wait); + + if (!nbss_release_session(session)) { + dprintk("about to call schedule\n"); + schedule(); +#if WAITQUEUE_DEBUG + dprintk("sleeper=%p, waker=%lx\n", + current_text_addr(), wait.__waker); +#endif + } else + set_current_state(TASK_RUNNING); + remove_wait_queue(&session->waitq, &wait); +} + +/* + * Function: nbss_add_session_to_list + * Inserts a previously allocated/initialized session_t into session + * pending list. + * Parameters: + * session: pointer to session_t to add to pending session list + * Returns: None + */ +static void __nbss_add_session_to_list(session_t *session) +{ + session->next = session_list; + session_list = session; +} + +static void nbss_add_session_to_list(session_t *session) +{ + spin_lock_bh(&session_list_lock); + __nbss_add_session_to_list(session); + spin_unlock_bh(&session_list_lock); +} + +/* + * Function: nbss_remove_session_from_list + * Removes a session from pending session list + * Parameters: + * session: Pointer to session_t to remove from pending session list + * Returns: None + */ +static void nbss_remove_session_from_list(session_t *session) +{ + session_t *entry, *prev_entry = NULL; + + spin_lock_bh(&session_list_lock); + entry = session_list; + while (entry) { + if (entry == session) { + if (prev_entry) + prev_entry->next = entry->next; + else + session_list = entry->next; + } + prev_entry = entry; + entry = entry->next; + } + spin_unlock_bh(&session_list_lock); +} + +/* + * Function: nbss_find_listen + * Finds a session_t in session pending list who listens to a specific + * name. + * Parameters: + * name: pointer to NetBIOS name the session listens to + * Returns: + * NULL : if no pending session found listening to name + * non-NULL: pointer to a pending session in list who listens to name + */ +static session_t *nbss_find_listen(unsigned char *name) +{ + session_t *session; + + spin_lock_bh(&session_list_lock); + session = session_list; + while (session) { + if (session->state == NETBEUI_SESS_LISTENWAIT && + !memcmp(session->local_name->name, name, NETBEUI_NAME_LEN)) + break; + session = session->next; + } + if (session) + session_hold(session); + spin_unlock_bh(&session_list_lock); + return session; +} + +/* + * Function: nbss_unicast_name_recognized + * Prepares a NetBIOS NAME RECOGNIZED frame and nbll_uisends it to network + * Parameters: + * session: pointer to session_t structure the frame should be built from + * this session usually is selected from pending session list. + * Returns: + * 0 : if frame is successfully transmitted to network. + * non-zero: if frame transmission encountered an error (usually at NDI + * layer) + * Notes: + * - NetBIOS NAME RECOGNIZED frame is the response to a NetBIOS NAME QUERY + * frame received from network. The interface which accepts NAME QUERY + * frame passes the sk_buff via session->skb to reuse it for NAME + * RECOGNIZED frame, thus reducing memory consumption. + */ +static int nbss_unicast_name_recognized(session_t *session) +{ + /* It is supposed that name query skb is put in session->skb f/ reuse */ + dgram_t *hdr; + int rc; + + session_hold(session); + hdr = (dgram_t *)session->skb->data; + hdr->length = nb_cmd_hdr_len[NETBEUI_NAME_RECOGNIZED]; + hdr->command = NETBEUI_NAME_RECOGNIZED; + hdr->data1 = 0; + hdr->data2 = NETBEUI_CALL_DATA2(session->local_name->type, + session->lsn); + hdr->xmit_correlator = hdr->resp_correlator; + hdr->resp_correlator = + session->resp_correlator = nbss_next_correlator(); + memcpy(hdr->dest_name, hdr->source_name, NETBEUI_NAME_LEN); + memcpy(hdr->source_name, session->local_name->name, NETBEUI_NAME_LEN); + rc = nbll_uisend(session->remote_mac, session->skb); + session_put(session); + return rc; +} + +/* + * Function: nbss_alloc_session_skb + * Allocates and prepares a skb for session service purposes + * Parameters: + * sn : pointer to session that sk_buff is allocated for it. + * len : length of data in skb + * priority: a Linux kernel style memory allocation policy flag from + * GFP_* (GFP_KERNEL, GF_ATOMIC, GFP_USER, ...) family. + * Returns: + * NULL : if can not allocate memory for sk_buff + * non-NULL: pointer to sk_buff + */ +static struct sk_buff *nbss_alloc_session_skb(session_t *sn, int len, + int priority) +{ + struct sk_buff *skb; + + session_hold(sn); + skb = alloc_skb(len + sn->llcmac_ihl, priority); + if (skb) { + skb_reserve(skb, sn->llcmac_ihl); + skb->nh.raw = skb->h.raw = skb->data; + } + session_put(sn); + return skb; +} + +/* + * Function: nbss_ack_with_data + * Acknowledges incoming bytes with an outgoing frame by justifying data + * control bytes. + * Parameters: + * session: pointer to session_t, the acknowledgement is generated for + * hdr : pointer to packet_t header of outgoing frame. + * Returns: None + */ +static void nbss_ack_with_data(session_t *session, packet_t *hdr) +{ + session_hold(session); + barrier(); + if (session->o_ack_correlator) { + del_timer(&session->timer); + NETBEUI_INCLUDE_ACK_WITH_DATA(hdr); + hdr->xmit_correlator = (unsigned short) + session->o_ack_correlator; + session->o_ack_correlator = 0; + } + session_put(session); +} + +/* + * Function: nbss_isend_session_initialize + * Prepares a NetBIOS SESSION INITIALIZE frame and nbll_isends it toward + * remote session. + * Parameters: + * session: pointer to session_t structure the frame should be built for + * Returns: + * 0 : if frame is successfully transmitted to network. + * -ENOMEM: if memory allocation for sk_buff failed. + * other : if frame transmission encountered an error + * Notes: + * - NetBIOS NAME RECOGNIZED frame is the response to a NetBIOS NAME QUERY + * frame received from network. The interface which accepts NAME QUERY + * frame passes the sk_buff via session->skb to reuse it for NAME + * RECOGNIZED frame, thus reducing memory consumption. + */ +static int nbss_isend_session_initialize(session_t *session) +{ + int session_packet_len = nb_cmd_hdr_len[NETBEUI_SESSION_INITIALIZE]; + struct sk_buff *skb; + packet_t *hdr; + int rc = -ENOMEM; + + session_hold(session); + skb = nbss_alloc_session_skb(session, session_packet_len, GFP_ATOMIC); + if (!skb) + goto out; + hdr = (packet_t *)skb_put(skb, session_packet_len); + hdr->length = session_packet_len; + hdr->delimiter = NETBEUI_DELIMITER; + hdr->command = NETBEUI_SESSION_INITIALIZE; + hdr->data1 = 0x81; /* NetBIOS 2.2 with ability to + handle nack */ + /* Token Ring support */ + NETBEUI_CALC_SESS_MTU(session); + hdr->data1 |= (session->tr_frame_lf << 1) & 0x0E; + hdr->data2 = session->mtu; + hdr->xmit_correlator = session->xmit_correlator; + hdr->resp_correlator = + session->resp_correlator = nbss_next_correlator(); + hdr->dest_num = session->rsn; + hdr->source_num = session->lsn; + rc = nbll_isend(session->link, skb); +out: session_put(session); + return rc; +} + +/* + * Function: nbss_isend_session_confirm + * Prepares a NetBIOS SESSION CONFIRM frame and nbll_isends it toward + * remote session. + * Parameters: + * session : pointer to session_t structure the frame should be built for + * Returns: + * 0 : if frame is successfully transmitted to remote session. + * non-zero: if frame transmission encountered an error + * Notes: + * - NetBIOS SESSION INITIALIZE frame is the response to a NetBIOS SESSION + * CONFIRM frame received from remote session. The interface which + * accepts SESSION INITIALIZE frame passes the sk_buff via session->skb + * to reuse it for SESSION CONFIRM frame, thus reducing memory + * consumption. + */ +static int nbss_isend_session_confirm(session_t *session) +{ + /* I suppose get_session_initialize has set session->skb for reuse */ + packet_t *hdr; + int rc; + + session_hold(session); + hdr = (packet_t *)session->skb->data; + hdr->length = nb_cmd_hdr_len[NETBEUI_SESSION_CONFIRM]; + hdr->command = NETBEUI_SESSION_CONFIRM; + hdr->data1 = 0x81; /* NetBIOS 2.2 with ability to + handle nack */ + hdr->data2 = session->mtu; + session->resp_correlator = hdr->resp_correlator; + hdr->resp_correlator = session->xmit_correlator; + hdr->xmit_correlator = session->resp_correlator; + hdr->dest_num = session->rsn; + hdr->source_num = session->lsn; + rc = nbll_isend(session->link, session->skb); + session_put(session); + return rc; +} + +/* + * Function: nbss_isend_data_first_middle + * Prepares a NetBIOS DATA FIRST MIDDLE frame and nbll_isends it toward + * remote session. + * Parameters: + * session: pointer to session_t structure the frame should be built for + * cflow : flag that indicates requesting RECEIVE CONTINUE from remote + * session: + * zero means do not request RECEIVE CONTINUE + * non-zero means request RECEIVE CONTINUE + * Returns: + * 0 : if frame is successfully transmitted to remote session. + * -ENOMEM: if memory allocation for sk_buff failed. + * other : if frame transmission encountered an error + */ +static int nbss_isend_data_first_middle(session_t *session, int cflow) +{ + int session_packet_len = nb_cmd_hdr_len[NETBEUI_DATA_FIRST_MIDDLE]; + struct sk_buff *skb; + packet_t *hdr; + int rc = -ENOMEM; + + session_hold(session); + skb = nbss_alloc_session_skb(session, session_packet_len + session->mtu, + GFP_ATOMIC); + if (!skb) + goto out; + hdr = (packet_t *)skb_put(skb, session_packet_len); + hdr->length = session_packet_len; + hdr->delimiter = NETBEUI_DELIMITER; + hdr->command = NETBEUI_DATA_FIRST_MIDDLE; + hdr->data1 = 0; + hdr->data2 = session->o_receive_outstanding; + session->o_receive_outstanding = 0; + hdr->xmit_correlator = 0; + hdr->resp_correlator = 0; + hdr->dest_num = session->rsn; + hdr->source_num = session->lsn; + + if (cflow) { + NETBEUI_REQUEST_RECEIVE_CONTINUE(hdr); + session->o_receive_continue = 0; + hdr->resp_correlator = + session->resp_correlator = nbss_next_correlator(); + } + if (session->o_noack) + NETBEUI_INDICATE_NACK(hdr); + rc = -EFAULT; + if (copy_from_user(skb_put(skb, session->mtu), session->o_buff, + session->mtu)) + goto err; + nbss_ack_with_data(session, hdr); + rc = nbll_isend(session->link, skb); +out: session_put(session); + return rc; +err: kfree_skb(skb); + goto out; +} + +/* + * Function: nbss_isend_data_only_last + * Prepares a NetBIOS DATA ONLY LAST frame and nbll_isends it toward remote + * session. + * Parameters: + * session: pointer to session_t structure the frame should be built for + * Returns: + * 0 : if frame is successfully transmitted to remote session. + * -ENOMEM: if memory allocation for sk_buff failed. + * other : if frame transmission encountered an error + */ +static int nbss_isend_data_only_last(session_t *session) +{ + int session_packet_len = nb_cmd_hdr_len[NETBEUI_DATA_ONLY_LAST]; + struct sk_buff *skb; + packet_t *hdr; + int rc = -ENOMEM; + + session_hold(session); + skb = nbss_alloc_session_skb(session, session_packet_len + + session->o_size, GFP_ATOMIC); + if (!skb) + goto out; + hdr = (packet_t *)skb_put(skb, session_packet_len); + hdr->length = session_packet_len; + hdr->delimiter = NETBEUI_DELIMITER; + hdr->command = NETBEUI_DATA_ONLY_LAST; + hdr->data1 = 0; + hdr->data2 = session->o_receive_outstanding; + session->o_receive_outstanding = 0; + hdr->xmit_correlator = 0; + hdr->resp_correlator = 0; + hdr->dest_num = session->rsn; + hdr->source_num = session->lsn; + + if (session->o_noack) + NETBEUI_INDICATE_NACK(hdr); + else { + hdr->resp_correlator = session->resp_correlator = + nbss_next_correlator(); + NETBEUI_ALLOW_ACK_WITH_DATA(hdr); + } + rc = -EFAULT; + if (copy_from_user(skb_put(skb, session->o_size), session->o_buff, + session->o_size)) + goto err; + nbss_ack_with_data(session, hdr); + rc = nbll_isend(session->link, skb); +out: session_put(session); + return rc; +err: kfree_skb(skb); + goto out; +} + +/* + * Function: nbss_isend_receive_continue + * Prepares a NetBIOS RECEIVE CONTINUE frame and nbll_isends it toward + * remote session. + * Parameters: + * session: pointer to session_t structure the frame should be built for + * hdr : pointer to packet_t header of the incoming frame which the + * RECEIVE CONTINUE frame is built for. + * Returns: + * 0 : if frame is successfully transmitted to remote session. + * -ENOMEM: if memory allocation for sk_buff failed. + * other : if frame transmission encountered an error + */ +static int nbss_isend_receive_continue(packet_t *source_hdr, session_t *session) +{ + packet_t *hdr; + int session_packet_len = nb_cmd_hdr_len[NETBEUI_RECEIVE_CONTINUE]; + struct sk_buff *skb; + int rc = -ENOMEM; + + session_hold(session); + skb = nbss_alloc_session_skb(session, session_packet_len, GFP_ATOMIC); + if (!skb) + goto out; + hdr = (packet_t *)skb_put(skb, session_packet_len); + hdr->length = session_packet_len; + hdr->delimiter = NETBEUI_DELIMITER; + hdr->command = NETBEUI_RECEIVE_CONTINUE; + hdr->data1 = 0; + hdr->data2 = 0; + hdr->xmit_correlator = source_hdr->resp_correlator; + hdr->resp_correlator = 0; + hdr->dest_num = session->rsn; + hdr->source_num = session->lsn; + rc = nbll_isend(session->link, skb); +out: session_put(session); + return rc; +} + +/* + * Function: nbss_isend_no_receive + * Prepares a NetBIOS RECEIVE CONTINUE frame and nbll_isends it toward + * remote session. + * Parameters: + * session: pointer to session_t structure the frame should be built for + * skb : pointer to sk_buff to use for building frame. This sk_buff is + * the one that contained incoming frame and since its data is not + * accepted from input stream, it is passed for reuse. + * Returns: + * 0 : if frame is successfully transmitted to remote session. + * -ENOMEM: if memory allocation for sk_buff failed. + * other : if frame transmission encountered an error + */ +static int nbss_isend_no_receive(struct sk_buff *skb, session_t *session) +{ + int session_packet_len = nb_cmd_hdr_len[NETBEUI_NO_RECEIVE]; + packet_t *hdr; + unsigned char data1; + int rc; + + session_hold(session); + data1 = NETBEUI_NACK_INDICATOR(((packet_t *)skb->data)); + skb_trim(skb, 0); + hdr = (packet_t *)skb_put(skb, session_packet_len); + hdr->length = session_packet_len; + hdr->delimiter = NETBEUI_DELIMITER; + hdr->command = NETBEUI_NO_RECEIVE; + hdr->data1 = data1; + hdr->data2 = session->i_notacked; + hdr->xmit_correlator = 0; + hdr->resp_correlator = 0; + hdr->dest_num = session->rsn; + hdr->source_num = session->lsn; + + rc = nbll_isend(session->link, skb); + if (!rc) { + session->i_state = NETBEUI_RECV_NO_RECEIVE; + session->i_notacked = 0; + } + session_put(session); + return rc; +} + +/* + * Function: nbss_isend_receive_outstanding + * Prepares a NetBIOS RECEIVE OUTSTANDING frame and nbll_isends it toward + * remote session. + * Parameters: + * session: pointer to session_t structure the frame should be built for + * Returns: + * 0 : if frame is successfully transmitted to remote session. + * -ENOMEM: if memory allocation for sk_buff failed. + * other : if frame transmission encountered an error + * Notes: + * - Since the frame is transmitted within a user process context, + * and and works with input state variable, it locks a session during + * transmission period. + * - no need to hold refcnt, only called from nbss_receive that already + * does that + */ +static int nbss_isend_receive_outstanding(session_t *session) +{ + int session_packet_len = nb_cmd_hdr_len[NETBEUI_RECEIVE_OUTSTANDING]; + packet_t *hdr; + int rc = -ENOMEM; + struct sk_buff *skb = nbss_alloc_session_skb(session, + session_packet_len, + GFP_KERNEL); + if (!skb) + goto out; + hdr = (packet_t *)skb_put(skb, session_packet_len); + hdr->length = session_packet_len; + hdr->delimiter = NETBEUI_DELIMITER; + hdr->command = NETBEUI_RECEIVE_OUTSTANDING; + hdr->data1 = 0; + hdr->data2 = 0; + hdr->xmit_correlator = 0; + hdr->resp_correlator = 0; + hdr->dest_num = session->rsn; + hdr->source_num = session->lsn; + nbss_lock_session(session); + + rc = nbll_isend(session->link, skb); + if (!rc) + session->i_state = NETBEUI_RECV_RECEIVE_OUTSTANDING; + nbss_release_session(session); +out: return rc; +} + +/* + * Function: nbss_isend_data_ack + * Prepares a NetBIOS DATA ACK frame and nbll_isends it toward remote + * session. + * Parameters: + * session : pointer to session_t structure the frame should be + * built for + * ack_correlator: this is the xmit correlator found in the incoming frame + * passed to be put in response correlator of the DATA ACK + * Returns: + * 0 : if frame is successfully transmitted to remote session. + * -ENOMEM: if memory allocation for sk_buff failed. + * other : if frame transmission encountered an error + */ +static int nbss_isend_data_ack(session_t *session, + unsigned short ack_correlator) +{ + int session_packet_len = nb_cmd_hdr_len[NETBEUI_DATA_ACK]; + struct sk_buff *skb; + packet_t *hdr; + int rc = -ENOMEM; + + session_hold(session); + skb = nbss_alloc_session_skb(session, session_packet_len, GFP_ATOMIC); + if (!skb) + goto out; + hdr = (packet_t *)skb_put(skb, session_packet_len); + hdr->length = session_packet_len; + hdr->delimiter = NETBEUI_DELIMITER; + hdr->command = NETBEUI_DATA_ACK; + hdr->data1 = 0; + hdr->data2 = 0; + hdr->xmit_correlator = ack_correlator; + hdr->resp_correlator = 0; + hdr->dest_num = session->rsn; + hdr->source_num = session->lsn; + rc = nbll_isend(session->link, skb); +out: session_put(session); + return rc; +} + +/* + * Function: nbss_ack_session_data + * Actually acknowledges incoming session data depending on current + * condition either by sending DATA ACK frame or by postponing and sending + * ACK WITH DATA. + * Parameters: + * session: pointer to session_t structure the frame should be built for + * hdr : pointer to packet_t header of the incoming frame which the + * acknowledgement is built for. + * Returns: + * 0 : if frame is successfully transmitted to remote session. + * -ENOMEM: if memory allocation for sk_buff failed. + * other : if frame transmission encountered an error + */ +static int nbss_ack_session_data(packet_t *hdr, session_t *session) +{ + int rc = 0; + + session_hold(session); + if (NETBEUI_ACK_WITH_DATA_ALLOWED(hdr) && + !session->o_ack_correlator && !session->urgent_ack) { + session->o_ack_correlator = hdr->resp_correlator | + NETBEUI_ACK_FLAG; + session->timer.expires = jiffies + NETBEUI_DATA_ACK_TIMEOUT; + add_timer(&session->timer); + goto out; + } + rc = nbss_isend_data_ack(session, hdr->resp_correlator); +out: session_put(session); + return rc; +} + +/* + * Function: nbss_ack_timer_function + * Handles delayed acknowledgement for a session when its timer expires + * by sending a DATA ACK frame. + * Parameters: + * input: pointer to session_t structure whose timer is expired. + * Returns: None + * Notes: + * - We never re-enter LLC from its upper layer interface since it is + * not re-entrant. However ack timers expire and thus cause NetBEUI + * to send DATA ACK which re-enters LLC. + */ +static void nbss_ack_timer_function(unsigned long input) +{ + session_t *session = (session_t *)input; + + session_hold(session); + if (llc_in_progress || + nbss_isend_data_ack(session, session->o_ack_correlator)) { + session->timer.expires = jiffies + NETBEUI_DATA_ACK_TIMEOUT; + add_timer(&session->timer); + } else + session->o_ack_correlator = 0; + session_put(session); +} + +/* + * Function: nbss_isend_session_end + * Prepares a NetBIOS SESSION END frame and nbll_isends it toward remote + * session. + * Parameters: + * session : pointer to session_t structure the frame should be built for + * Returns: + * 0 : if frame is successfully transmitted to remote session. + * -ENOMEM: if memory allocation for sk_buff failed. + * other : if frame transmission encountered an error + */ +static int nbss_isend_session_end(session_t *session) +{ + int session_packet_len = nb_cmd_hdr_len[NETBEUI_SESSION_END]; + struct sk_buff *skb; + packet_t *hdr; + int rc = -ENOMEM; + + session_hold(session); + skb = nbss_alloc_session_skb(session, session_packet_len, GFP_ATOMIC); + if (!skb) + goto out; + hdr = (packet_t *)skb_put(skb, session_packet_len); + hdr->length = session_packet_len; + hdr->delimiter = NETBEUI_DELIMITER; + hdr->command = NETBEUI_SESSION_END; + hdr->data1 = 0; + hdr->data2 = 0; + hdr->xmit_correlator = 0; + hdr->resp_correlator = 0; + hdr->dest_num = session->rsn; + hdr->source_num = session->lsn; + rc = nbll_isend(session->link, skb); +out: session_put(session); + return rc; +} + +/* + * Function: nbns_handle_event + * This is the heart of Session Service State Machine, which performs a + * transition from current state of session element to new state based + * on event occurred and session state table contents. + * Parameters: + * event : An integer of NETBEUI_SESS_* family that implies type of event + * nb_name: pointer to name_t structure which the event occurred on + * Returns: None + * Notes: + * - The state changes before actions be executed. This is due to + * non deterministic behavior of actions which may sleep the current + * process, thus stopping the function in the mid-way. + */ +static void nbss_handle_event(session_event_t event, session_t *session) +{ + struct event_struct *ev; + + session_hold(session); + ev = &session_state_table[session->state][event]; + if (ev && ev->event_handler) { + unsigned char old_state = session->state; + + session->state = ev->next_state; + if (ev->event_handler(session)) + session->state = old_state; + } + session_put(session); +} + +/* + * Function: nbss_wait_timer_function + * This is the callback function triggered upon expiration of session + * wait timer used first during session establishment and then for + * delaying acknowledgements. + * Parameters: + * input: pointer to session_t structure whose timer is expired. + * Returns: None + * Notes: + * - This timer function, set in session allocation time is used during + * session establishment. + */ +static void nbss_wait_timer_function(unsigned long input) +{ + session_t *session = (session_t *)input; + + session_hold(session); + session->status = -ETIMEDOUT; + nbss_handle_event(NETBEUI_SESS_TIMEOUT, session); + session_put(session); +} + +/* + * Function: + * This is the callback function trigerred upon expiration of session + * resource timer used when resources (usually memory) are ended up. + * Parameters: + * input: pointer to session_t structure whose timer is expired. + * Returns: None + */ +static void nbss_resource_timer_function(unsigned long input) +{ + session_t *session = (session_t *)input; + + session_hold(session); + switch (session->o_rsrc_origin) { + case NETBEUI_ORIGIN_CONNECTED: + nbss_handle_event(NETBEUI_SESS_CONN_RETRY, session); + break; + case NETBEUI_ORIGIN_NORMAL: + nbss_handle_event(NETBEUI_SESS_NORM_RETRY, session); + break; + default: + printk(KERN_ERR "NetBEUI serious error: Resource " + "timer expired from %u\n", + session->o_rsrc_origin); + break; + } + session_put(session); +} + +/* + * Session service state machine functions + * Implementing transition actions + */ +static int nbss_event_abort_send_in_all(session_t *session) +{ + session->o_aborted = 1; + wake_up(&session->waitq); + return 0; +} + +static int nbss_event_call_in_initial(session_t *session) +{ + int rc = -1; + + session->status = nbll_attach_session(session, session->dev, + session->remote_mac); + if (session->status) + goto out; + rc = 0; + nbss_add_session_to_list(session); +out: return rc; +} + +static int nbss_event_listen_in_initial(session_t *session) +{ + __nbss_add_session_to_list(session); + return 0; +} + +static int nbss_event_confirm_in_callwait(session_t *session) +{ + int rc; + + session->status = nbll_link_session(session->link); + if (session->status) { + rc = session->status; + goto out; + } + session->status = nbss_isend_session_initialize(session); + rc = -ENOMEM; + if (session->status) + goto out; + rc = 0; + nbss_remove_session_from_list(session); + session->timer.expires = jiffies + NETBEUI_TRANSMIT_TIMEOUT * + NETBEUI_TRANSMIT_COUNT; + add_timer(&session->timer); + sleep_on(&session->waitq); +out: return rc; +} + +static int nbss_event_reject_in_callwait(session_t *session) +{ + nbss_remove_session_from_list(session); + nbll_detach_session(session->link, session->lsn); + session->status = -ECONNABORTED; + return 0; +} + +static int nbss_event_abort_in_callwait(session_t *session) +{ + nbss_remove_session_from_list(session); + session->status = -ECONNRESET; + return 0; +} + +static int nbss_event_connect_in_confwait(session_t *session) +{ + del_timer(&session->timer); + wake_up(&session->waitq); + session->status = 0; + return 0; +} + +static int nbss_event_timeout_in_confwait(session_t *session) +{ + nbll_detach_session(session->link, session->lsn); + wake_up(&session->waitq); + session->status = -ECONNREFUSED; + return 0; +} + +static int nbss_event_abort_in_confwait(session_t *session) +{ + del_timer(&session->timer); + wake_up(&session->waitq); + session->status = -ECONNRESET; + return 0; +} + +static int nbss_event_confirm_in_listenwait(session_t *session) +{ + int rc = -1; + + session->status = nbll_attach_session(session, session->dev, + session->remote_mac); + if (session->status) + goto out; + session->status = nbss_unicast_name_recognized(session); + if (session->status) { + nbll_detach_session(session->link, session->lsn); + goto out; + } + rc = 0; + session->timer.expires = jiffies + NETBEUI_TRANSMIT_TIMEOUT * + NETBEUI_TRANSMIT_COUNT; + add_timer(&session->timer); +out: return rc; +} + +static int nbss_event_reject_in_listenwait(session_t *session) +{ + nbss_remove_session_from_list(session); + session->status = -ECONNABORTED; + return 0; +} + +static int nbss_event_connect_in_initwait(session_t *session) +{ + int rc = -1; + + session->status = nbss_isend_session_confirm(session); + if (session->status) + goto out; + rc = 0; + del_timer(&session->timer); + nbss_remove_session_from_list(session); + session->session_ready_callback(session->owner, session); + session->status = 0; +out: return rc; +} + +static int nbss_event_timeout_in_initwait(session_t *session) +{ + nbll_detach_session(session->link, session->lsn); + session->status = -ECONNREFUSED; + return 0; +} + +static int nbss_event_abort_in_initwait(session_t *session) +{ + del_timer(&session->timer); + session->status = -ECONNRESET; + return 0; +} + +static int nbss_event_reject_in_initwait(session_t *session) +{ + del_timer(&session->timer); + nbll_detach_session(session->link, session->lsn); + nbss_remove_session_from_list(session); + session->status = -ECONNABORTED; + return 0; +} + +static int nbss_event_abort_in_connected(session_t *session) +{ + if (session->owner) + session->abort_owner_callback(session->owner, session); + session->status = -ECONNRESET; + return 0; +} + +static int nbss_event_hangup_in_connected(session_t *session) +{ + nbss_isend_session_end(session); + nbll_detach_session(session->link, session->lsn); + session->status = -ECONNABORTED; + return 0; +} + +static int nbss_event_end_in_connected(session_t *session) +{ + if (session->owner) + session->abort_owner_callback(session->owner, session); + nbll_detach_session(session->link, session->lsn); + session->status = -ECONNRESET; + return 0; +} + +static int nbss_event_hangup_in_discwait(session_t *session) +{ + return 0; +} + +static int nbss_event_first_middle_cont_in_connected(session_t *session) +{ + int rc = -1; + + session->status = nbss_isend_data_first_middle(session, 1); + if (session->status) + goto out; + rc = 0; + session->o_buff += session->mtu; + session->o_size -= session->mtu; + session->o_txed += session->mtu; + nbss_wait_event(session); +out: return rc; +} + +static int nbss_event_first_middle_in_connected(session_t *session) +{ + int rc = -1; + + session->status = nbss_isend_data_first_middle(session, 0); + if (session->status) + goto out; + rc = 0; + session->o_buff += session->mtu; + session->o_size -= session->mtu; + session->o_txed += session->mtu; +out: return rc; +} + +static int nbss_event_only_last_ack_in_connected(session_t *session) +{ + int rc = -1; + + session->status = nbss_isend_data_only_last(session); + if (session->status) + goto out; + rc = 0; + session->o_buff += session->o_size; + session->o_txed += session->o_size; + session->o_size -= session->o_size; + nbss_wait_event(session); +out: return rc; +} + +static int nbss_event_only_last_in_connected(session_t *session) +{ + int rc = -1; + + session->status = nbss_isend_data_only_last(session); + if (session->status) + goto out; + rc = 0; + session->o_buff += session->o_size; + session->o_txed += session->o_size; + session->o_size -= session->o_size; +out: return rc; +} + +static int nbss_event_resource_in_connected(session_t *session) +{ + session->o_rsrc_origin = NETBEUI_ORIGIN_CONNECTED; + session->timer.expires = jiffies + NETBEUI_RESOURCE_TIMEOUT; + session->timer.function = nbss_resource_timer_function; + add_timer(&session->timer); + sleep_on(&session->waitq); + return 0; +} + +static int nbss_event_continue_in_contwait(session_t *session) +{ + session->o_acked += session->o_txed; + session->o_txed = 0; + wake_up(&session->waitq); + return 0; +} + +static int nbss_event_restart_in_contwait(session_t *session) +{ + nbss_ack_bytes(session); + wake_up(&session->waitq); + return 0; +} + +static int nbss_event_pause_in_contwait(session_t *session) +{ + nbss_ack_bytes(session); + session->o_no_receive = 1; + wake_up(&session->waitq); + return 0; +} + +static int nbss_event_nonblock_in_contwait(session_t *session) +{ + nbss_ack_bytes(session); + session->o_no_receive = 1; + wake_up(&session->waitq); + return 0; +} + +static int nbss_event_restart_in_standwait(session_t *session) +{ + session->o_no_receive = 0; + wake_up(&session->waitq); + return 0; +} + +static int nbss_event_pause2_in_standwait(session_t *session) +{ + nbss_sleep_on(session, TASK_INTERRUPTIBLE); + return 0; +} + +static int nbss_event_data_acked_in_ackwait(session_t *session) +{ + session->o_acked += session->o_txed; + session->o_txed = 0; + wake_up(&session->waitq); + return 0; +} + +static int nbss_event_restart_in_ackwait(session_t *session) +{ + nbss_ack_bytes(session); + wake_up(&session->waitq); + return 0; +} + +static int nbss_event_pause_in_ackwait(session_t *session) +{ + nbss_ack_bytes(session); + session->o_no_receive = 1; + wake_up(&session->waitq); + return 0; +} + +static int nbss_event_nonblock_in_ackwait(session_t *session) +{ + nbss_ack_bytes(session); + session->o_no_receive = 1; + wake_up(&session->waitq); + return 0; +} + +static int nbss_event_norm_retry_in_rsrcwait(session_t *session) +{ + wake_up(&session->waitq); + return 0; +} + +static int nbss_event_conn_retry_in_rsrcwait(session_t *session) +{ + wake_up(&session->waitq); + return 0; +} + +static int nbss_event_first_middle_in_normal(session_t *session) +{ + int rc = -1; + + session->status = nbss_isend_data_first_middle(session, 0); + if (session->status) + goto out; + rc = 0; + session->o_buff += session->mtu; + session->o_size -= session->mtu; + session->o_txed += session->mtu; +out: return rc; +} + +static int nbss_event_restart_in_normal(session_t *session) +{ + nbss_ack_bytes(session); + return 0; +} + +static int nbss_event_only_last_ack_in_normal(session_t *session) +{ + int rc = -1; + + session->status = nbss_isend_data_only_last(session); + if (session->status) + goto out; + rc = 0; + session->o_buff += session->o_size; + session->o_txed += session->o_size; + session->o_size -= session->o_size; + nbss_wait_event(session); +out: return rc; +} + +static int nbss_event_only_last_in_normal(session_t *session) +{ + int rc = -1; + + session->status = nbss_isend_data_only_last(session); + if (session->status) + goto out; + rc = 0; + session->o_buff += session->o_size; + session->o_txed += session->o_size; + session->o_size -= session->o_size; +out: return rc; +} + +static int nbss_event_pause_in_normal(session_t *session) +{ + nbss_ack_bytes(session); + session->o_no_receive = 1; + return 0; +} + +static int nbss_event_nonblock_in_normal(session_t *session) +{ + nbss_ack_bytes(session); + session->o_no_receive = 1; + return 0; +} + +static int nbss_event_resource_in_normal(session_t *session) +{ + session->o_rsrc_origin = NETBEUI_ORIGIN_NORMAL; + session->timer.expires = jiffies + NETBEUI_RESOURCE_TIMEOUT; + session->timer.function = nbss_resource_timer_function; + add_timer(&session->timer); + sleep_on(&session->waitq); + return 0; +} + +/* + * Session service state machine functions + * Implementing interface functions + */ +/* + * Function: nbss_call + * This is a sophisticated interface routine for establishing a session + * with a remote hosts. Finding host that owns name, establishing session + * building LLC connection and configuring session are the phases a session + * element passes through them to prepare session for transferring data. + * Parameters: + * calling_name : pointer to name_t structure that the session is built + * either registered by client or NAME_NUMBER_1 auto bound + * called_name : pointer to NetBIOS name of remote node + * owner : pointer to a data structure of the owner of session + * used for calling its call backs + * itf_abort_owner: pointer to a callback routine for alerting owner, of + * session abortion + * session_ptr : (VRP) pointer to session_structure if return value + * indicates a valid value which is a pointer to session_t + * The owner later uses this value for getting services + * from Session Service module + * Returns: + * 0 : if a session successfully established to remote node + * -ENOMEM : if failed to allocate memory for session_t structure. + * -EHOSTUNREACH: if can not find a node on network who owns the name. + * -ETOONAMYREFS: if more than one node responded to session establishment + * request. This means that it can not establish session + * with group names. + * -ECONNREFUSED: if node responded to request but refused to establish a + * session anyway. + * -ECONNRESET : if connection reset by LLC before session establishment + * ends + * other : any other error reported by LLC. + */ +int nbss_call(name_t *calling_name, char *called_name, struct sock *owner, + abort_owner_cbt itf_abort_owner, session_t **session_ptr) +{ + int status; +#define MAX_FIND 3 + char macs[MAX_FIND][6]; + struct net_device *devs[MAX_FIND]; + session_t *session = nbss_alloc_session(); + int rc = -ENOMEM; + + if (!session) + goto out; + *session_ptr = NULL; + session->state = NETBEUI_SESS_INITIAL; + session->owner = owner; + session->local_name = calling_name; + memcpy(session->remote_name, called_name, NETBEUI_NAME_LEN); + session->abort_owner_callback = itf_abort_owner; + + rc = status = nbqs_find_name(called_name, (char *)macs, devs, MAX_FIND); + if (status < 0) + goto sput; + else if (!status) { + rc = -EHOSTUNREACH; + goto sput; + } else if (status != 1) { + rc = -ETOOMANYREFS; + goto sput; + } + session_hold(session); + session->dev = devs[0]; + memcpy(session->remote_mac, macs, session->dev->addr_len); + + for (;;) { + nbss_handle_event(NETBEUI_SESS_CALL, session); + if (session->state == NETBEUI_SESS_INITIAL) { + rc = status = session->status; + goto dsput; + } + session->status = nbqs_query_name(called_name, calling_name, + session->lsn, &session->rsn, + &session->tr_frame_lf, + &session->xmit_correlator); + /* We may have got a session abort here */ + if (session->state == NETBEUI_SESS_INITIAL) + continue; + else + break; + } + /* We may also could not query server */ + rc = -ECONNREFUSED; + if (session->status || !session->rsn || session->rsn == 0xFF) { + nbss_handle_event(NETBEUI_SESS_REJ, session); + goto dsput; + } + /* Token Ring support */ + session->llcmac_ihl = LLCMAC_I_HEADLEN(session->dev); + nbss_handle_event(NETBEUI_SESS_CONFIRM, session); + if (session->state != NETBEUI_SESS_CONNECTED || session->status) { + status = session->status; + nbqs_delete_rnc(called_name); + rc = status ? : -ECONNRESET; + goto dsput; + } + rc = 0; + *session_ptr = session; +sput: session_put(session); +out: return rc; +dsput: session_put(session); + goto sput; +} + +/* + * Function: __nbss_listen + * Prepares backlog session_ts for a server who is going to listen on + * a name, kept in pending session list. Has to be called with + * session_list_lock held, with spin_lock_bh or spin_lock, depending + * on the context (process or BH). + * Parameters: + * nb_name : pointer to name_t the sessions listen to connection + * requests on it + * backlog : count of concurrent session establishments the + * session service should process at once. + * owner : pointer to a data structure of the owner of session + * used for calling its call backs + * itf_abort_owner : pointer to a callback routine for alerting owner, of + * session abortion + * itf_session_ready: pointer to callback routine alerting owner, of + * existence of an established session. + * Returns: + * >= 0: count of backlog pending session in list who listen to name for + * connection establishment requests. + * Notes: + * - The session does not guarantee to have as many pending sessions + * as requested by backlog parameter due to memory allocation fails. + * This should be considered by upper layer routines. + */ +int __nbss_listen(name_t *nb_name, int backlog, struct sock *owner, + abort_owner_cbt itf_abort_owner, + session_ready_cbt itf_session_ready) +{ + int count, exist = 0; + session_t *session = session_list; + + while (session) { + if (session->local_name == nb_name) + exist++; + session = session->next; + } + for (count = exist; count < backlog; count++) { + session = nbss_alloc_session(); + if (session) { + session->state = NETBEUI_SESS_INITIAL; + session->owner = owner; + session->local_name = nb_name; + session->abort_owner_callback = itf_abort_owner; + session->session_ready_callback = itf_session_ready; + nbss_handle_event(NETBEUI_SESS_LISTEN, session); + exist++; + } else + break; + } + return exist; +} + +int nbss_listen(name_t *nb_name, int backlog, struct sock *owner, + abort_owner_cbt itf_abort_owner, + session_ready_cbt itf_session_ready) +{ + int rc; + spin_lock(&session_list_lock); + rc = __nbss_listen(nb_name, backlog, owner, itf_abort_owner, + itf_session_ready); + spin_unlock(&session_list_lock); + return rc; +} + +int nbss_listen_bh(name_t *nb_name, int backlog, struct sock *owner, + abort_owner_cbt itf_abort_owner, + session_ready_cbt itf_session_ready) +{ + int rc; + spin_lock_bh(&session_list_lock); + rc = __nbss_listen(nb_name, backlog, owner, itf_abort_owner, + itf_session_ready); + spin_unlock_bh(&session_list_lock); + return rc; +} + +/* + * Function: nbss_end_listen + * Removes session_ts on pending session list who listen to session + * establishment requests on a specific name, called only from + * nbso_session_release, in process context, so no need to spin_lock_bh, + * plain spin_lock is enough. + * Parameters: + * nb_name: pointer to name which sessions listening to it should be + * removed from pending session list. + * Returns: None + */ +void __nbss_end_listen(name_t *nb_name) +{ + session_t *session = session_list; + + while (session) { + session_t *next_session = session->next; + + if (session->local_name == nb_name) { + nbss_handle_event(NETBEUI_SESS_REJ, session); + session_put(session); + } + session = next_session; + } +} + +/* + * Function: nbss_send + * This is the heart of output data stream. + * Sends a block of user data to remote session by fragmenting and + * controlling flow of data. In addition to simplicity it operates + * a considerable part of Session Service State Machine by generating + * different events carefully + * Parameters: + * session : pointer to session_t to send data on + * buf : pointer to user buffer that contains data + * size : size of data in user buffer + * nonblock: flag that indicates to block user process or not block + * it (0/1) + * noack : flag that indicates to receive data receive acknowledgement + * or not (0/1) + * Returns: + * >= 0 : count of data bytes successfully sent to remote session + * -ECONNABORTED: if session aborted. + * -EINPROGRESS : if another process currently sends data in session this + * may happen if two process share a socket. + * -ETIME : if send timeout. this happens if interface layer calls + * nbss_send_abort when its timers expire. + */ +int nbss_send(session_t *session, unsigned char *buf, unsigned short size, + unsigned char nonblock, unsigned char noack) +{ + int rc = -ECONNABORTED; + + session_hold(session); + if (session->zapped) + goto out; + rc = -EINPROGRESS; + if (session->state != NETBEUI_SESS_CONNECTED) + goto out; + session->o_nonblock = nonblock; + session->o_noack = session->version == NETBEUI_VERSION_2xx ? + noack : 0; + session->o_no_receive = 0; + session->o_rsrc_origin = 0; + session->o_buff = buf; + session->o_buffsize = size; + session->o_size = size; + session->o_txed = 0; + session->o_acked = 0; + session->r_acked = 0; + session->o_aborted = 0; + while (session->o_acked < session->o_buffsize) { + nbss_lock_session(session); + session->status = 0; + + if (session->o_size > session->mtu && + session->o_size == session->o_buffsize && + session->o_receive_continue) + nbss_handle_event(NETBEUI_SESS_FIRST_MIDDLE_CONT, + session); + else if (session->o_size > session->mtu) + nbss_handle_event(NETBEUI_SESS_FIRST_MIDDLE, session); + else if (!noack && session->o_size > 0) + nbss_handle_event(NETBEUI_SESS_ONLY_LAST_ACK, session); + else if (session->o_size > 0) + nbss_handle_event(NETBEUI_SESS_ONLY_LAST, session); + rc = session->status; + if (nbss_release_session(session)) + goto out; + rc = -ETIME; + if (session->o_aborted) + goto out; + if (session->o_no_receive && session->o_nonblock) { + rc = session->o_acked; + break; + } + if (session->o_no_receive) { + nbss_lock_session(session); + nbss_handle_event(NETBEUI_SESS_PAUSE2, session); + nbss_release_session(session); + if (signal_pending(current)) { + rc = session->o_acked > 0 ? session->o_acked : + -ERESTART; + break; + } + } + if (session->status == -ENOMEM) { + nbss_lock_session(session); + nbss_handle_event(NETBEUI_SESS_RESOURCE, session); + nbss_release_session(session); + } + rc = session->o_acked; + } + session->state = NETBEUI_SESS_CONNECTED; + if (rc > size) + rc = size; + if (rc > 0) + session->o_total += rc; +out: session_put(session); + return rc; +} + +/* + * Function: nbss_send_zero + * Sends a zero byte DATA ONLY LAST frame to remote node. + * Parameters: + * session: pointer to session_t to send frame on + * buf : pointer to a user buffer that is referenced in transition + * handlers of state machine + * Returns: + * >= 0 : if size of data bytes successfully sent to remote session + * -ECONNABORTED: if session aborted. + * -EINPROGRESS : if another process currently sends data in session this + * may happen if two process share a socket. + * Notes: + * - This feature is activated via ioctl interface and has special + * meaning to SAMBA that operates over NetBEUI + */ +int nbss_send_zero(session_t *session, char *buf) +{ + int rc = -ECONNABORTED; + + session_hold(session); + if (session->zapped) + goto out; + rc = -EINPROGRESS; + if (session->state != NETBEUI_SESS_CONNECTED) + goto out; + session->o_nonblock = 1; + session->o_noack = 1; + session->o_no_receive = 0; + session->o_rsrc_origin = 0; + session->o_buff = buf; + session->o_buffsize = 0; + session->o_size = 0; + session->o_txed = 0; + session->o_acked = 0; + session->r_acked = 0; + session->o_aborted = 0; + session->status = 0; + nbss_handle_event(NETBEUI_SESS_ONLY_LAST, session); + rc = session->status; +out: session_put(session); + return rc; +} + +/* + * Function: nbss_abort_send + * The interface which aborts a send operation, usually called from + * upper interface when send timers expire. + * Parameters: + * session: pointer to session_t whose send operation is to be aborted. + * Returns: None + */ +void nbss_abort_send(session_t *session) +{ + session_hold(session); + session->o_aborted = 1; + nbss_handle_event(NETBEUI_SESS_ABORT_SEND, session); + session_put(session); +} + +/* + * Function: nbss_send_ready + * Determines if session is ready to send data or not + * Parameters: + * session: pointer to session_t. + * Returns: + * 1: if session is ready to send data + * 0: if session is not ready to send data + */ +int nbss_send_ready(session_t *session) +{ + int rc; + + session_hold(session); + rc = !session->zapped && + session->state == NETBEUI_SESS_CONNECTED ? 1 : 0; + session_put(session); + return rc; +} + +/* + * Function: nbss_receive + * Receives data from input stream buffer and copies it into user buffer. + * Parameters: + * session : pointer to session_t to receive data from + * buf : pointer to user space buffer to put data into + * size : maximum size of data to put in buf + * nonblock: flag that indicates whether to block user process if data was + * not available + * Returns: + * >= 0 : count of data bytes fetched from input stream queue + * -ECONNABORTED: if session aborted. + * -ETIME : if receive timeout. this happens if interface layer calls + * nbss_receive_abort when its timers expire. + * -ERESTART : if process caught a signal + * -EAGAIN : if zero data bytes received. + */ +int nbss_receive(session_t *session, unsigned char *buf, unsigned short size, + unsigned char nonblock) +{ + unsigned short i_size = size; + struct sk_buff *skb; + int rc = -ECONNABORTED; + int passed_2nd = 0; + + session_hold(session); + if (session->zapped && !skb_queue_len(&session->i_skbq)) + goto out; + session->i_aborted = 0; +try_read: + nbss_lock_session(session); + while (i_size > 0 && (skb = skb_peek(&session->i_skbq)) != NULL) { + if (passed_2nd) + dprintk("entering 1st loop after the 2nd...\n"); + passed_2nd = 0; + nbss_release_session(session); + if (i_size >= skb->len) { + rc = -EFAULT; + if (copy_to_user(buf, skb->data, skb->len)) + goto out; + i_size -= skb->len; + buf += skb->len; + nbss_lock_session(session); + __skb_unlink(skb, &session->i_skbq); + session->i_size -= skb->len; + kfree_skb(skb); + } else { + rc = -EFAULT; + if (copy_to_user(buf, skb->data, i_size)) + goto out; + skb_pull(skb, i_size); + buf += i_size; + nbss_lock_session(session); + session->i_size -= i_size; + i_size = 0; + } + } + while (i_size == size && !nonblock) { + dprintk("entering second loop...\n"); + passed_2nd = 1; + rc = 0; + if (session->i_state == NETBEUI_RECV_NO_RECEIVE && + nbss_isend_receive_outstanding(session)) { + dprintk("session->i_state == " + "NETBEUI_RECV_NO_RECEIVE && " + "nbss_isend_receive_outstanding(session)\n"); + goto out; + } + /* nbss_sleep_on calls nbss_release_session */ + nbss_sleep_on(session, TASK_INTERRUPTIBLE); + rc = -ERESTART; + if (signal_pending(current)) { + dprintk("signal_pending(current)\n"); + goto out; + } + if (session->i_size) { + dprintk("session->i_size != 0, goto try_read\n"); + goto try_read; + } + rc = -ECONNABORTED; + if (session->zapped) { + dprintk("session->zapped != 0\n"); + goto out; + } + rc = -ETIME; + if (session->i_aborted) { + dprintk("session->i_aborted != 0\n"); + goto out; + } + } + nbss_release_session(session); + rc = i_size == size ? -EAGAIN : (size - i_size); +out: session_put(session); + return rc; +} + +/* + * Function: nbss_abort_receive + * The interface which aborts a receive operation, usually called from + * upper interface when receive timers expire. + * Parameters: + * session: pointer to session_t whose send operation is to be aborted. + * Returns: None + */ +void nbss_abort_receive(session_t *session) +{ + session_hold(session); + session->i_aborted = 1; + session->status = -ETIME; + wake_up_interruptible(&session->waitq); + session_put(session); +} + +/* + * Function: nbss_receive_ready + * Determines if session has data in input stream queue or not + * Parameters: + * session: pointer to session_t. + * Returns: + * 1: if session is ready to send data + * 0: if session is not ready to send data + */ +int nbss_receive_ready(session_t *session) +{ + int rc; + session_hold(session); + rc = session->i_size; + session_put(session); + return rc; +} + +/* + * Function: nbss_trim_data + * Removes some bytes from a DATA ONLY LAST frame which is fetched + * before. + * Parameters: + * session: pointer to session_t. + * Returns: + * 0: always returns zero + * Notes: + * - This feature is activated via ioctl interface and has special + * meaning to SAMBA that operates over NetBEUI + * - skb->acked flags the frame as a DATA ONLY LAST frame + * - skb->used indicates that some of frame data is fetched + * Important Note: + * - Windows API implements NetBEUI socket interface of type SOCK_SEQPACKET + * and sends garbage at end of SMB messages. We have implemented + * SOCK_STREAM which accepts those garbages. The users process + * activates an IOCTL to remove unused data bytes from the stream of + * bytes. + * - Another solution is modifying socket read mechanism so that a process + * can read the whole message. This may significantly improve SAMBA reads + * but reduces NetBEUI extensibility. + */ +int nbss_trim_data(session_t *session) +{ + struct sk_buff *skb; + + session_hold(session); + skb = skb_peek(&session->i_skbq); + if (skb) { + nbss_lock_session(session); + __skb_unlink(skb, &session->i_skbq); + session->i_size -= skb->len; + nbss_release_session(session); + kfree_skb(skb); + } + session_put(session); + return 0; +} + +/* + * Function: nbss_hangup + * The upper layer interface which terminates a session by generating a + * proper event. + * Parameters: + * session: pointer to session_t which is to be terminated + * Returns: None + * Notes: + * - During session termination there may be some unacknowledged data in + * input stream queue whose acknowledgement is not a an action of session + * transition handlers, since session data input stream is not part of + * Session State Machine. + */ +void nbss_hangup(session_t *session) +{ + session_hold(session); + del_timer(&session->timer); + if (session->o_ack_correlator) + nbss_isend_data_ack(session, + (unsigned short)session->o_ack_correlator); + nbss_handle_event(NETBEUI_SESS_HANGUP, session); + session_put(session); + session_put(session); +} + +/* + * Function: nbss_abort_session + * This upper layer interface abnormally terminates a session. + * Parameters: + * session: pointer to session_t which is to be aborted + * Returns: None + */ +void nbss_abort_session(session_t *session) +{ + session_hold(session); + session->zapped = 1; + del_timer(&session->timer); + nbss_abort_receive(session); + nbss_handle_event(NETBEUI_SESS_ABORT_SEND, session); + nbss_handle_event(NETBEUI_SESS_ABORT, session); + session_put(session); +} + +/* + * Function: nbss_get_name_query + * Accepts a NAME QUERY frame and depending on FIND/QUERY characteristic + * of it either responds NAME FIND or generates an event to start + * session establishment. + * Parameters: + * skb : pointer to sk_buff that holds the frame + * remote_mac: pointer to MAC address of remote node who sent the frame + * Returns: None + * Notes: + * - NAME FIND and NAME QUERY use the same frame format with different + * flags and field values. + * - NAME FIND processing is simply responding with a NAME RECOGNIZED + * - NAME QUERY processing is doing the first step of session establishment + * - Since the skb is reused for generating response frame it is passed to + * element in session->skb + */ +void nbss_get_name_query(struct sk_buff *skb, unsigned char *remote_mac) +{ + dgram_t *hdr = (dgram_t *)skb->data; + name_t *nb_name = nbns_find_name(hdr->dest_name); + session_t *session = nbss_find_listen(hdr->dest_name); + session_t tmp_session; + + if (!session) { + session = &tmp_session; + session->local_name = nb_name; + session->rsn = 0; + atomic_set(&session->refcnt, 1); + session_hold(session); + } else + session->rsn = NETBEUI_CALL_SS(hdr->data2); + if (!nb_name) { + kfree_skb(skb); + goto out; + } + session->skb = skb; + session->dev = skb->dev; + memcpy(session->remote_mac, remote_mac, skb->dev->addr_len); + memcpy(session->remote_name, hdr->source_name, NETBEUI_NAME_LEN); + session->lsn = 0; + if (!session->rsn || session->rsn == 0xFF) + nbss_unicast_name_recognized(session); + else { + /* Token Ring support */ + session->llcmac_ihl = LLCMAC_I_HEADLEN(session->dev); + nbss_handle_event(NETBEUI_SESS_CONFIRM, session); + } + nbns_name_put(nb_name); +out: session_put(session); +} + +/* + * Function: nbss_switch_get_session_initialize + * Accepts a SESSION INITIALIZE frame and generates proper event. + * Parameters: + * skb : pointer to sk_buff that holds the frame + * session: pointer to session_t structure the frame is received from + * Returns: None + * Notes: + * - Due to implementation of events in NetBEUI whose data is put element + * temporary variable and just event identifier is passed to state + * machine, the routine first checks if the session is in a proper state + * to accept event or not. + * - Since the skb is reused for generating response frame it is passed to + * element in session->skb + * - At this point session_t element timer callback function changes to the + * callback that processes delayed acknowledgements of input data + */ +static void nbss_switch_get_session_initialize(struct sk_buff *skb, + session_t *session) +{ + packet_t *hdr; + unsigned short data2; + + hdr = (packet_t *)skb->data; + data2 = hdr->data2; + if (session->state != NETBEUI_SESS_INITWAIT || + session->resp_correlator != hdr->xmit_correlator) { + kfree_skb(skb); + goto out; + } + if (!NETBEUI_IS_ABLE_TO_HANDLE_NACK(hdr)) + session->nack_indicator = NETBEUI_NACK_NONE; + if (!NETBIOS_VERSION(hdr)) + session->version = NETBEUI_VERSION_1xx; + session->tr_frame_lf = NETBEUI_TR_FRAME_LF(hdr); + /* Token Ring support */ + NETBEUI_CALC_SESS_MTU(session); + if (session->mtu > data2) + session->mtu = data2; + session->skb = skb; + nbss_handle_event(NETBEUI_SESS_CONNECT, session); + /* From now on, the session timer is used for ACK piggy-backing */ + session->timer.function = nbss_ack_timer_function; + /* skb is reused, thus we don't need to free it */ +out:; +} + +/* + * Function: nbss_switch_get_session_confirm + * Accepts a SESSION confirm frame and generates proper event. + * Parameters: + * hdr : pointer to packet_t which is frame header in sk_buff + * session: pointer to session_t structure the frame is received from + * Returns: None + * Notes: + * - Due to implementation of events in NetBEUI whose data is put element + * temporary variable and just event identifier is passed to state + * machine, the routine first checks if the session is in a proper state + * to accept event or not. + * - At this point session_t element timer callback function changes to the + * callback that processes delayed acknowledgements of input data + */ +static void nbss_switch_get_session_confirm(packet_t *hdr, session_t *session) +{ + unsigned short data2; + + data2 = hdr->data2; + if (session->state != NETBEUI_SESS_CONFWAIT || + session->resp_correlator != hdr->xmit_correlator) + goto out; + if (!NETBEUI_IS_ABLE_TO_HANDLE_NACK(hdr)) + session->nack_indicator = NETBEUI_NACK_NONE; + if (!NETBIOS_VERSION(hdr)) + session->version = NETBEUI_VERSION_1xx; + if (session->mtu > data2) + session->mtu = data2; + nbss_handle_event(NETBEUI_SESS_CONNECT, session); + /* From now on, the session timer is used for ACK piggy-backing */ + session->timer.function = nbss_ack_timer_function; +out:; +} + +/* + * Function: nbss_switch_get_data_ack + * Accepts a DATA ACK frame and generates proper event. + * Parameters: + * hdr : pointer to packet_t which is frame header in sk_buff + * session: pointer to session_t structure the frame is received from + * Returns: None + */ +static void nbss_switch_get_data_ack(packet_t *hdr, session_t *session) +{ + if (session->resp_correlator == hdr->xmit_correlator) + nbss_handle_event(NETBEUI_SESS_DATA_ACKED, session); +} + +/* + * Function: nbss_switch_get_session_data + * Accepts DATA FIRST MIDDLE and DATA ONLY LAST frames and tries to process + * frame by checking input state, data acknowledgement, controlling flow of + * data and queueing frame in input stream queue. (It does more than you + * may think at first glance) + * Parameters: + * skb : pointer to sk_buff which holds the frame + * session: pointer to session_t structure the frame is received from + * Returns: None + * Notes: + * - The frame pointers are adjusted to user data when frame is queued. + * - skb->acked is set for DATA ONLY LAST frames and is used in trimming + * user data in nbss_trim_data(). It is since we adjust pointers to user + * data not NetBIOS header of frame. + */ +static void nbss_switch_get_session_data(struct sk_buff *skb, + session_t *session) +{ + packet_t *hdr; + + hdr = (packet_t *)skb->data; + if (NETBEUI_ACK_WITH_DATA_INCLUDED(hdr)) + nbss_switch_get_data_ack(hdr, session); + if (session->i_state == NETBEUI_RECV_NO_RECEIVE || + (session->i_state == NETBEUI_RECV_RECEIVE_OUTSTANDING && + NETBEUI_RESYNCH_INDICATOR(hdr) != 0x0001) || + (session->i_state == NETBEUI_RECV_NORMAL && + NETBEUI_RESYNCH_INDICATOR(hdr) != 0x0000)) { + kfree_skb(skb); + goto out; + } + session->i_state = NETBEUI_RECV_NORMAL; + + if (session->i_size > session->i_rcvbuf || + (hdr->command == NETBEUI_DATA_FIRST_MIDDLE && + NETBEUI_RECEIVE_CONTINUE_REQUESTED(hdr) && + nbss_isend_receive_continue(hdr, session)) || + (hdr->command == NETBEUI_DATA_ONLY_LAST && + !NETBEUI_NACK_INDICATOR(hdr) && + nbss_ack_session_data(hdr, session))) { + nbss_isend_no_receive(skb, session); + goto out; + } + skb_pull(skb, hdr->length); + __skb_queue_tail(&session->i_skbq, skb); + session->i_size += skb->len; + if (hdr->command == NETBEUI_DATA_FIRST_MIDDLE) { + if (!NETBEUI_RECEIVE_CONTINUE_REQUESTED(hdr)) + session->i_notacked += skb->len; + else + session->i_notacked = 0; + } else /* DATA ONLY LAST */ + session->i_notacked = 0; + + wake_up_interruptible(&session->waitq); + session->i_total += skb->len; +out:; +} + +/* + * Function: nbss_switch_get_receive_continue + * Accepts a RECEIVE CONTINUE frame and generates a proper event. + * Parameters: + * hdr : pointer to packet_t which is frame header in sk_buff + * session: pointer to session_t structure the frame is received from + * Returns: None + */ +static void nbss_switch_get_receive_continue(packet_t *hdr, session_t *session) +{ + if (session->resp_correlator == hdr->xmit_correlator) + nbss_handle_event(NETBEUI_SESS_CONTINUE, session); +} + +/* + * Function: nbss_switch_get_no_receive + * Accepts a NO RECEIVE frame and generates proper events. The session + * state diagram purpose different events for blocking and non-blocking + * sends + * Parameters: + * hdr : pointer to packet_t which is frame header in sk_buff + * session: pointer to session_t structure the frame is received from + * Returns: None + */ +static void nbss_switch_get_no_receive(packet_t *hdr, session_t *session) +{ + session->o_receive_continue = 1; + if (!session->o_nonblock) + nbss_handle_event(NETBEUI_SESS_PAUSE, session); + else + nbss_handle_event(NETBEUI_SESS_NONBLOCK, session); +} + +/* + * Function: nbss_switch_get_receive_outstanding + * Accepts a RECEIVE OUTSTANDING frame and generates a proper event. + * Parameters: + * hdr : pointer to packet_t which is frame header in sk_buff + * session: pointer to session_t structure the frame is received from + * Returns: None + */ +static void nbss_switch_get_receive_outstanding(packet_t *hdr, + session_t *session) +{ + if (session->version == NETBEUI_VERSION_1xx) + hdr->data2 = 0; + session->o_receive_outstanding = 1; + session->r_acked = hdr->data2; + nbss_handle_event(NETBEUI_SESS_RESTART, session); +} + +/* + * Function: nbss_switch_get_session_end + * Accepts a SESSION END frame and generates a proper event. + * Parameters: + * session: pointer to session_t structure the frame is received from + * Returns: None + */ +static void nbss_switch_get_session_end(session_t *session) +{ + session->zapped = 1; + del_timer(&session->timer); + nbss_abort_receive(session); + nbss_handle_event(NETBEUI_SESS_ABORT_SEND, session); + nbss_handle_event(NETBEUI_SESS_END, session); +} + +/* + * Function: nbss_switch_frame + * This is the I-frame dispatcher. + * Parameters: + * skb : pointer to sk_buff which holds the frame + * session: pointer to session_t structure the frame is received from + * Returns: None + * Notes: + * - This function has to be called with a reference held + */ +static void nbss_switch_frame(session_t *session, struct sk_buff *skb) +{ + packet_t *hdr = (packet_t *)skb->data; + + switch (hdr->command) { + case NETBEUI_DATA_FIRST_MIDDLE: + case NETBEUI_DATA_ONLY_LAST: + nbss_switch_get_session_data(skb, session); + goto out; /* SKB is reused */ + case NETBEUI_DATA_ACK: + nbss_switch_get_data_ack(hdr, session); + break; + case NETBEUI_RECEIVE_CONTINUE: + nbss_switch_get_receive_continue(hdr, session); + break; + case NETBEUI_NO_RECEIVE: + nbss_switch_get_no_receive(hdr, session); + break; + case NETBEUI_RECEIVE_OUTSTANDING: + nbss_switch_get_receive_outstanding(hdr, session); + break; + case NETBEUI_SESSION_INITIALIZE: + nbss_switch_get_session_initialize(skb, session); + goto out; /* SKB is reused */ + case NETBEUI_SESSION_CONFIRM: + nbss_switch_get_session_confirm(hdr, session); + break; + case NETBEUI_SESSION_END: + nbss_switch_get_session_end(session); + break; + } + kfree_skb(skb); +out:; +} + +/* + * Function: nbss_deliver_frame + * Accepts an I-Frame frame and depending on session locking state either + * queues the frame for later processing (when session unlocked) or calls + * frame dispatcher for direct processing. + * Parameters: + * session: pointer to session_t structure the frame is received from + * skb : pointer to sk_buff which holds the frame + * Returns: None + */ +void nbss_deliver_frame(session_t *session, struct sk_buff *skb) +{ + session_hold(session); + if (session->users) + __skb_queue_tail(&session->back_log, skb); + else + nbss_switch_frame(session, skb); + session_put(session); +} + +/* + * Function: nbss_drop_session + * Drops a specified session on a specified link. + * Parameters: + * link : an integer that indicates the link number. + * session_no : an integer that indicates the session number. + * Returns: int + * zero : if the session dropped successfully. + * negative: if operation fails. + * -EINVAL: at least one of the arguments is invalid. + */ +int nbss_drop_session(int link, int session_no) +{ + session_t *sn; + link_t *nb_link = nbll_get_link(link); + dextab_t *sn_tbl; + int rc = -EINVAL; + + if (!nb_link) /* Invalid link number */ + goto out; + sn_tbl = &nb_link->session_table; + spin_lock_bh(&sn_tbl->lock); + rc = -EINVAL; + if (session_no > sn_tbl->size) { /* Invalid session number */ + spin_unlock_bh(&sn_tbl->lock); + goto out; + } + sn = sn_tbl->addr[session_no]; + spin_unlock_bh(&sn_tbl->lock); + if (!sn) /* no such session */ + goto out; + session_hold(sn); + /* Announce the link manager */ + nbll_detach_session(link, session_no); + /* Announce the session state machine */ + nbss_abort_session(sn); + session_put(sn); +out: nbll_link_put(nb_link); + return rc; +} + +/* Session service state machine functions */ +/* + * Function: nbss_lock_session + * Locks a session while processing a critical region. + * Parameters: + * session: pointer to session_t structure which is to be locked + * Returns: None + * Notes: + * - Locking is a low cost mechanism for avoiding races when a critical + * region appears in code. + */ +static void nbss_lock_session(session_t *session) +{ + session->users++; + barrier(); +} + +/* + * Function: nbss_process_backlog + * Processes frames entered on a session while the session was locked it + * simply calls dispatcher for every queued frame. + * Parameters: + * session: pointer to session_t structure who may have some frames in its + * backlog. + * Returns: None + */ +static void nbss_process_backlog(session_t *session) +{ + struct sk_buff *skb; + + session_hold(session); + while ((skb = __skb_dequeue(&session->back_log)) != NULL) + nbss_switch_frame(session, skb); + session_put(session); +} + +/* + * Function: nbss_release_session + * Unlocks a previously locked session. + * Parameters: + * session : pointer to session_t structure which is to be unlocked + * Returns: + * 0 : if session is successfully unlocked. + * -ECONNABORTED: if session is aborted + * Notes: + * - The return value is important to nbss_sleep_on() who decides whether + * to re-schedule system or continue execution of current process. + */ +static int nbss_release_session(session_t *session) +{ + int rc = 0; + + barrier(); + if (!session->users) + goto out; + if (!--session->users) + nbss_process_backlog(session); + if (session->zapped) + rc = session->status = -ECONNABORTED; +out: return rc; +} Index: kernel-acme/net/netbeui/sock_dgram.c diff -u /dev/null kernel-acme/net/netbeui/sock_dgram.c:1.1.12.1 --- /dev/null Sat Dec 22 02:21:25 2001 +++ kernel-acme/net/netbeui/sock_dgram.c Thu Nov 29 20:36:57 2001 @@ -0,0 +1,456 @@ +/* + * sock_dgram.c - Contains functions that supply SOCK_DGRAM type sockets for + * NetBEUI protocol stack which their names has a 'nbso_dgram_' + * prefix. + * Notes: + * - VRP in comments is the acronym of "Value Result Parameter" + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SOCK_DGRAM Calls */ +/* + * Function: nbso_dgram_release + * Performs additional actions at release of SOCK_DGRAM sockets. + * + * Parameters: + * sock : pointer to socket that must be released. + * + * Returns: int + * 0 : in all cases. (this function always succeed) + */ +static int nbso_dgram_release(struct socket *sock) +{ + struct sock *sk = sock->sk; + + if (sk) { + sock_orphan(sk); + sock_hold(sk); + lock_sock(sk); + if (NB_SK(sk)->u.dg.namep) { + nbdg_del_name(NB_SK(sk)->u.dg.namep); + if (NB_SK(sk)->name) + nbns_del_name(NB_SK(sk)->name); + } + release_sock(sk); + sock_put(sk); + } + MOD_DEC_USE_COUNT; + return 0; +} + +/* + * Function: nbso_dgram_bind + * Performs additional actions at bind of SOCK_DGRAM sockets to names. + * + * Parameters: + * sock : pointer to socket that must bind a name to it. + * uaddr : pointer to 'struct sockaddr_netbeui' that contains + * information about sightly name. + * addr_len : length of 'struct sockaddr_netbeui'. + * + * Returns: int + * 0 : if name is binded to socket successfully. + * negative: if a fault occurs. + * -EINVAL: if socket binds already, or given name is not valid. + */ +static int nbso_dgram_bind(struct socket *sock, struct sockaddr *uaddr, + int addr_len) +{ + name_t *nb_name; + struct sock *sk = sock->sk; + struct sockaddr_netbeui *addr = (struct sockaddr_netbeui *)uaddr; + int rc = -EPERM; + + if (!capable(CAP_NET_BIND_SERVICE)) + goto out; + rc = -EINVAL; + if (NB_SK(sk)->u.dg.namep || addr->snb_addr.name[0] == '*') + goto out; + rc = nbns_add_name(addr->snb_addr.name, addr->snb_addr.name_type, + &nb_name); + if (rc) + goto out; + rc = nbdg_add_name(addr->snb_addr.name, sk->sleep, + &NB_SK(sk)->u.dg.namep); + if (rc) + nbns_del_name(nb_name); + else + NB_SK(sk)->name = nb_name; + nbns_name_put(nb_name); +out: return rc; +} + +/* + * Function: nbso_dgram_connect + * Performs additional actions at attach of SOCK_DGRAM sockets to a + * specified peer. + * + * Parameters: + * sock : pointer to socket that must attach to peer. + * uaddr : pointer to 'struct sockaddr_netbeui' that contains + * information about peer. + * addr_len: length of 'struct sockaddr_netbeui'. + * sflags : bitwise integer that contains socket flags. + * + * Returns: int + * 0 : if socket attaches to the specified peer successfully. + * negative: if a fault occurs. + * -EINVAL: means socket not bounded normally. + * -EACCES: permission denied for broadcasting. user must sets + * the SO_BROADCAST socket option to active, before + * try to connect to all ('*'). + */ +static int nbso_dgram_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int sflags) +{ + struct sock *sk = sock->sk; + struct sockaddr_netbeui *addr = (struct sockaddr_netbeui *)uaddr; + int rc = -EINVAL; + + lock_sock(sk); + if (!NB_SK(sk)->name) + goto out; + + if (uaddr && addr_len == sizeof(*addr)) { + rc = -EACCES; + if (addr->snb_addr.name[0] == '*' && !sk->broadcast) + goto out; + sock->state = SS_CONNECTING; + memcpy(&NB_SK(sk)->u.dg.conn_name, addr, sizeof(*addr)); + nbdg_register_peername(NB_SK(sk)->u.dg.namep, + NB_SK(sk)->u.dg.conn_name.snb_addr.name); + sock->state = SS_CONNECTED; + } else { /* Invalid address means detach from previous address */ + if (sock->state == SS_UNCONNECTED) + goto out_ok; + sock->state = SS_DISCONNECTING; + nbdg_deregister_peername(NB_SK(sk)->u.dg.namep); + sock->state = SS_UNCONNECTED; + } +out_ok: rc = 0; +out: release_sock(sk); + return rc; +} + +/* + * Function: nbso_dgram_getname + * Gets SOCK_DGRAM socket name or peer name that attached to it. + * + * Parameters: + * sock : pointer to socket that we need to name of it or its peer. + * uaddr : (VRP) pointer to 'struct sockaddr_netbeui' that be filled + * with requested information. + * uaddr_len: (VRP) pointer to an integer that returns length of + * 'struct sockaddr_netbeui'. + * peer : an integer that indicates type of request. + * + * Returns: int + * 0 : if requested name is retrieved successfully. + * negative: if a fault occurs. + * -ENOTCONN: name of peer was requested but socket has not + * any attachment. + * -EBADF : socket not bounded to a name but name of it + * was requested. + */ +static int nbso_dgram_getname(struct socket *sock, struct sockaddr *uaddr, + int *uaddr_len, int peer) +{ + struct sock *sk = sock->sk; + struct sockaddr_netbeui *addr = (struct sockaddr_netbeui *)uaddr; + int rc; + + *uaddr_len = sizeof(*addr); + lock_sock(sk); + if (peer) { + rc = -ENOTCONN; + if (sock->state != SS_CONNECTED) + goto out; + memcpy(addr, &NB_SK(sk)->u.dg.conn_name, sizeof(*addr)); + } else { + rc = -EBADF; + if (!NB_SK(sk)->u.dg.namep) + goto out; + memcpy(addr->snb_addr.name, NB_SK(sk)->u.dg.namep->name, + NETBEUI_NAME_LEN); + addr->snb_addr.name_type = NB_SK(sk)->name->type; + } + rc = 0; +out: release_sock(sk); + return rc; +} + +/* + * Function: nbso_dgram_poll + * Determines operational (particularly I/O) condition of SOCK_STREAM + * socket. + * + * Parameters: + * sock : pointer to socket that check it. + * sel_type: an integer that determines type of checking. + * wait : pointer to a particular structure that contains some + * wait queues. The system itself checks members of these + * wait queues for their time outs. we only sleep on this + * structure if there is not exist a categoric answer, so far. + * + * Returns: int + * 0 : means that however must wait. + * 1 : means that answer is positive or an error occurred. + */ +static unsigned int nbso_dgram_poll(struct file *file, struct socket *sock, + poll_table *wait) +{ + struct sock *sk = sock->sk; + unsigned int mask = POLLWRNORM; + + poll_wait(file, sk->sleep, wait); + + if (sk->err) + mask |= POLLERR; + if (!NB_SK(sk)->u.dg.namep) + mask |= POLLERR; + else + if (!nbdg_receive_ready(NB_SK(sk)->u.dg.namep)) + mask |= POLLIN | POLLRDNORM; + return mask; +} + +/* + * Function: nbso_dgram_ioctl + * Performs some particular operations on SOCK_DGRAM socket, that can not + * do with regular system calls. + * + * Parameters: + * sock : pointer to socket that action must perform on it. + * cmd : an integer that indicates type of operation. + * arg : this parameter often is a pointer to 'cmd' relative data + * structure that be used by it as an argument. + * + * Returns: int + * 0 : if cmd is performed successfully. + * negative: if a fault occurs. error codes that bubble to user are + * dependent to cmd. + */ +static int nbso_dgram_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg) +{ + struct sock *sk = sock->sk; + int rc = -EINVAL; + + lock_sock(sk); + if (cmd == SIOCRUWDGF) { + int len; + + if (!NB_SK(sk)->u.dg.namep) + goto out; + rc = -EFAULT; + if (get_user(len, (int *)arg)) + goto out; + rc = -EINVAL; + if (len < 0) + goto out; + rc = nbdg_remove_unwanted_dgf(NB_SK(sk)->u.dg.namep, len); + } +out: release_sock(sk); + return rc; +} + +/* + * Function: nbso_dgram_sendmsg + * Sends a DATAGRAM message through a SOCK_DGRAM socket to desired + * target(s). + * + * Parameters: + * sock : a pointer to socket that data sends through it. + * msg : a pointer to 'struct msghdr' that contains message body, + * target name and etc. + * Note: msg->msg_control AND msg->msg_controllen are per + * protocol magic fields, and in our sendmsg() they + * indicate alias name to use for message sender name + * instead of the name that socket binds to it. + * len : length of message all around. + * nonblock: an integer that if be set to non-zero value means that + * no waiting (sleeping, blocking & ...) acceptable during + * operation. + * sflags : bitwise integer that contains socket flags. + * + * Returns: int + * positive: indicates how many bytes of data was sent. + * negative: if a fault occurs. + * -EINVAL : if a flag specified (we do not support any + * flags), or socket not bounded normally, or + * given target name is not valid. + * -EACCES : permission denied for broadcasting. user must + * sets the SO_BROADCAST socket option to active, + * before try to broadcasts a message. + * -ENOTCONN: target name not given and socket is not + * attached to any peer. + */ +static int nbso_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len, + struct scm_cookie *scm) +{ + char *local_name, name_buff[NETBEUI_NAME_LEN]; + struct sock *sk = sock->sk; + int rc, noblock = msg->msg_flags & MSG_DONTWAIT; + struct sockaddr_netbeui *remote_addr; + + lock_sock(sk); + if (msg->msg_name) { + struct sockaddr_netbeui *addr = (struct sockaddr_netbeui *) + msg->msg_name; + rc = -EINVAL; + if (!NB_SK(sk)->name || msg->msg_namelen < sizeof(*addr) || + (addr->snb_family && addr->snb_family != AF_NETBEUI)) + goto out; + rc = -EACCES; + if (addr->snb_addr.name[0] == '*' && !sk->broadcast) + goto out; + remote_addr = addr; + } else { + rc = -ENOTCONN; + if (sock->state != SS_CONNECTED) + goto out; + remote_addr = &NB_SK(sk)->u.dg.conn_name; + } + if (msg->msg_control && msg->msg_controllen == NETBEUI_NAME_LEN) { + rc = -EFAULT; + if (copy_from_user(name_buff, msg->msg_control, + NETBEUI_NAME_LEN)) + goto out; + local_name = name_buff; + } else + local_name = NB_SK(sk)->name->name; + /* All things are good, so start to send data ... */ + rc = nbdg_send(sk, local_name, remote_addr->snb_addr.name, + remote_addr->snb_addr.name_type, msg->msg_iov, + len, noblock); +out: release_sock(sk); + return rc; +} + +/* + * Function: nbso_dgram_recvmsg + * Receives a DATAGRAM message through a SOCK_DGRAM socket. + * + * Parameters: + * sock : a pointer to socket that data receives through it. + * msg : (VRP) a pointer to 'struct msghdr' that at return contains + * message body, source name and etc. + * Note: msg->msg_control AND msg->msg_controllen are per + * protocol magic fields, and in our recvmsg() at return + * they indicate target name of received message, that + * for sockets which connect to all ('*') may be different + * from the socket name. + * size : MAXimum length of message all around. + * nonblock: an integer that if be set to non-zero value means that + * no waiting (sleeping, blocking & ...) acceptable during + * operation. + * sflags : bitwise integer that contains socket flags. + * addr_len: (VRP) a pointer to an integer that if it is not NULL, at + * return will be filled with length of 'struct + * sockaddr_netbeui'. + * + * Returns: int + * positive: indicates how many bytes of data was received. + * negative: if a fault occurs. + * -EINVAL: if a flag specified (we do not support any flags), + * or socket not bounded to a name normally. + */ +static int nbso_dgram_recvmsg(struct socket *sock, struct msghdr *msg, + int size, int flags, struct scm_cookie *scm) +{ + int iov_no, bytes_received; + struct iovec *iov; + int nonblock = msg->msg_flags & MSG_DONTWAIT; + char *dest_name = NULL, + *source_name = NULL; + struct sock *sk = sock->sk; + int rc = -EINVAL; + + lock_sock(sk); + if (!NB_SK(sk)->u.dg.namep) + goto out; + if (msg->msg_name) { + struct sockaddr_netbeui *addr = msg->msg_name; + + addr->snb_family = AF_NETBEUI; + addr->snb_addr.reserved = 0; + source_name = addr->snb_addr.name; + } + if (msg->msg_control && msg->msg_controllen == NETBEUI_NAME_LEN) { + rc = verify_area(VERIFY_WRITE, msg->msg_control, + NETBEUI_NAME_LEN); + if (rc) + goto out; + dest_name = msg->msg_control; + } + bytes_received = 0; + iov = msg->msg_iov; + iov_no = msg->msg_iovlen; + + /* All things are good, so start to receive data ... */ + while (iov_no--) { + rc = verify_area(VERIFY_WRITE, iov->iov_base, iov->iov_len); + if (rc) { + rc = bytes_received ? : rc; + break; + } + rc = nbdg_receive(NB_SK(sk)->u.dg.namep, source_name, dest_name, + iov->iov_base, iov->iov_len, nonblock); + if (rc < 0) { + rc = bytes_received ? : rc; + break; + } + bytes_received += rc; + ++iov; + rc = bytes_received; + } +out: release_sock(sk); + return rc; +} + +/* Dispatcher struct for SOCK_DGRAM calls */ +struct proto_ops SOCKOPS_WRAPPED(nbso_dgram_proto_ops) = { + family: PF_NETBEUI, + release: nbso_dgram_release, + bind: nbso_dgram_bind, + connect: nbso_dgram_connect, + socketpair: sock_no_socketpair, + accept: sock_no_accept, + getname: nbso_dgram_getname, + poll: nbso_dgram_poll, + ioctl: nbso_dgram_ioctl, + listen: sock_no_listen, + shutdown: sock_no_shutdown, + setsockopt: sock_no_setsockopt, + getsockopt: sock_no_getsockopt, + sendmsg: nbso_dgram_sendmsg, + recvmsg: nbso_dgram_recvmsg, +}; +#include +SOCKOPS_WRAP(nbso_dgram_proto, PF_NETBEUI); Index: kernel-acme/net/netbeui/sock_name.c diff -u /dev/null kernel-acme/net/netbeui/sock_name.c:1.1.12.1 --- /dev/null Sat Dec 22 02:21:25 2001 +++ kernel-acme/net/netbeui/sock_name.c Thu Nov 29 20:36:57 2001 @@ -0,0 +1,156 @@ +/* + * sock_name.c - Contains functions that implement first layer of socket + * interface for socket type SOCK_NAME. SOCK_NAME is a new + * socket type introduced in NetBEUI used as a interface for + * manipulating NetBIOS names under kernel control. + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Socket interface layer + * SOCK_NAME interface routines + */ +/* + * Function: nbso_name_release + * Releases a SOCK_NAME by requesting Name Service to remove all names + * the socket owns. + * + * Parameters: + * sock : pointer to socket that must be released. + * + * Returns: + * 0 : always returns zero + * + * Notes: + * - The names a SOCK_NAME type socket owns are detected by their + * identifier which is socket memory address. + */ +static int nbso_name_release(struct socket *sock) +{ + struct sock *sk = sock->sk; + unsigned long id = (unsigned long)NB_SK(sk); + + nbns_del_identifier(id); + MOD_DEC_USE_COUNT; + return 0; +} + +/* + * Function: nbso_name_bind + * Manipulates (binds/unbinds) names to SOCK_NAME type socket. + * + * Parameters: + * sock : pointer to socket structure + * uaddr : pointer to 'struct sockaddr_netbeui' that contains + * information about sightly name. + * addr_len: length of 'struct sockaddr_netbeui'. + * + * Returns: + * 0 : if name is bound to socket successfully. + * other : errors reported by name service module. + * + * Notes: + * - NetBEUI extends SOCK_NAME bind system call by defining + * bind+ for registering a name from socket + * bind- for deregistering or releasing a name from socket + * * bind- is recognized by setting name_type in sockaddr_netbeui to 255 + * * bind+ is recognized by setting name_type in sockaddr_netbeui to + * other values + * + * - The names a SOCK_NAME type socket owns are detected by their + * identifier which is socket memory address. + */ +static int nbso_name_bind(struct socket *sock, struct sockaddr *uaddr, + int addr_len) +{ + struct sock *sk = sock->sk; + unsigned long id = (unsigned long)NB_SK(sk); + struct sockaddr_netbeui *addr = (struct sockaddr_netbeui *)uaddr; + name_t *nb_name; + int rc = -EPERM; + + if (!capable(CAP_NET_BIND_SERVICE)) + goto out; + nb_name = nbns_find_name(addr->snb_addr.name); + rc = 0; + if (addr->snb_addr.name_type == 0xFF) { /* Remove name from socket */ + if (nb_name) { + if (nb_name->identifier == id) + nbns_del_name(nb_name); + nbns_name_put(nb_name); + } + goto out; + } + /* Add name to socket */ + if (nb_name) { + nbns_name_put(nb_name); + goto out; + } + rc = nbns_add_name(addr->snb_addr.name, addr->snb_addr.name_type, + &nb_name); + if (!rc) { + nb_name->identifier = id; + nbns_name_put(nb_name); + } +out: return rc; +} + +/* + * Function: nbso_name_ioctl + * + * Parameters: + * + * Returns: + * + * Notes: + * - is not supported in SOCK_NAME, pass it to the config functions + */ +static int nbso_name_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg) +{ + return nbcs_ioctl(cmd, (void *)arg); +} + +/* proto_ops definition for SOCK_NAME socket type */ +struct proto_ops SOCKOPS_WRAPPED(nbso_name_proto_ops) = { + family: PF_NETBEUI, + release: nbso_name_release, + bind: nbso_name_bind, + connect: sock_no_connect, + socketpair: sock_no_socketpair, + accept: sock_no_accept, + getname: sock_no_getname, + ioctl: nbso_name_ioctl, + listen: sock_no_listen, + shutdown: sock_no_shutdown, + setsockopt: sock_no_setsockopt, + getsockopt: sock_no_getsockopt, + sendmsg: sock_no_sendmsg, + recvmsg: sock_no_recvmsg, +}; +#include +SOCKOPS_WRAP(nbso_name_proto, PF_NETBEUI); Index: kernel-acme/net/netbeui/sock_session.c diff -u /dev/null kernel-acme/net/netbeui/sock_session.c:1.1.12.2 --- /dev/null Sat Dec 22 02:21:25 2001 +++ kernel-acme/net/netbeui/sock_session.c Fri Dec 21 02:12:16 2001 @@ -0,0 +1,864 @@ +/* + * sock_session.c - Contains functions that supply SOCK_STREAM type sockets for + * NetBEUI protocol stack which their names has a + * 'nbso_session_' prefix, and also some utility functions that + * their names only has a 'nbso_' prefix. + * Notes: + * - VRP in comments is the acronym of "Value Result Parameter" + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SOCK_STREAM internal functions */ +/* + * Function: nbso_end_backlog + * Closes sessions that their connection was established but not + * accepted yet. + * Parameters: + * sk: pointer to NetBEUI socket that must close its waited connections. + * Returns: none + */ +static void nbso_end_backlog(struct sock *sk) +{ + while (NB_SK(sk)->u.st.backlog) { + session_t *sn = NB_SK(sk)->u.st.backlog; + + NB_SK(sk)->u.st.backlog = NB_SK(sk)->u.st.backlog->next; + nbss_hangup(sn); + } +} + +/* + * Function: nbso_autobind + * Automatically binds a NetBEUI socket to NAME_NUMBER_1 . + * Parameters: + * sk: pointer to NetBEUI socket that must bind it to NAME_NUMBER_1 . + * Returns: int + * 0 : if NetBEUI socket binds to NAME_NUMBER_1 successfully. + * -1: if can not bind NetBEUI socket to NAME_NUMBER_1 . + */ +static int nbso_autobind(struct sock *sk) +{ + NB_SK(sk)->name = nbns_name_number_1(); + return NB_SK(sk)->name ? 0 : -1; +} + +/* + * Function: nbso_session_ready (Call back function) + * Gets an established session from transport layer, and puts it + * in its owner's queue for sessions which are waited for accept. + * Parameters: + * sk : a pointer to NetBEUI socket that is owner of established + * session. + * session: a pointer to established session. + * Returns: none + */ +static void nbso_session_ready(struct sock *sk, session_t *sn) +{ + sock_hold(sk); + bh_lock_sock(sk); + if (NB_SK(sk)->u.st.backlog) + NB_SK(sk)->u.st.backlog->prev = sn; + sn->next = NB_SK(sk)->u.st.backlog; + sn->prev = NULL; + NB_SK(sk)->u.st.backlog = sn; + wake_up_interruptible(sk->sleep); + bh_unlock_sock(sk); + sock_put(sk); +} +/* + * Function: nbso_abort_interface_session (Call back function) + * Transport layer announces that a session is not valid from now. + * we must perform different actions depend on NetBEUI socket state: + * i) if socket state is NBSO_INIT, we are in a special case that causes + * when a 'nbss_call()' was interrupted. we must only announce + * process which wants to establish connection that its request was + * aborted. + * ii) if socket state is NBSO_RUNNING, we must announce all processes + * that wait for something on the socket. + * iii) if socket state is NBSO_LISTENNING, we only must remove the + * session from backlog list. + * Parameters: + * owner : a pointer to NetBEUI socket that is owner of aborted session. + * session: a pointer to aborted session. + * Returns: none + */ +static void nbso_abort_interface_session(struct sock *sk, session_t *sn) +{ + sock_hold(sk); + bh_lock_sock(sk); + if (sk->state == NBSO_INIT) { + sk->socket->state = SS_UNCONNECTED; + goto out; + } + if (sk->state == NBSO_RUNNING) { + sk->state = NBSO_INIT; + sk->socket->state = SS_UNCONNECTED; + wake_up_interruptible(sk->sleep); + goto out; + } + /* NOW, Certainly state is NBSO_LISTENING */ + if (sn->next) + sn->next->prev = sn->prev; + if (sn->prev) + sn->prev->next = sn->next; + else + NB_SK(sk)->u.st.backlog = sn->next; + /* To countervail deletion of this session from backlog list */ + nbss_listen_bh(NB_SK(sk)->name, sk->max_ack_backlog, sk, + nbso_abort_interface_session, nbso_session_ready); +out: bh_unlock_sock(sk); + sock_put(sk); +} + +/* SOCK_STREAM Calls */ +/* + * Function: nbso_session_release + * Performs additional actions at release of SOCK_STREAM sockets. + * Parameters: + * sock : pointer to socket that must be released. + * Returns: int + * 0 : in all cases. (this function always succeed) + */ +static int nbso_session_release(struct socket *sock) +{ + struct sock *sk = sock->sk; + + if (!sk) + goto out; + sock_orphan(sk); + sock_hold(sk); + lock_sock(sk); + sk->shutdown = SHUTDOWN_MASK; + if (sk->state == NBSO_LISTENING) { + __nbss_end_listen(NB_SK(sk)->name); + nbso_end_backlog(sk); + } + if (NB_SK(sk)->u.st.session) + nbss_hangup(NB_SK(sk)->u.st.session); + if (NB_SK(sk)->name) + nbns_del_name(NB_SK(sk)->name); + release_sock(sk); + sock_put(sk); + MOD_DEC_USE_COUNT; +out: return 0; +} + +/* + * Function: nbso_session_bind + * Performs additional actions at bind of SOCK_STREAM sockets to names. + * Parameters: + * sock : pointer to socket that must bind a name to it. + * uaddr : pointer to 'struct sockaddr_netbeui' that contains + * information about sightly name. + * addr_len: length of 'struct sockaddr_netbeui'. + * Returns: int + * 0 : if name is binded to socket successfully. + * negative: if a fault occurs. + * -EINVAL: if socket is bound already. + */ +static int nbso_session_bind(struct socket *sock, struct sockaddr *uaddr, + int addr_len) +{ + name_t *nb_name; + struct sock *sk = sock->sk; + struct sockaddr_netbeui *addr = (struct sockaddr_netbeui *)uaddr; + int rc = -EINVAL; + + if (!NB_SK(sk)->name) { + rc = nbns_add_name(addr->snb_addr.name, + addr->snb_addr.name_type, &nb_name); + if (!rc) { + NB_SK(sk)->name = nb_name; + nbns_name_put(nb_name); + } + } + return rc; +} + +/* + * Function: nbso_session_connect + * Performs additional actions at connect of SOCK_STREAM sockets to a + * specified peer. + * Parameters: + * sock : pointer to socket that must connect to peer. + * uaddr : pointer to 'struct sockaddr_netbeui' that contains + * information about peer. + * addr_len: length of 'struct sockaddr_netbeui'. + * flags : bitwise integer that contains socket flags. + * Returns: int + * 0 : if socket connects to the specified peer successfully. + * negative: if a fault occurs. + * -EISCONN : socket connected already or listens for + * incoming connection requests. + * -EAGAIN : no name available for the socket now, try + * again. + * -ECONNRESET: connection reset by peer. + */ +static int nbso_session_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags) +{ + int rc; + session_t *sn; + struct sock *sk = sock->sk; + struct sockaddr_netbeui *addr = (struct sockaddr_netbeui *)uaddr; + + lock_sock(sk); + rc = -EISCONN; + if (sk->state != NBSO_INIT) + goto out; + if (!NB_SK(sk)->name) { + rc = -EAGAIN; /* return -EADDRNOTAVAIL; ?! */ + if (nbso_autobind(sk)) + goto out; + } + sock->state = SS_CONNECTING; + rc = nbss_call(NB_SK(sk)->name, addr->snb_addr.name, sk, + nbso_abort_interface_session, &sn); + if (rc) + goto out; + rc = -ECONNRESET; + if (sock->state != SS_CONNECTING) + goto out; + sock->state = SS_CONNECTED; + sk->state = NBSO_RUNNING; + sk->sleep = &sn->waitq; + NB_SK(sk)->u.st.session = sn; + rc = 0; +out: release_sock(sk); + return rc; +} + +static struct sock *nbso_session_accept_newsk(struct sock *sk, + struct socket *newsock) +{ + struct sock *nsk = sk_alloc(PF_NETBEUI, sk->allocation, 1, NULL); + + if (!nsk) + goto out; + memset(NB_SK(nsk), 0, sizeof(*NB_SK(nsk))); + sock_init_data(newsock, nsk); + NB_SK(nsk)->u.st.session = NB_SK(sk)->u.st.backlog; + NB_SK(nsk)->u.st.session->owner = nsk; + newsock->state = SS_CONNECTED; + NB_SK(nsk)->name = NB_SK(sk)->name; + nbns_name_hold(NB_SK(sk)->name); + nsk->state = NBSO_RUNNING; + nsk->sleep = &NB_SK(nsk)->u.st.session->waitq; + NB_SK(sk)->u.st.backlog = NB_SK(sk)->u.st.backlog->next; + + if (NB_SK(sk)->u.st.backlog) + NB_SK(sk)->u.st.backlog->prev = NULL; + nbss_listen(NB_SK(sk)->name, sk->max_ack_backlog, sk, + nbso_abort_interface_session, nbso_session_ready); +out: return nsk; +} + +/* + * Wait for an incoming connection, avoid race conditions. This must be called + * with the socket locked. + */ +static int nbso_session_wait_for_connect(struct sock *sk) +{ + DECLARE_WAITQUEUE(wait, current); + int rc, timeout = netbios_config.inactivity_timeout * HZ; + + add_wait_queue_exclusive(sk->sleep, &wait); + for (;;) { + __set_current_state(TASK_INTERRUPTIBLE); + if (!NB_SK(sk)->u.st.backlog) { + release_sock(sk); + timeout = schedule_timeout(timeout); + lock_sock(sk); + } + rc = 0; + if (NB_SK(sk)->u.st.backlog) + break; + rc = -EINVAL; + if (sk->state != NBSO_LISTENING) + break; + rc = -ERESTARTSYS; + if (signal_pending(current)) + break; + rc = -EAGAIN; + if (!timeout) + break; + } + __set_current_state(TASK_RUNNING); + remove_wait_queue(sk->sleep, &wait); + return rc; +} + +/* + * Function: nbso_session_accept + * Performs additional actions at accept of incoming connection requests + * for a SOCK_STREAM socket. + * Parameters: + * sock : pointer to socket that wants to accept the incoming + * connection requests. + * newsock: (Semi VRP!) pointer to a new socket with attributes like + * original that connection between it & peer will be + * established. This 'struct socket' created by system before + * call us, and we only must complete its fields. + * flags : bitwise integer that contains socket flags. + * + * Returns: int + * 0 : if connection is successfully established between newsock + * and peer. + * negative: if a fault occurs. + * -EINVAL : this operation permitted only after a + * successful call of listen(). + * -EAGAIN : user requests non-blocking operation, but + * operation would block. + * -ERESTARTSYS: interrupted system call. + */ +static int nbso_session_accept(struct socket *sock, struct socket *newsock, + int flags) +{ + struct sock *sk = sock->sk, *nsk; + int rc = -EINVAL; + + lock_sock(sk); + if (sk->state != NBSO_LISTENING) + goto out; + newsock->state = SS_CONNECTING; + + if (!NB_SK(sk)->u.st.backlog) { + rc = -EAGAIN; + if (flags & O_NONBLOCK) + goto err; + rc = nbso_session_wait_for_connect(sk); + if (rc) + goto err; + } + nsk = nbso_session_accept_newsk(sk, newsock); + rc = -ENOBUFS; + if (!nsk) + goto out; + rc = nbss_listen(NB_SK(sk)->name, sk->max_ack_backlog, sk, + nbso_abort_interface_session, nbso_session_ready); + if (rc < 0) + goto err; + MOD_INC_USE_COUNT; +out: release_sock(sk); + return rc; +err: newsock->state = SS_UNCONNECTED; + goto out; +} + +/* + * Function: nbso_session_getname + * Gets SOCK_STREAM socket name or peer name that connected to it. + * Parameters: + * sock : pointer to socket that we need to name of it or its peer. + * uaddr : (VRP) pointer to 'struct sockaddr_netbeui' that be filled + * with requested information. + * uaddr_len : (VRP) pointer to an integer that returns length of + * 'struct sockaddr_netbeui'. + * peer : an integer that indicates type of request. + * Returns: int + * 0 : if requested name is retrieved successfully. + * negative: if a fault occurs. + * -ENOTCONN: name of peer was requested but socket has not + * any connection. + * -EBADF : socket not bounded to a name but name of it + * was requested. + */ +static int nbso_session_getname(struct socket *sock, struct sockaddr *uaddr, + int *uaddr_len, int peer) +{ + int rc; + struct sock *sk = sock->sk; + struct sockaddr_netbeui *addr = (struct sockaddr_netbeui *)uaddr; + + lock_sock(sk); + if (peer) { + rc = -ENOTCONN; + if (sk->state != NBSO_RUNNING) + goto out; + memcpy(addr->snb_addr.name, + NB_SK(sk)->u.st.session->remote_name, NETBEUI_NAME_LEN); + addr->snb_addr.name_type = + NB_SK(sk)->u.st.session->remote_name_type; + } else { + rc = -EBADF; + if (!NB_SK(sk)->name) + goto out; + memcpy(addr->snb_addr.name, NB_SK(sk)->name->name, + NETBEUI_NAME_LEN); + addr->snb_addr.name_type = NB_SK(sk)->name->type; + } + rc = 0; + *uaddr_len = sizeof(*addr); +out: release_sock(sk); + return rc; +} + +/* + * Function: nbso_session_poll + * Determines operational (particularly I/O) condition of SOCK_STREAM + * socket. + * Parameters: + * sock : pointer to socket that check it. + * sel_type: an integer that determines type of checking. + * wait : pointer to a particular structure that contains some wait + * queues. The system itself checks members of these wait queues + * for their time outs. we only sleep on this structure if there + * is not exist a categoric answer, so far. + * Returns: int + * 0: means that however must wait. + * 1: means that answer is positive or an error occurred. + */ +static unsigned int nbso_session_poll(struct file *file, struct socket *sock, + poll_table *wait) +{ + struct sock *sk = sock->sk; + unsigned int mask = 0; + + poll_wait(file, sk->sleep, wait); + if (sk->err) + mask |= POLLERR; + if (sk->shutdown == SHUTDOWN_MASK || sk->state != NBSO_RUNNING) + mask |= POLLHUP; + if (sk->shutdown & RCV_SHUTDOWN) + mask |= POLLIN | POLLRDNORM; + /* Connected? */ + if (sk->state == NBSO_RUNNING) { + if (nbss_receive_ready(NB_SK(sk)->u.st.session)) + mask |= POLLIN | POLLRDNORM; + if (!(sk->shutdown & SEND_SHUTDOWN) && + nbss_send_ready(NB_SK(sk)->u.st.session)) + mask |= POLLOUT | POLLWRNORM; + } + return mask; +} + +/* + * Function: nbso_session_ioctl + * Performs some particular operations on SOCK_STREAM socket, that can not + * do with regular system calls. + * Parameters: + * sock: pointer to socket that action must perform on it. + * cmd : an integer that indicates type of operation. + * arg : this parameter often is a pointer to 'cmd' relative data + * structure that be used by it as an argument. + * Returns: int + * 0 : if cmd is performed successfully. + * negative: if a fault occurs. error codes that bubble to user are + * dependent to cmd. + */ +static int nbso_session_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg) +{ + int rc = -EOPNOTSUPP; + struct sock *sk = sock->sk; + session_t *session; + + lock_sock(sk); + session = NB_SK(sk)->u.st.session; + if (cmd == SIOCTRIMDATA) { + if (sk->state == NBSO_RUNNING) + rc = nbss_trim_data(session); + } else if (cmd == SIOCSENDZERO) { + if (sk->state == NBSO_RUNNING) + rc = nbss_send_zero(session, (char *)arg); + } else + rc = -EINVAL; + release_sock(sk); + return rc; +} + +/* + * Function: nbso_session_listen + * Listens for incoming connection requests, and places them in a queue + * that MAXimum of its length is 'backlog'. this operation defined only + * for SOCK_STREAM functions. + * Parameters: + * sock : pointer to socket that must listens for incoming requests. + * backlog: an integer that indicates length of queue which holds + * incoming requests that not accepted yet. + * Returns: int + * 0 : if operation is performed successfully. + * negative: if a fault occurs. + * -EPERM : this operation not permitted on a connected socket. + */ +static int nbso_session_listen(struct socket *sock, int backlog) +{ + struct sock *sk = sock->sk; + int rc = -EPERM; + + lock_sock(sk); + if (sk->state == NBSO_RUNNING) + goto out; + if (!(unsigned)backlog) /* BSDism */ + backlog = 1; + if ((unsigned)backlog > SOMAXCONN) + backlog = SOMAXCONN; + if (backlog > sk->max_ack_backlog) + nbss_listen(NB_SK(sk)->name, backlog, sk, + nbso_abort_interface_session, nbso_session_ready); + sk->max_ack_backlog = backlog; + sk->state = NBSO_LISTENING; + rc = 0; +out: release_sock(sk); + return rc; +} + +/* + * Function: nbso_session_shutdown + * Shuts down part of a full-duplex connection. + * Parameters: + * sock: pointer to socket that part of its connection must be closed. + * how : an integer that indicates part of full_duplex connection that + * must be closed. + * Returns: int + * 0 : if operation is performed successfully. + * negative: if a fault occurs. + * -ENOTCONN: the specified socket is not connected. + * -EINVAL : the 'how' parameter has not a valid value. + */ +static int nbso_session_shutdown(struct socket *sock, int how) +{ + struct sock *sk = sock->sk; + int rc = -ENOTCONN; + + lock_sock(sk); + if (!sk) + goto out; + /* To avoid short circuiting by compiler */ + rc = -ENOTCONN; + if (sk->state != NBSO_RUNNING) + goto out; + how++; /* + * maps 0->1 has the advantage of making bit 1 rcvs and + * 1->2 bit 2 snds. + * 2->3 + */ + rc = -EINVAL; + if ((how & ~SHUTDOWN_MASK) || !how) /* Is "1 <= how <= 3" ?! */ + goto out; + sk->shutdown |= how; + rc = 0; +out: release_sock(sk); + return rc; +} + +/* + * Function: nbso_session_setsockopt + * Sets some operational options of SOCK_STREAM sockets. + * Parameters: + * sock : a pointer to socket that must tune its options. + * level : this parameter is not used in this function and always is + * zero. + * optname: an integer that indicates option that must tune. + * optval : a pointer to related data structure which used for assign + * value(s) to option. + * optlen : length of data structure that 'optval' points to it. + * + * Returns: int + * 0 : if tuning is performed successfully. + * negative: if a fault occurs. + * -EOPNOTSUPP : Operation not supported by us. + * -ENOPROTOOPT: Option name is not defined for us. + */ +static int nbso_session_setsockopt(struct socket *sock, int level, int optname, + char *optval, int optlen) +{ + int rc = 0; + struct sock *sk = sock->sk; + + lock_sock(sk); + switch (optname) { + case SO_SNDBUF: + case SO_RCVBUF: + case SO_SNDLOWAT: + case SO_RCVLOWAT: + rc = -EOPNOTSUPP; + break; + case SO_SNDTIMEO: + if (copy_from_user((void *)&NB_SK(sk)->u.st.sto, optval, + MIN(sizeof(NB_SK(sk)->u.st.sto), + optlen))) + rc = -EFAULT; + break; + case SO_RCVTIMEO: + if (copy_from_user((void *)&NB_SK(sk)->u.st.rto, optval, + MIN(sizeof(NB_SK(sk)->u.st.rto), + optlen))) + rc = -EFAULT; + break; + default: + rc = -ENOPROTOOPT; + break; + } + release_sock(sk); + return rc; +} + +/* + * Function: nbso_session_getsockopt + * Gets some operational options of SOCK_STREAM sockets. + * Parameters: + * sock : a pointer to socket that action performs on it. + * level : this parameter is not used in this function and always is + * zero. + * optname: an integer that indicates option that must be gotten. + * optval : (VRP) a pointer to related data structure which used for + * getting value(s) of option. + * optlen : (VRP) length of data structure that 'optval' points to it. + * + * Returns: int + * 0 : if operation is performed successfully. + * negative: if a fault occurs. + * -EOPNOTSUPP : Operation not supported by us. + * -ENOPROTOOPT: Option name is not defined for us. + */ +static int nbso_session_getsockopt(struct socket *sock, int level, int optname, + char *optval, int *optlen) +{ + int len, rc = 0; + struct sock *sk = sock->sk; + + lock_sock(sk); + switch (optname) { + case SO_SNDBUF: + case SO_RCVBUF: + case SO_SNDLOWAT: + case SO_RCVLOWAT: + rc = -EOPNOTSUPP; + break; + case SO_SNDTIMEO: + if (get_user(len, (int *)optlen)) { + rc = -EFAULT; + break; + } + len = MIN(len, sizeof(NB_SK(sk)->u.st.sto)); + if (copy_to_user(optval, + (void *)&NB_SK(sk)->u.st.sto, len) || + put_user(len, (int *)optlen)) + rc = -EFAULT; + break; + case SO_RCVTIMEO: + if (get_user(len, (int *)optlen)) { + rc = -EFAULT; + break; + } + len = MIN(len, sizeof(NB_SK(sk)->u.st.rto)); + if (copy_to_user(optval, + (void *)&NB_SK(sk)->u.st.rto, len) || + put_user(len, (int *)optlen)) + rc = -EFAULT; + break; + default: + rc = -ENOPROTOOPT; + break; + } + release_sock(sk); + return rc; +} + +/* + * Function: nbso_session_sendmsg + * Sends a message through a SOCK_STREAM socket to desired target. + * Parameters: + * sock : a pointer to socket that data sends through it. + * msg : a pointer to 'struct msghdr' that contains message body, + * target name and etc. + * len : length of message all around. + * nonblock: an integer that if be set to non-zero value means that + * no waiting (sleeping, blocking & ...) acceptable during + * operation. + * flags : bitwise integer that contains socket flags. + * Returns: int + * positive: indicates how many bytes of data was sent. + * negative: if a fault occurs. + * -EINVAL : we do not support any flags. + * -EPIPE : 'send part' of full-duplex connection was + * closed already. + * -ENOTCONN : socket is not connected yet. + * -EMSGSIZE : length of one of iovec buffers is greater + * than NETBEUI_MAX_DATALEN. + * -EWOULDBLOCK: user requests non-blocking operation, but + * operation would block. + */ +static int nbso_session_sendmsg(struct socket *sock, struct msghdr *msg, + int len, struct scm_cookie *scm) +{ + int rc, iov_no, bytes_sent; + int nonblock = msg->msg_flags & MSG_DONTWAIT; + struct iovec *iov; + struct timer_list snd_tmr; + struct sock *sk = sock->sk; + + lock_sock(sk); + rc = -EPIPE; + if (sk->shutdown & SEND_SHUTDOWN) { + send_sig(SIGPIPE, current, 1); + goto out; + } + rc = -ENOTCONN; + if (sock->state != SS_CONNECTED || sk->state != NBSO_RUNNING) + goto out; + init_timer(&snd_tmr); + if (NB_SK(sk)->u.st.sto.tv_sec || NB_SK(sk)->u.st.sto.tv_usec) { + snd_tmr.expires = jiffies + NB_SK(sk)->u.st.sto.tv_sec * HZ + + NB_SK(sk)->u.st.sto.tv_usec / (1000000 / HZ); + snd_tmr.data = (unsigned long)NB_SK(sk)->u.st.session; + snd_tmr.function = (void *)nbss_abort_send; + add_timer(&snd_tmr); + } + rc = bytes_sent = 0; + iov = msg->msg_iov; + iov_no = msg->msg_iovlen; + /* All things are good, so start to send data ... */ + while (iov_no--) { + /* Currently, limit on size of data + which can be sent is 64K-bytes */ + if (iov->iov_len > NETBEUI_MAX_DATALEN) { + rc = bytes_sent ? : -EMSGSIZE; + break; + } + rc = nbss_send(NB_SK(sk)->u.st.session, iov->iov_base, + iov->iov_len, nonblock, 0); + if (rc < 0) { + rc = bytes_sent ? : rc; + break; + } + bytes_sent += rc; + + if (rc < iov->iov_len) { + rc = bytes_sent ? : -EWOULDBLOCK; + break; + } + ++iov; + rc = bytes_sent; + } + del_timer(&snd_tmr); +out: release_sock(sk); + return rc; +} + +/* + * Function: nbso_session_recvmsg + * Receives a message through a SOCK_STREAM socket from desired source. + * Parameters: + * sock : a pointer to socket that data receives through it. + * msg : (VRP) a pointer to 'struct msghdr' that at return contains + * message body, source name and etc. + * size : MAXimum length of message all around. + * nonblock: an integer that if be set to non-zero value means that no + * waiting (sleeping, blocking & ...) acceptable during + * operation. + * flags : bitwise integer that contains socket flags. + * addr_len : (VRP) a pointer to an integer that if it is not NULL, at + * return will be filled with length of struct sockaddr_netbeui. + * + * Returns: int + * positive: indicates how many bytes of data was received. + * negative: if a fault occurs. + * -EINVAL : we do not support any flags. + * -EPIPE : 'receive part' of full-duplex connection was + * closed already. + * -ENOTCONN : socket is not connected yet. + * -EWOULDBLOCK: user requests non-blocking operation, but + * operation would block. + */ +static int nbso_session_recvmsg(struct socket *sock, struct msghdr *msg, + int size, int flags, struct scm_cookie *scm) +{ + int rc, iov_no, bytes_received; + int nonblock = msg->msg_flags & MSG_DONTWAIT; + struct iovec *iov; + struct timer_list rcv_tmr; + struct sock *sk = sock->sk; + + lock_sock(sk); + rc = -EPIPE; + if (sk->shutdown & RCV_SHUTDOWN) { + send_sig(SIGPIPE, current, 1); + goto out; + } + if (sock->state != SS_CONNECTED || sk->state != NBSO_RUNNING) { + rc = -ENOTCONN; + if (!(NB_SK(sk)->u.st.session && + nbss_receive_ready(NB_SK(sk)->u.st.session))) + goto out; + } + init_timer(&rcv_tmr); + if (NB_SK(sk)->u.st.rto.tv_sec || NB_SK(sk)->u.st.rto.tv_usec) { + rcv_tmr.expires = jiffies + NB_SK(sk)->u.st.rto.tv_sec * HZ + + NB_SK(sk)->u.st.rto.tv_usec / (1000000 / HZ); + rcv_tmr.data = (unsigned long)NB_SK(sk)->u.st.session; + rcv_tmr.function = (void *)nbss_abort_receive; + add_timer(&rcv_tmr); + } + rc = bytes_received = 0; + iov = msg->msg_iov; + iov_no = msg->msg_iovlen; + + while (iov_no--) { + rc = nbss_receive(NB_SK(sk)->u.st.session, iov->iov_base, + iov->iov_len, nonblock); + if (rc < 0) { + rc = bytes_received ? : rc; + break; + } + bytes_received += rc; + + if (rc < iov->iov_len) { + rc = bytes_received ? : -EWOULDBLOCK; + break; + } + ++iov; + rc = bytes_received; + } + del_timer(&rcv_tmr); +out: release_sock(sk); + return rc; +} + +/* Dispatcher struct for SOCK_STREAM calls */ +struct proto_ops SOCKOPS_WRAPPED(nbso_session_proto_ops) = { + family: PF_NETBEUI, + release: nbso_session_release, + bind: nbso_session_bind, + connect: nbso_session_connect, + socketpair: sock_no_socketpair, + accept: nbso_session_accept, + getname: nbso_session_getname, + poll: nbso_session_poll, + ioctl: nbso_session_ioctl, + listen: nbso_session_listen, + shutdown: nbso_session_shutdown, + setsockopt: nbso_session_setsockopt, + getsockopt: nbso_session_getsockopt, + sendmsg: nbso_session_sendmsg, + recvmsg: nbso_session_recvmsg, +}; +#include +SOCKOPS_WRAP(nbso_session_proto, PF_NETBEUI); Index: kernel-acme/net/netbeui/status_serve.c diff -u /dev/null kernel-acme/net/netbeui/status_serve.c:1.1.12.1 --- /dev/null Sat Dec 22 02:21:25 2001 +++ kernel-acme/net/netbeui/status_serve.c Thu Nov 29 20:36:57 2001 @@ -0,0 +1,764 @@ +/* + * status_serve.c - Contains functions that supply STATUS service for NetBEUI + * protocol stack, and also some utility functions. + * Notes: + * - VRP in comments is the acronym of "Value Result Parameter" + * - EHF in comments is the acronym of "Event Handling Function". + * + * Copyright (c) 1997 by Procom Technology, Inc. + * 2001 by Arnaldo Carvalho de Melo + * + * This program can be redistributed or modified under the terms of the + * GNU General Public License as published by the Free Software Foundation. + * This program is distributed without any warranty or implied warranty + * of merchantability or fitness for a particular purpose. + * + * See the GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void nbst_timer_function(unsigned long input); + +/* These functions are STATUS State Transition handlers */ +static int nbst_status_query_in_initial(status_t *nb_status); +static int nbst_retry_timeout_in_all(status_t *nb_status); +static int nbst_response_timeout_in_all(status_t *nb_status); +static int nbst_status_response_in_respwait(status_t *nb_status); +static int nbst_incomp_response_in_respwait(status_t *nb_status); + +#define NBST_LENGTH_MASK 0x3FFF +#define NBST_OVERFLOW_MASK 0x4000 +#define NBST_FRAGMENT_MASK 0x8000 + +/* DataGram BroadCast Maximum Transfer Unit */ +extern unsigned int dgbc_mtu; + +static unsigned long jiffies_at_reset; + +static unsigned short int nbst_correlator; +#define nbst_next_correlator() (++nbst_correlator) + +static status_t *status_request_list; +static rwlock_t status_request_list_lock = RW_LOCK_UNLOCKED; + +typedef int (* status_event_handler_t)(status_t *); + +struct event_struct { + status_state_t next_state; + status_event_handler_t event_handler; +}; + +static struct event_struct status_state_table[2][5] = { + /* NBS_STAT_INITIAL */ +{ +{ NBS_STAT_RESPWAIT, + nbst_status_query_in_initial }, /* NBE_STAT_STATUS_QUERY */ +{ -1, NULL }, /* NBE_STAT_RETRY_TIMEOUT */ +{ -1, NULL }, /* NBE_STAT_RESPONSE_TIMEOUT */ +{ -1, NULL }, /* NBE_STAT_STATUS_RESPONSE */ +{ -1, NULL } /* NBE_STAT_INCOMP_RESPONSE */ +}, + /* NBS_STAT_RESPWAIT */ +{ +{ -1, NULL }, /* NBE_STAT_STATUS_QUERY */ +{ NBS_STAT_RESPWAIT, + nbst_retry_timeout_in_all }, /* NBE_STAT_RETRY_TIMEOUT */ +{ NBS_STAT_INITIAL, + nbst_response_timeout_in_all }, /* NBE_STAT_RESPONSE_TIMEOUT */ +{ NBS_STAT_INITIAL, + nbst_status_response_in_respwait }, /* NBE_STAT_STATUS_RESPONSE */ +{ NBS_STAT_RESPWAIT, + nbst_incomp_response_in_respwait } /* NBE_STAT_INCOMP_RESPONSE */ +} +}; + +static nb_status_buffer_t nb_status_record; +/* Internal NBST functions */ +/* + * Function: nbst_alloc_status + * Allocates a 'nb_status' structure and initializes its fields. + * Parameters: none + * Returns: status_t * + * non NULL: address of allocated nb_status. + * NULL : if can not allocate nb_status, or initialize its fields + * properly. + */ +static status_t *nbst_alloc_status(void) +{ + int status_dgram_len; + status_t *nb_status = kmalloc(sizeof(*nb_status), GFP_KERNEL); + + if (!nb_status) + goto out; + /* Implicitly initialize all fields */ + memset(nb_status, 0, sizeof(*nb_status)); + /* Allocate status skb */ + status_dgram_len = nb_cmd_hdr_len[NETBEUI_STATUS_QUERY]; + nb_status->tx_skb = alloc_skb(CALC_DG_SKBLEN(NETBEUI_MAC_B_HEADLEN, + status_dgram_len), GFP_KERNEL); + if (!nb_status->tx_skb) + goto err; + skb_reserve(nb_status->tx_skb, LLCMAC_UIB_HEADLEN()); + nb_status->tx_skb->nh.raw = nb_status->tx_skb->h.raw = + nb_status->tx_skb->data; + skb_put(nb_status->tx_skb, status_dgram_len); + nb_status->tx_skb->dev = NULL; + init_timer(&nb_status->timer); + nb_status->timer.data = (unsigned long)nb_status; + nb_status->timer.function = nbst_timer_function; + init_waitqueue_head(&nb_status->waitq); +out: return nb_status; +err: kfree(nb_status); + nb_status = NULL; + goto out; +} + +/* + * Function: nbst_free_status + * Frees a nb_status structure and its sk_buff. + * Parameters: + * nb_status : pointer to nb_status structure that must be freed. + * Returns: none + */ +static void nbst_free_status(status_t *nb_status) +{ + kfree_skb(nb_status->tx_skb); + kfree(nb_status); +} + +/* + * Function: nbst_add_status_to_list + * Adds a nb_status structure to the 'status_request_list'. + * Parameters: + * nb_status: pointer to nb_status structure that must be added to the + * list. + * Returns: none + */ +static inline void nbst_add_status_to_list(status_t *nb_status) +{ + write_lock(&status_request_list_lock); + nb_status->next = status_request_list; + status_request_list = nb_status; + write_unlock(&status_request_list_lock); +} + +/* + * Function: nbst_remove_status_from_list + * Removes a nb_status structure from the 'status_request_list'. + * Parameters: + * nb_status : pointer to nb_status structure that must be removed from + * the list. + * Returns: none + */ +static void nbst_remove_status_from_list(status_t *nb_status) +{ + status_t *entry, *prev_entry = NULL; + + write_lock(&status_request_list_lock); + for (entry = status_request_list; entry; entry = entry->next) { + if (entry == nb_status) { + if (prev_entry) + prev_entry->next = entry->next; + else + status_request_list = entry->next; + break; + } + prev_entry = entry; + } + write_unlock(&status_request_list_lock); +} + +/* + * Function: nbst_find_correlator + * Finds a nb_status in the 'status_request_list' that have a specific + * response correlator. + * Parameters: + * correlator : the response correlator that we search for it. + * Returns: status_t * + * non NULL : address of sightly nb_status in the list. + * NULL : if no match be found. + */ +static status_t *nbst_find_correlator(__u16 correlator) +{ + status_t *nb_status; + + read_lock(&status_request_list_lock); + nb_status = status_request_list; + for (; nb_status; nb_status = nb_status->next) + if (nb_status->resp_correlator == correlator) + break; + read_unlock(&status_request_list_lock); + return nb_status; +} + +/* + * Function: nbst_handle_event + * Handles an entrant event to STATUS state machine. + * Parameters: + * event : the entrant event. + * nb_status: (Semi VRP!) pointer to nb_status structure (entity) that + * event is for it. + * Returns: none + */ +static void nbst_handle_event(status_event_t event, status_t *nb_status) +{ + struct event_struct *ev = &status_state_table[nb_status->state][event]; + + if (ev && ev->event_handler) + if (!ev->event_handler(nb_status)) + nb_status->state = ev->next_state; +} + +/* + * Function: nbst_timer_function (Call back function) + * Produces an appropriate event related to number of retries + * so far, due to fire of a timer. + * Parameters: + * input : pointer to nb_status structure that timer of it has been fired. + * Returns: none + */ +static void nbst_timer_function(unsigned long input) +{ + status_t *nb_status = (status_t *)input; + + if (nb_status->retries < NETBEUI_TRANSMIT_COUNT) + nbst_handle_event(NBE_STAT_RETRY_TIMEOUT, nb_status); + else + nbst_handle_event(NBE_STAT_RESPONSE_TIMEOUT, nb_status); +} + +/* + * Function: nbst_status_query_in_initial + * (EHF) Handles NBE_STAT_STATUS_QUERY event in NBS_STAT_INITIAL state. + * Parameters: + * nb_status : pointer to nb_status structure that event happens on it. + * Returns: int + * zero : if event be handled successfully. + * non zero : if an error occurred during event handling. + */ +static int nbst_status_query_in_initial(status_t *nb_status) +{ + int rc; + dgram_t *hdrp; + + /* all fields were set to zero in nbst_alloc_status() */ + nb_status->resp_status = NO_RESPONSE; + hdrp = (dgram_t *)nb_status->tx_skb->data; + hdrp->length = nb_cmd_hdr_len[NETBEUI_STATUS_QUERY]; + hdrp->delimiter = NETBEUI_DELIMITER; + hdrp->command = NETBEUI_STATUS_QUERY; + /* We implement NetBIOS 3.0 */ + hdrp->data1 = 1; + hdrp->data2 = nb_status->sbuff_len; + hdrp->resp_correlator = nb_status->resp_correlator = + nbst_next_correlator(); + rc = -EFAULT; + if (copy_from_user(hdrp->dest_name, nb_status->called_name, + NETBEUI_NAME_LEN)) + goto out; + memcpy(hdrp->source_name, nbns_name_number_1()->name, NETBEUI_NAME_LEN); + + /* BroadCast NETBEUI_STATUS_QUERY */ + rc = nbll_uisend(NULL, nb_status->tx_skb); + if (!rc) { + nb_status->retries++; + nb_status->timer.expires = jiffies + NETBEUI_TRANSMIT_TIMEOUT; + add_timer(&nb_status->timer); + nbst_add_status_to_list(nb_status); + } +out: return rc; +} + +/* + * Function: nbst_retry_timeout_in_all + * (EHF) Handles NBE_STAT_RETRY_TIMEOUT event in all of states. + * Parameters: + * nb_status : pointer to nb_status structure that event happens on it. + * Returns: int + * zero : if event be handled successfully. + * non zero : if an error occurred during event handling. + */ +static int nbst_retry_timeout_in_all(status_t *nb_status) +{ + int rc = 0; + + nb_status->timer.expires = jiffies+ NETBEUI_TRANSMIT_TIMEOUT; + add_timer(&nb_status->timer); + if (nb_status->unicast) { + /* UniCast NETBEUI_STATUS_QUERY */ + rc = nbll_uisend(nb_status->remote_mac, nb_status->tx_skb); + if (rc) + goto out; + skb_pull(nb_status->tx_skb, + LLCMAC_UI_HEADLEN(MAC_HEADLEN(nb_status->tx_skb->dev))); + } else { + /* BroadCast NETBEUI_STATUS_QUERY */ + rc = nbll_uisend(NULL, nb_status->tx_skb); + if (rc) + goto out; + } + nb_status->retries++; +out: return rc; +} + +/* + * Function: nbst_response_timeout_in_all + * (EHF) Handles NBE_STAT_RESPONSE_TIMEOUT event in all of states. + * Parameters: + * nb_status : pointer to nb_status structure that event happens on it. + * Returns: int + * zero : this function always succeed. + */ +static int nbst_response_timeout_in_all(status_t *nb_status) +{ + nbst_remove_status_from_list(nb_status); + wake_up(&nb_status->waitq); + return 0; +} + +/* + * Function: nbst_status_response_in_respwait + * (EHF) Handles NBE_STAT_STATUS_RESPONSE event in NBS_STAT_RESPWAIT state. + * Parameters: + * nb_status : pointer to nb_status structure that event happens on it. + * Returns: int + * zero : this function always succeed. + */ +static int nbst_status_response_in_respwait(status_t *nb_status) +{ + del_timer(&nb_status->timer); + nbst_remove_status_from_list(nb_status); + if (nb_status->overflowed) + nb_status->resp_status = USER_BUFFER_OVERFLOW; + else + nb_status->resp_status = COMPLETED_RESPONSE; + return 0; +} + +/* + * Function: nbst_incomp_response_in_respwait + * (EHF) Handles NBE_STAT_INCOMP_RESPONSE event in NBS_STAT_RESPWAIT state. + * Parameters: + * nb_status : pointer to nb_status structure that event happens on it. + * Returns: int + * zero : if event be handled successfully. + * non zero : if an error occurred during event handling. + */ +static int nbst_incomp_response_in_respwait(status_t *nb_status) +{ + int rc; + + del_timer(&nb_status->timer); + nb_status->unicast = 1; + nb_status->retries = 0; + nb_status->resp_status = INCOMPLETE_RESPONSE; + ((dgram_t *)(nb_status->tx_skb->data))->data1 = nb_status->no_rx_names; + ((dgram_t *)(nb_status->tx_skb->data))->data2 = nb_status->sbuff_len - + nb_status->len_rx_info; + nb_status->timer.expires = jiffies + NETBEUI_TRANSMIT_TIMEOUT; + add_timer(&nb_status->timer); + rc = nbll_uisend(nb_status->remote_mac, nb_status->tx_skb); + if (!rc) { + skb_pull(nb_status->tx_skb, + LLCMAC_UI_HEADLEN(MAC_HEADLEN(nb_status->tx_skb->dev))); + nb_status->retries++; + } + return rc; +} + +/* + * Function: nbst_gather_status_info + * Gathers NetBIOS status information in local machine. + * Parameters: + * dev : pointer to struct net_device that its related status information + * has been requested. + * Returns: int + * positive : length of gathered status information. this function always + * succeed. + */ +static int nbst_gather_status_info(struct net_device *dev) +{ + int i; + __u8 tmp8; + __u16 non; + name_t *ntp; + unsigned long tmpl; + + if (!dev) + dev = netbeui_adapters.dev[0]; + if (dev) { + dev_hold(dev); + memcpy(nb_status_record.adptr_addr, dev->dev_addr, 6); + if (dev->type == ARPHRD_IEEE802) + nb_status_record.adptr_type_AND_sftwr_level.adptr_type = + NETBEUI_TOKEN_RING; + else if (dev->type == ARPHRD_ETHER || + dev->type == ARPHRD_EETHER) + nb_status_record.adptr_type_AND_sftwr_level.adptr_type = + NETBEUI_ETHERNET; + } else { + memset(nb_status_record.adptr_addr, 0, 6); + nb_status_record.adptr_type_AND_sftwr_level.adptr_type = 0; + } + /* We support new parameters , NetBIOS 3.0 */ + nb_status_record.adptr_type_AND_sftwr_level.sftwr_level = 0x20; + nb_status_record.sftwr_release_no = 3; /* We implement NetBIOS 3.0 */ + tmpl = (jiffies - jiffies_at_reset) / (HZ * 60); + nb_status_record.duration = tmpl > 0xFFFF ? 0xFFFF : tmpl; + nb_status_record.max_dgram_packet_size = dgbc_mtu; + nb_status_record.max_no_pend_sess = 0xFFFF; /* No limit! */ + nb_status_record.max_size_sess_data_packet = dev ? + (dev->mtu - LLCMAC_I_HEADLEN(dev) - NETBEUI_ILEN) : 0; + if (dev) + dev_put(dev); + non = nbns_count_names(); + nb_status_record.no_names_in_local_name_tbl = non; + ntp = nbns_get_name_list(); + for (i = 0; i < non; i++, ntp = ntp->next) { + memcpy(nb_status_record.local_names[i].name, ntp->name, + NETBEUI_NAME_LEN); + nb_status_record.local_names[i].name_number = ntp->name_number; + + tmp8 = ntp->type == NETBEUI_NAME_GROUP ? 0x80 : 0x00; + switch (ntp->state) { + case NETBEUI_NAME_ACQUIRED: /* A registered name */ + tmp8 |= 0x04; + break; + case NETBEUI_NAME_INITIAL: /* A deregistered name */ + tmp8 |= 0x05; + default: ; /* Only for silence of the gcc! */ + } + if (ntp->conflicted) /* A detected duplicate name */ + tmp8 |= 0x06; + nb_status_record.local_names[i].name_status = tmp8; + } + return NETBEUI_MIN_STATUS_BUFF_LEN + (NETBEUI_NAME_LEN + 2) * non; +} + +/* + * Function: nbst_local_status + * Retrieves local NetBIOS status information. + * + * Parameters: + * status_buff: pointer to user buffer that must be filled with local + * status information. + * buff_len : (VRP) pointer to an integer that indicates length of user + * buffer at start and length of retrieved information at end + * + * Returns: int + * zero : if information retrieved successfully. + * negative : if something is bad. + * -EOVERFLOW : user buffer length is not large enough to + * keep all of information, so some of it was + * copied to user buffer. + */ +static int nbst_local_status(char *status_buff, int *buff_len) +{ + int len, info_len; + + if (get_user(len, buff_len)) + return -EFAULT; + info_len = nbst_gather_status_info(NULL); + len = MIN(len, info_len); + if (copy_to_user(status_buff, &nb_status_record, len) || + put_user(len, buff_len)) + return -EFAULT; + return len < info_len ? -EOVERFLOW : 0; +} + +/* + * Function: nbst_wait_for_resp + * Waits for end of STATUS state machine operation, and supervise + * received status response frames. + * + * Parameters: + * nb_status: pointer to nb_status structure that operations perform on it + * + * Returns: none + */ +static void nbst_wait_for_resp(status_t *nb_status) +{ + sleep_on(&nb_status->waitq); + nb_status->locked = 1; + + while (nb_status->rx_skb) { + int sdl, tmp; + char *sdp; + dgram_t *hdrp = (dgram_t *)nb_status->rx_skb->data; + + nb_status->overflowed = hdrp->data2 & NBST_OVERFLOW_MASK; + /* Pointer to the status data in the received frame */ + sdp = skb_pull(nb_status->rx_skb, NETBEUI_UILEN); + sdl = hdrp->data2 & NBST_LENGTH_MASK; + tmp = nb_status->len_rx_info ? + sdl : (sdl - NETBEUI_MIN_STATUS_BUFF_LEN); + nb_status->no_rx_names += tmp / (NETBEUI_NAME_LEN + 2); + nb_status->len_rx_info += sdl; + + if (nb_status->len_rx_info < nb_status->sbuff_len) { + /* FIXME(acme): check copy_to_user result! */ + copy_to_user(nb_status->user_sbuff, (char *)sdp, sdl); + + if ((hdrp->data2 & NBST_FRAGMENT_MASK) && hdrp->data1) + nbst_handle_event(NBE_STAT_INCOMP_RESPONSE, + nb_status); + else + nbst_handle_event(NBE_STAT_STATUS_RESPONSE, + nb_status); + } + else { + sdl -= nb_status->len_rx_info - nb_status->sbuff_len; + copy_to_user(nb_status->user_sbuff, sdp, sdl); + + nbst_handle_event(NBE_STAT_STATUS_RESPONSE, nb_status); + } + nb_status->user_sbuff += sdl; + kfree_skb(nb_status->rx_skb); + nb_status->rx_skb = NULL; + + if (nb_status->state == NBS_STAT_RESPWAIT) { + barrier(); + nb_status->locked = 0; + sleep_on(&nb_status->waitq); + } + } +} + +/* + * Function: nbst_remote_status + * Retrieves NetBIOS status information of a remote host. + * + * Parameters: + * remote_name : pointer to a NetBIOS name that must retrieve status + * information about it. + * status_buff : (VRP) pointer to user buffer that must be filled with + * status information of remote host. + * buff_len : (VRP) pointer to an integer that indicates length of + * user buffer at start and length of retrieved information + * at end. + * + * Returns: int + * zero : if information retrieved successfully. + * negative: if something is bad. + * -ENONET : no network device found. + * -ENOMEM : out of memory condition. + * -EHOSTUNREACH: no response from remote host. + * -ETIMEDOUT : system timed out before retrieving all of + * information, so some of it was copied to + * user buffer. + * -EOVERFLOW : user buffer length is not large enough to + * keep all of information, so some of it was + * copied to user buffer. + */ +static int nbst_remote_status(char *remote_name, char *status_buff, + int *buff_len) +{ + status_t *nb_status; + int rc = -ENONET; + + if (!netbeui_adapters.dev[0]) + goto out; + nb_status = nbst_alloc_status(); + rc = -ENOMEM; + if (!nb_status) + goto out; + nb_status->called_name = remote_name; + nb_status->user_sbuff = status_buff; + rc = -EFAULT; + if (get_user(nb_status->sbuff_len, buff_len)) + goto out_status; + nb_status->state = NBS_STAT_INITIAL; + nbst_handle_event(NBE_STAT_STATUS_QUERY, nb_status); + if (nb_status->state != NBS_STAT_INITIAL) + nbst_wait_for_resp(nb_status); + rc = -EFAULT; + if (put_user(MIN(nb_status->sbuff_len, nb_status->len_rx_info), + buff_len)) + goto out_status; + switch (nb_status->resp_status) { + case NO_RESPONSE: + rc = -EHOSTUNREACH; + break; + case INCOMPLETE_RESPONSE: + rc = -ETIMEDOUT; + break; + case USER_BUFFER_OVERFLOW: + rc = -EOVERFLOW; + default: /* COMPLETED_RESPONSE */ + rc = 0; + } +out_status: + nbst_free_status(nb_status); +out: return rc; +} + +/* Exported N B S T Functions */ +/* + * Function: nbst_init_status + * Performs some initializes for STATUS service functions during + * installation of NetBEUI in memory. + * + * Parameters: none + * + * Returns: none + */ +void nbst_init_status(void) +{ + memset(&nb_status_record, 0, sizeof(nb_status_record)); + jiffies_at_reset = jiffies; +} + +/* + * Function: nbst_obtain_status + * Interface function for NetBEUI STATUS service. + * + * Parameters: + * remote_name: pointer to a NetBIOS name that must retrieve status + * information about it. + * status_buff: (VRP) pointer to user buffer that must be filled with + * status information. + * buff_len : (VRP) pointer to an integer that indicates length of user + * buffer at start and length of retrieved information at end + * + * Returns: int + * zero : if information retrieved successfully. + * negative : if something is bad. + */ +int nbst_obtain_status(char *called_name, char *status_buff, int *buff_len) +{ + int name; + + if (get_user(name, called_name)) + return -EFAULT; + return name == '*' ? nbst_local_status(status_buff, buff_len) : + nbst_remote_status(called_name, status_buff, + buff_len); +} + +/* + * Function: nbst_get_status_query + * Takes a NETBEUI_STATUS_QUERY frame from 'llc supplementary' and response + * to it. + * + * Parameters: + * skb: pointer to sk_buff that contains received frame. + * remote_mac: pointer to buffer that contains MAC address of sender + * of the frame. + * + * Returns: none + */ +void nbst_get_status_query(struct sk_buff *skb, unsigned char *remote_mac) +{ + int tmp, losd, nonts, info_len; + __u16 loits; + struct sk_buff *resp_skb; + dgram_t *resp_hdrp, *hdrp = (dgram_t *)skb->data; + /* Test for illegal requests */ + name_t *nb_name = nbns_find_name(hdrp->dest_name); + + if (!nb_name) + goto free_skb; + /* Status query for a group name has no meaning */ + if (nb_name->type == NETBEUI_NAME_GROUP) + goto out_put; + info_len = nbst_gather_status_info(skb->dev); + if (hdrp->data1 > 1 && + hdrp->data1 >= nb_status_record.no_names_in_local_name_tbl) + goto out_put; + /* Make a sk_buff for response */ + resp_skb = alloc_skb(skb->dev->mtu, GFP_ATOMIC); + if (!resp_skb) + goto out_put; + tmp = LLCMAC_UI_HEADLEN(MAC_HEADLEN(skb->dev)); + skb_reserve(resp_skb, tmp); + resp_skb->nh.raw = resp_skb->h.raw = resp_skb->data; + resp_hdrp = (dgram_t *)skb_put(resp_skb, + nb_cmd_hdr_len[NETBEUI_STATUS_RESPONSE]); + resp_hdrp->length = nb_cmd_hdr_len[NETBEUI_STATUS_RESPONSE]; + resp_hdrp->delimiter = NETBEUI_DELIMITER; + resp_hdrp->command = NETBEUI_STATUS_RESPONSE; + resp_hdrp->xmit_correlator = hdrp->resp_correlator; + /* Find length of data that can be sent */ + tmp = skb->dev->mtu - tmp; + losd = tmp - nb_cmd_hdr_len[NETBEUI_STATUS_RESPONSE]; + losd = MIN(losd, hdrp->data2); + + if (hdrp->data1 <= 1) { /* An initial request */ + nonts = (losd - NETBEUI_MIN_STATUS_BUFF_LEN) / + (NETBEUI_NAME_LEN + 2); + nonts = MIN(nonts, nb_status_record.no_names_in_local_name_tbl); + loits = NETBEUI_MIN_STATUS_BUFF_LEN + nonts * + (NETBEUI_NAME_LEN + 2); + memcpy(skb_put(resp_skb, loits), &nb_status_record, loits); + resp_hdrp->data1 = nonts ? nonts : 1; + } else { + nonts = losd / (NETBEUI_NAME_LEN + 2); + tmp = nb_status_record.no_names_in_local_name_tbl - hdrp->data1; + nonts = MIN(nonts, tmp); + info_len = tmp * (NETBEUI_NAME_LEN + 2); + loits = nonts * (NETBEUI_NAME_LEN + 2); + memcpy(skb_put(resp_skb, loits), + &nb_status_record.local_names[hdrp->data1], loits); + resp_hdrp->data1 = nonts + hdrp->data1; + } + loits &= NBST_LENGTH_MASK; + if (info_len > losd) + loits |= NBST_FRAGMENT_MASK; + if (info_len > hdrp->data2) + loits |= NBST_OVERFLOW_MASK; + resp_hdrp->data2 = loits; + memcpy(resp_hdrp->dest_name, hdrp->source_name, NETBEUI_NAME_LEN); + memcpy(resp_hdrp->source_name, hdrp->dest_name, NETBEUI_NAME_LEN); + resp_skb->dev = skb->dev; + kfree_skb(skb); + nbll_uisend(remote_mac, resp_skb); + nbns_name_put(nb_name); +out: return; +out_put: + nbns_name_put(nb_name); +free_skb: + kfree_skb(skb); + goto out; +} + +/* + * Function: nbst_get_status_response + * Takes a NETBEUI_STATUS_RESPONSE frame from 'llc supplementary' and + * place it on appropriate nb_status structure. + * + * Parameters: + * skb: pointer to sk_buff that contains received frame. + * remote_mac: pointer to buffer that contains MAC address of sender + * of the frame. + * + * Returns: none + */ +void nbst_get_status_response(struct sk_buff *skb, unsigned char *remote_mac) +{ + dgram_t *dgram = (dgram_t *)skb->data; + status_t *nb_status = nbst_find_correlator(dgram->xmit_correlator); + + /* If it does not match a waited status query */ + if (!nb_status) + goto free_skb; + barrier(); + if (nb_status->locked) + goto free_skb; + nb_status->rx_skb = skb; + nb_status->tx_skb->dev = skb->dev; + memcpy(nb_status->remote_mac, remote_mac, ETH_ALEN); + wake_up(&nb_status->waitq); +out: return; +free_skb: + kfree_skb(skb); + goto out; +} Index: kernel-acme/net/netlink/af_netlink.c diff -u kernel-acme/net/netlink/af_netlink.c:1.1.1.2 kernel-acme/net/netlink/af_netlink.c:1.1.1.2.10.4 --- kernel-acme/net/netlink/af_netlink.c:1.1.1.2 Thu Aug 16 18:44:24 2001 +++ kernel-acme/net/netlink/af_netlink.c Fri Dec 21 02:12:17 2001 @@ -64,6 +64,8 @@ void (*data_ready)(struct sock *sk, int bytes); }; +#define NLK_SK(__sk) ((struct netlink_opt *)(__sk)->protinfo) + static struct sock *nl_table[MAX_LINKS]; static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait); @@ -89,9 +91,9 @@ } BUG_TRAP(atomic_read(&sk->rmem_alloc)==0); BUG_TRAP(atomic_read(&sk->wmem_alloc)==0); - BUG_TRAP(sk->protinfo.af_netlink->cb==NULL); + BUG_TRAP(NLK_SK(sk)->cb==NULL); - kfree(sk->protinfo.af_netlink); + kfree(NLK_SK(sk)); atomic_dec(&netlink_sock_nr); #ifdef NETLINK_REFCNT_DEBUG @@ -156,7 +158,7 @@ read_lock(&nl_table_lock); for (sk=nl_table[protocol]; sk; sk=sk->next) { - if (sk->protinfo.af_netlink->pid == pid) { + if (NLK_SK(sk)->pid == pid) { sock_hold(sk); read_unlock(&nl_table_lock); return sk; @@ -176,13 +178,13 @@ netlink_table_grab(); for (osk=nl_table[sk->protocol]; osk; osk=osk->next) { - if (osk->protinfo.af_netlink->pid == pid) + if (NLK_SK(osk)->pid == pid) break; } if (osk == NULL) { err = -EBUSY; - if (sk->protinfo.af_netlink->pid == 0) { - sk->protinfo.af_netlink->pid = pid; + if (NLK_SK(sk)->pid == 0) { + NLK_SK(sk)->pid = pid; sk->next = nl_table[sk->protocol]; nl_table[sk->protocol] = sk; sock_hold(sk); @@ -222,21 +224,21 @@ sock->ops = &netlink_ops; - sk = sk_alloc(PF_NETLINK, GFP_KERNEL, 1); + sk = sk_alloc(PF_NETLINK, GFP_KERNEL, 1, NULL); if (!sk) return -ENOMEM; sock_init_data(sock,sk); - sk->protinfo.af_netlink = kmalloc(sizeof(struct netlink_opt), GFP_KERNEL); - if (sk->protinfo.af_netlink == NULL) { + NLK_SK(sk) = kmalloc(sizeof(struct netlink_opt), GFP_KERNEL); + if (NLK_SK(sk) == NULL) { sk_free(sk); return -ENOMEM; } - memset(sk->protinfo.af_netlink, 0, sizeof(struct netlink_opt)); + memset(NLK_SK(sk), 0, sizeof(struct netlink_opt)); - spin_lock_init(&sk->protinfo.af_netlink->cb_lock); - init_waitqueue_head(&sk->protinfo.af_netlink->wait); + spin_lock_init(&NLK_SK(sk)->cb_lock); + init_waitqueue_head(&NLK_SK(sk)->wait); sk->destruct = netlink_sock_destruct; atomic_inc(&netlink_sock_nr); @@ -253,21 +255,21 @@ netlink_remove(sk); - spin_lock(&sk->protinfo.af_netlink->cb_lock); - if (sk->protinfo.af_netlink->cb) { - sk->protinfo.af_netlink->cb->done(sk->protinfo.af_netlink->cb); - netlink_destroy_callback(sk->protinfo.af_netlink->cb); - sk->protinfo.af_netlink->cb = NULL; + spin_lock(&NLK_SK(sk)->cb_lock); + if (NLK_SK(sk)->cb) { + NLK_SK(sk)->cb->done(NLK_SK(sk)->cb); + netlink_destroy_callback(NLK_SK(sk)->cb); + NLK_SK(sk)->cb = NULL; __sock_put(sk); } - spin_unlock(&sk->protinfo.af_netlink->cb_lock); + spin_unlock(&NLK_SK(sk)->cb_lock); /* OK. Socket is unlinked, and, therefore, no new packets will arrive */ sock_orphan(sk); sock->sk = NULL; - wake_up_interruptible_all(&sk->protinfo.af_netlink->wait); + wake_up_interruptible_all(&NLK_SK(sk)->wait); skb_queue_purge(&sk->write_queue); @@ -285,7 +287,7 @@ retry: netlink_table_grab(); for (osk=nl_table[sk->protocol]; osk; osk=osk->next) { - if (osk->protinfo.af_netlink->pid == pid) { + if (NLK_SK(osk)->pid == pid) { /* Bind collision, search negative pid values. */ if (pid > 0) pid = -4096; @@ -299,7 +301,7 @@ err = netlink_insert(sk, pid); if (err == -EADDRINUSE) goto retry; - sk->protinfo.af_netlink->groups = 0; + NLK_SK(sk)->groups = 0; return 0; } @@ -316,23 +318,23 @@ if (nladdr->nl_groups && !capable(CAP_NET_ADMIN)) return -EPERM; - if (sk->protinfo.af_netlink->pid) { - if (nladdr->nl_pid != sk->protinfo.af_netlink->pid) + if (NLK_SK(sk)->pid) { + if (nladdr->nl_pid != NLK_SK(sk)->pid) return -EINVAL; - sk->protinfo.af_netlink->groups = nladdr->nl_groups; + NLK_SK(sk)->groups = nladdr->nl_groups; return 0; } if (nladdr->nl_pid == 0) { err = netlink_autobind(sock); if (err == 0) - sk->protinfo.af_netlink->groups = nladdr->nl_groups; + NLK_SK(sk)->groups = nladdr->nl_groups; return err; } err = netlink_insert(sk, nladdr->nl_pid); if (err == 0) - sk->protinfo.af_netlink->groups = nladdr->nl_groups; + NLK_SK(sk)->groups = nladdr->nl_groups; return err; } @@ -344,8 +346,8 @@ struct sockaddr_nl *nladdr=(struct sockaddr_nl*)addr; if (addr->sa_family == AF_UNSPEC) { - sk->protinfo.af_netlink->dst_pid = 0; - sk->protinfo.af_netlink->dst_groups = 0; + NLK_SK(sk)->dst_pid = 0; + NLK_SK(sk)->dst_groups = 0; return 0; } if (addr->sa_family != AF_NETLINK) @@ -355,12 +357,12 @@ if (nladdr->nl_groups && !capable(CAP_NET_ADMIN)) return -EPERM; - if (!sk->protinfo.af_netlink->pid) + if (!NLK_SK(sk)->pid) err = netlink_autobind(sock); if (err == 0) { - sk->protinfo.af_netlink->dst_pid = nladdr->nl_pid; - sk->protinfo.af_netlink->dst_groups = nladdr->nl_groups; + NLK_SK(sk)->dst_pid = nladdr->nl_pid; + NLK_SK(sk)->dst_groups = nladdr->nl_groups; } return 0; @@ -375,18 +377,18 @@ *addr_len = sizeof(*nladdr); if (peer) { - nladdr->nl_pid = sk->protinfo.af_netlink->dst_pid; - nladdr->nl_groups = sk->protinfo.af_netlink->dst_groups; + nladdr->nl_pid = NLK_SK(sk)->dst_pid; + nladdr->nl_groups = NLK_SK(sk)->dst_groups; } else { - nladdr->nl_pid = sk->protinfo.af_netlink->pid; - nladdr->nl_groups = sk->protinfo.af_netlink->groups; + nladdr->nl_pid = NLK_SK(sk)->pid; + nladdr->nl_groups = NLK_SK(sk)->groups; } return 0; } static void netlink_overrun(struct sock *sk) { - if (!test_and_set_bit(0, &sk->protinfo.af_netlink->state)) { + if (!test_and_set_bit(0, &NLK_SK(sk)->state)) { sk->err = ENOBUFS; sk->error_report(sk); } @@ -408,18 +410,18 @@ goto no_dst; #ifdef NL_EMULATE_DEV - if (sk->protinfo.af_netlink->handler) { + if (NLK_SK(sk)->handler) { skb_orphan(skb); - len = sk->protinfo.af_netlink->handler(protocol, skb); + len = NLK_SK(sk)->handler(protocol, skb); sock_put(sk); return len; } #endif if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf || - test_bit(0, &sk->protinfo.af_netlink->state)) { + test_bit(0, &NLK_SK(sk)->state)) { if (!timeo) { - if (ssk->protinfo.af_netlink->pid == 0) + if (NLK_SK(ssk)->pid == 0) netlink_overrun(sk); sock_put(sk); kfree_skb(skb); @@ -427,15 +429,15 @@ } __set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&sk->protinfo.af_netlink->wait, &wait); + add_wait_queue(&NLK_SK(sk)->wait, &wait); if ((atomic_read(&sk->rmem_alloc) > sk->rcvbuf || - test_bit(0, &sk->protinfo.af_netlink->state)) && + test_bit(0, &NLK_SK(sk)->state)) && !sk->dead) timeo = schedule_timeout(timeo); __set_current_state(TASK_RUNNING); - remove_wait_queue(&sk->protinfo.af_netlink->wait, &wait); + remove_wait_queue(&NLK_SK(sk)->wait, &wait); sock_put(sk); if (signal_pending(current)) { @@ -460,14 +462,14 @@ static __inline__ int netlink_broadcast_deliver(struct sock *sk, struct sk_buff *skb) { #ifdef NL_EMULATE_DEV - if (sk->protinfo.af_netlink->handler) { + if (NLK_SK(sk)->handler) { skb_orphan(skb); - sk->protinfo.af_netlink->handler(sk->protocol, skb); + NLK_SK(sk)->handler(sk->protocol, skb); return 0; } else #endif if (atomic_read(&sk->rmem_alloc) <= sk->rcvbuf && - !test_bit(0, &sk->protinfo.af_netlink->state)) { + !test_bit(0, &NLK_SK(sk)->state)) { skb_orphan(skb); skb_set_owner_r(skb, sk); skb_queue_tail(&sk->receive_queue, skb); @@ -493,8 +495,8 @@ if (ssk == sk) continue; - if (sk->protinfo.af_netlink->pid == pid || - !(sk->protinfo.af_netlink->groups&group)) + if (NLK_SK(sk)->pid == pid || + !(NLK_SK(sk)->groups&group)) continue; if (failure) { @@ -539,8 +541,8 @@ if (ssk == sk) continue; - if (sk->protinfo.af_netlink->pid == pid || - !(sk->protinfo.af_netlink->groups&group)) + if (NLK_SK(sk)->pid == pid || + !(NLK_SK(sk)->groups&group)) continue; sk->err = code; @@ -570,11 +572,11 @@ if (dst_groups && !capable(CAP_NET_ADMIN)) return -EPERM; } else { - dst_pid = sk->protinfo.af_netlink->dst_pid; - dst_groups = sk->protinfo.af_netlink->dst_groups; + dst_pid = NLK_SK(sk)->dst_pid; + dst_groups = NLK_SK(sk)->dst_groups; } - if (!sk->protinfo.af_netlink->pid) { + if (!NLK_SK(sk)->pid) { err = netlink_autobind(sock); if (err) goto out; @@ -588,8 +590,8 @@ if (skb==NULL) goto out; - NETLINK_CB(skb).pid = sk->protinfo.af_netlink->pid; - NETLINK_CB(skb).groups = sk->protinfo.af_netlink->groups; + NETLINK_CB(skb).pid = NLK_SK(sk)->pid; + NETLINK_CB(skb).groups = NLK_SK(sk)->groups; NETLINK_CB(skb).dst_pid = dst_pid; NETLINK_CB(skb).dst_groups = dst_groups; memcpy(NETLINK_CREDS(skb), &scm->creds, sizeof(struct ucred)); @@ -657,30 +659,30 @@ scm->creds = *NETLINK_CREDS(skb); skb_free_datagram(sk, skb); - if (sk->protinfo.af_netlink->cb + if (NLK_SK(sk)->cb && atomic_read(&sk->rmem_alloc) <= sk->rcvbuf/2) netlink_dump(sk); out: if (skb_queue_len(&sk->receive_queue) <= sk->rcvbuf/2) { if (skb_queue_len(&sk->receive_queue) == 0) - clear_bit(0, &sk->protinfo.af_netlink->state); - if (!test_bit(0, &sk->protinfo.af_netlink->state)) - wake_up_interruptible(&sk->protinfo.af_netlink->wait); + clear_bit(0, &NLK_SK(sk)->state); + if (!test_bit(0, &NLK_SK(sk)->state)) + wake_up_interruptible(&NLK_SK(sk)->wait); } return err ? : copied; } void netlink_data_ready(struct sock *sk, int len) { - if (sk->protinfo.af_netlink->data_ready) - sk->protinfo.af_netlink->data_ready(sk, len); + if (NLK_SK(sk)->data_ready) + NLK_SK(sk)->data_ready(sk, len); if (skb_queue_len(&sk->receive_queue) <= sk->rcvbuf/2) { if (skb_queue_len(&sk->receive_queue) == 0) - clear_bit(0, &sk->protinfo.af_netlink->state); - if (!test_bit(0, &sk->protinfo.af_netlink->state)) - wake_up_interruptible(&sk->protinfo.af_netlink->wait); + clear_bit(0, &NLK_SK(sk)->state); + if (!test_bit(0, &NLK_SK(sk)->state)) + wake_up_interruptible(&NLK_SK(sk)->wait); } } @@ -711,7 +713,7 @@ sk = sock->sk; sk->data_ready = netlink_data_ready; if (input) - sk->protinfo.af_netlink->data_ready = input; + NLK_SK(sk)->data_ready = input; netlink_insert(sk, 0); return sk; @@ -740,11 +742,11 @@ if (!skb) return -ENOBUFS; - spin_lock(&sk->protinfo.af_netlink->cb_lock); + spin_lock(&NLK_SK(sk)->cb_lock); - cb = sk->protinfo.af_netlink->cb; + cb = NLK_SK(sk)->cb; if (cb == NULL) { - spin_unlock(&sk->protinfo.af_netlink->cb_lock); + spin_unlock(&NLK_SK(sk)->cb_lock); kfree_skb(skb); return -EINVAL; } @@ -752,7 +754,7 @@ len = cb->dump(skb, cb); if (len > 0) { - spin_unlock(&sk->protinfo.af_netlink->cb_lock); + spin_unlock(&NLK_SK(sk)->cb_lock); skb_queue_tail(&sk->receive_queue, skb); sk->data_ready(sk, len); return 0; @@ -765,8 +767,8 @@ sk->data_ready(sk, skb->len); cb->done(cb); - sk->protinfo.af_netlink->cb = NULL; - spin_unlock(&sk->protinfo.af_netlink->cb_lock); + NLK_SK(sk)->cb = NULL; + spin_unlock(&NLK_SK(sk)->cb_lock); netlink_destroy_callback(cb); sock_put(sk); @@ -798,15 +800,15 @@ return -ECONNREFUSED; } /* A dump is in progress... */ - spin_lock(&sk->protinfo.af_netlink->cb_lock); - if (sk->protinfo.af_netlink->cb) { - spin_unlock(&sk->protinfo.af_netlink->cb_lock); + spin_lock(&NLK_SK(sk)->cb_lock); + if (NLK_SK(sk)->cb) { + spin_unlock(&NLK_SK(sk)->cb_lock); netlink_destroy_callback(cb); sock_put(sk); return -EBUSY; } - sk->protinfo.af_netlink->cb = cb; - spin_unlock(&sk->protinfo.af_netlink->cb_lock); + NLK_SK(sk)->cb = cb; + spin_unlock(&NLK_SK(sk)->cb_lock); netlink_dump(sk); return 0; @@ -850,7 +852,7 @@ struct sock *sk = netlink_kernel_create(unit, NULL); if (sk == NULL) return -ENOBUFS; - sk->protinfo.af_netlink->handler = function; + NLK_SK(sk)->handler = function; write_lock_bh(&nl_emu_lock); netlink_kernel[unit] = sk->socket; write_unlock_bh(&nl_emu_lock); @@ -912,11 +914,11 @@ len+=sprintf(buffer+len,"%p %-3d %-6d %08x %-8d %-8d %p %d", s, s->protocol, - s->protinfo.af_netlink->pid, - s->protinfo.af_netlink->groups, + NLK_SK(s)->pid, + NLK_SK(s)->groups, atomic_read(&s->rmem_alloc), atomic_read(&s->wmem_alloc), - s->protinfo.af_netlink->cb, + NLK_SK(s)->cb, atomic_read(&s->refcnt) ); @@ -969,8 +971,8 @@ }; struct net_proto_family netlink_family_ops = { - PF_NETLINK, - netlink_create + family: PF_NETLINK, + create: netlink_create, }; static int __init netlink_proto_init(void) Index: kernel-acme/net/netrom/af_netrom.c diff -u kernel-acme/net/netrom/af_netrom.c:1.1.1.3 kernel-acme/net/netrom/af_netrom.c:1.1.1.3.8.2 --- kernel-acme/net/netrom/af_netrom.c:1.1.1.3 Wed Sep 26 22:00:32 2001 +++ kernel-acme/net/netrom/af_netrom.c Fri Dec 21 02:12:17 2001 @@ -97,7 +97,7 @@ struct sock *sk; nr_cb *nr; - if ((sk = sk_alloc(PF_NETROM, GFP_ATOMIC, 1)) == NULL) + if ((sk = sk_alloc(PF_NETROM, GFP_ATOMIC, 1, NULL)) == NULL) return NULL; if ((nr = kmalloc(sizeof(*nr), GFP_ATOMIC)) == NULL) { @@ -109,7 +109,7 @@ memset(nr, 0x00, sizeof(*nr)); - sk->protinfo.nr = nr; + NR_SK(sk) = nr; nr->sk = sk; return sk; @@ -152,7 +152,7 @@ struct sock *s; for (s = nr_list; s != NULL; s = s->next) { - if (s->protinfo.nr->device == dev) + if (NR_SK(s)->device == dev) nr_disconnect(s, ENETUNREACH); } } @@ -201,7 +201,8 @@ cli(); for (s = nr_list; s != NULL; s = s->next) { - if (ax25cmp(&s->protinfo.nr->source_addr, addr) == 0 && s->state == TCP_LISTEN) { + if (!ax25cmp(&NR_SK(s)->source_addr, addr) && + s->state == TCP_LISTEN) { restore_flags(flags); return s; } @@ -223,7 +224,9 @@ cli(); for (s = nr_list; s != NULL; s = s->next) { - if (s->protinfo.nr->my_index == index && s->protinfo.nr->my_id == id) { + nr_cb *nr = NR_SK(s); + + if (nr->my_index == index && nr->my_id == id) { restore_flags(flags); return s; } @@ -246,7 +249,10 @@ cli(); for (s = nr_list; s != NULL; s = s->next) { - if (s->protinfo.nr->your_index == index && s->protinfo.nr->your_id == id && ax25cmp(&s->protinfo.nr->dest_addr, dest) == 0) { + nr_cb *nr = NR_SK(s); + + if (nr->your_index == index && nr->your_id == id && + !ax25cmp(&nr->dest_addr, dest)) { restore_flags(flags); return s; } @@ -318,7 +324,7 @@ if (skb->sk != sk) { /* A pending connection */ skb->sk->dead = 1; /* Queue the unaccepted socket for death */ nr_start_heartbeat(skb->sk); - skb->sk->protinfo.nr->state = NR_STATE_0; + NR_SK(skb->sk)->state = NR_STATE_0; } kfree_skb(skb); @@ -347,6 +353,7 @@ char *optval, int optlen) { struct sock *sk = sock->sk; + nr_cb *nr = NR_SK(sk); int opt; if (level != SOL_NETROM) @@ -362,31 +369,31 @@ case NETROM_T1: if (opt < 1) return -EINVAL; - sk->protinfo.nr->t1 = opt * HZ; + nr->t1 = opt * HZ; return 0; case NETROM_T2: if (opt < 1) return -EINVAL; - sk->protinfo.nr->t2 = opt * HZ; + nr->t2 = opt * HZ; return 0; case NETROM_N2: if (opt < 1 || opt > 31) return -EINVAL; - sk->protinfo.nr->n2 = opt; + nr->n2 = opt; return 0; case NETROM_T4: if (opt < 1) return -EINVAL; - sk->protinfo.nr->t4 = opt * HZ; + nr->t4 = opt * HZ; return 0; case NETROM_IDLE: if (opt < 0) return -EINVAL; - sk->protinfo.nr->idle = opt * 60 * HZ; + nr->idle = opt * 60 * HZ; return 0; default: @@ -398,6 +405,7 @@ char *optval, int *optlen) { struct sock *sk = sock->sk; + nr_cb *nr = NR_SK(sk); int val = 0; int len; @@ -412,23 +420,23 @@ switch (optname) { case NETROM_T1: - val = sk->protinfo.nr->t1 / HZ; + val = nr->t1 / HZ; break; case NETROM_T2: - val = sk->protinfo.nr->t2 / HZ; + val = nr->t2 / HZ; break; case NETROM_N2: - val = sk->protinfo.nr->n2; + val = nr->n2; break; case NETROM_T4: - val = sk->protinfo.nr->t4 / HZ; + val = nr->t4 / HZ; break; case NETROM_IDLE: - val = sk->protinfo.nr->idle / (60 * HZ); + val = nr->idle / (60 * HZ); break; default: @@ -448,7 +456,7 @@ struct sock *sk = sock->sk; if (sk->state != TCP_LISTEN) { - memset(&sk->protinfo.nr->user_addr, '\0', AX25_ADDR_LEN); + memset(&NR_SK(sk)->user_addr, '\0', AX25_ADDR_LEN); sk->max_ack_backlog = backlog; sk->state = TCP_LISTEN; return 0; @@ -468,7 +476,7 @@ if ((sk = nr_alloc_sock()) == NULL) return -ENOMEM; - nr = sk->protinfo.nr; + nr = NR_SK(sk); sock_init_data(sock, sk); @@ -500,7 +508,7 @@ static struct sock *nr_make_new(struct sock *osk) { struct sock *sk; - nr_cb *nr; + nr_cb *nr, *onr; if (osk->type != SOCK_SEQPACKET) return NULL; @@ -508,7 +516,7 @@ if ((sk = nr_alloc_sock()) == NULL) return NULL; - nr = sk->protinfo.nr; + nr = NR_SK(sk); sock_init_data(NULL, sk); @@ -531,16 +539,18 @@ init_timer(&nr->t2timer); init_timer(&nr->t4timer); init_timer(&nr->idletimer); + + onr = NR_SK(osk); - nr->t1 = osk->protinfo.nr->t1; - nr->t2 = osk->protinfo.nr->t2; - nr->n2 = osk->protinfo.nr->n2; - nr->t4 = osk->protinfo.nr->t4; - nr->idle = osk->protinfo.nr->idle; - nr->window = osk->protinfo.nr->window; + nr->t1 = onr->t1; + nr->t2 = onr->t2; + nr->n2 = onr->n2; + nr->t4 = onr->t4; + nr->idle = onr->idle; + nr->window = onr->window; - nr->device = osk->protinfo.nr->device; - nr->bpqext = osk->protinfo.nr->bpqext; + nr->device = onr->device; + nr->bpqext = onr->bpqext; return sk; } @@ -548,10 +558,13 @@ static int nr_release(struct socket *sock) { struct sock *sk = sock->sk; + nr_cb *nr; if (sk == NULL) return 0; + + nr = NR_SK(sk); - switch (sk->protinfo.nr->state) { + switch (nr->state) { case NR_STATE_0: case NR_STATE_1: @@ -562,19 +575,19 @@ case NR_STATE_3: nr_clear_queues(sk); - sk->protinfo.nr->n2count = 0; + nr->n2count = 0; nr_write_internal(sk, NR_DISCREQ); nr_start_t1timer(sk); nr_stop_t2timer(sk); nr_stop_t4timer(sk); nr_stop_idletimer(sk); - sk->protinfo.nr->state = NR_STATE_2; - sk->state = TCP_CLOSE; - sk->shutdown |= SEND_SHUTDOWN; + nr->state = NR_STATE_2; + sk->state = TCP_CLOSE; + sk->shutdown |= SEND_SHUTDOWN; sk->state_change(sk); - sk->dead = 1; - sk->destroy = 1; - sk->socket = NULL; + sk->dead = 1; + sk->destroy = 1; + sk->socket = NULL; break; default: @@ -590,6 +603,7 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; + nr_cb *nr = NR_SK(sk); struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr; struct net_device *dev; ax25_address *user, *source; @@ -618,8 +632,8 @@ if (addr->fsa_ax25.sax25_ndigis == 1) { if (!capable(CAP_NET_BIND_SERVICE)) return -EACCES; - sk->protinfo.nr->user_addr = addr->fsa_digipeater[0]; - sk->protinfo.nr->source_addr = addr->fsa_ax25.sax25_call; + nr->user_addr = addr->fsa_digipeater[0]; + nr->source_addr = addr->fsa_ax25.sax25_call; } else { source = &addr->fsa_ax25.sax25_call; @@ -629,11 +643,11 @@ user = source; } - sk->protinfo.nr->user_addr = *user; - sk->protinfo.nr->source_addr = *source; + nr->user_addr = *user; + nr->source_addr = *source; } - sk->protinfo.nr->device = dev; + nr->device = dev; nr_insert_socket(sk); sk->zapped = 0; @@ -645,6 +659,7 @@ int addr_len, int flags) { struct sock *sk = sock->sk; + nr_cb *nr = NR_SK(sk); struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr; ax25_address *user, *source = NULL; struct net_device *dev; @@ -685,19 +700,19 @@ user = source; } - sk->protinfo.nr->user_addr = *user; - sk->protinfo.nr->source_addr = *source; - sk->protinfo.nr->device = dev; + nr->user_addr = *user; + nr->source_addr = *source; + nr->device = dev; nr_insert_socket(sk); /* Finish the bind */ } - sk->protinfo.nr->dest_addr = addr->sax25_call; + nr->dest_addr = addr->sax25_call; circuit = nr_find_next_circuit(); - sk->protinfo.nr->my_index = circuit / 256; - sk->protinfo.nr->my_id = circuit % 256; + nr->my_index = circuit / 256; + nr->my_id = circuit % 256; circuit++; @@ -707,7 +722,7 @@ nr_establish_data_link(sk); - sk->protinfo.nr->state = NR_STATE_1; + nr->state = NR_STATE_1; nr_start_heartbeat(sk); @@ -794,19 +809,20 @@ { struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr; struct sock *sk = sock->sk; + nr_cb *nr = NR_SK(sk); if (peer != 0) { if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; sax->fsa_ax25.sax25_family = AF_NETROM; sax->fsa_ax25.sax25_ndigis = 1; - sax->fsa_ax25.sax25_call = sk->protinfo.nr->user_addr; - sax->fsa_digipeater[0] = sk->protinfo.nr->dest_addr; + sax->fsa_ax25.sax25_call = nr->user_addr; + sax->fsa_digipeater[0] = nr->dest_addr; *uaddr_len = sizeof(struct full_sockaddr_ax25); } else { sax->fsa_ax25.sax25_family = AF_NETROM; sax->fsa_ax25.sax25_ndigis = 0; - sax->fsa_ax25.sax25_call = sk->protinfo.nr->source_addr; + sax->fsa_ax25.sax25_call = nr->source_addr; *uaddr_len = sizeof(struct sockaddr_ax25); } @@ -817,6 +833,7 @@ { struct sock *sk; struct sock *make; + nr_cb *nr_make; ax25_address *src, *dest, *user; unsigned short circuit_index, circuit_id; unsigned short peer_circuit_index, peer_circuit_id; @@ -874,9 +891,9 @@ skb->h.raw = skb->data; if (frametype == NR_CONNACK && skb->len == 22) - sk->protinfo.nr->bpqext = 1; + NR_SK(sk)->bpqext = 1; else - sk->protinfo.nr->bpqext = 0; + NR_SK(sk)->bpqext = 0; return nr_process_rx_frame(sk, skb); } @@ -916,42 +933,43 @@ make->state = TCP_ESTABLISHED; /* Fill in his circuit details */ - make->protinfo.nr->source_addr = *dest; - make->protinfo.nr->dest_addr = *src; - make->protinfo.nr->user_addr = *user; + nr_make = NR_SK(make); + nr_make->source_addr = *dest; + nr_make->dest_addr = *src; + nr_make->user_addr = *user; - make->protinfo.nr->your_index = circuit_index; - make->protinfo.nr->your_id = circuit_id; + nr_make->your_index = circuit_index; + nr_make->your_id = circuit_id; circuit = nr_find_next_circuit(); - make->protinfo.nr->my_index = circuit / 256; - make->protinfo.nr->my_id = circuit % 256; + nr_make->my_index = circuit / 256; + nr_make->my_id = circuit % 256; circuit++; /* Window negotiation */ - if (window < make->protinfo.nr->window) - make->protinfo.nr->window = window; + if (window < nr_make->window) + nr_make->window = window; /* L4 timeout negotiation */ if (skb->len == 37) { timeout = skb->data[36] * 256 + skb->data[35]; - if (timeout * HZ < make->protinfo.nr->t1) - make->protinfo.nr->t1 = timeout * HZ; - make->protinfo.nr->bpqext = 1; + if (timeout * HZ < nr_make->t1) + nr_make->t1 = timeout * HZ; + nr_make->bpqext = 1; } else { - make->protinfo.nr->bpqext = 0; + nr_make->bpqext = 0; } nr_write_internal(make, NR_CONNACK); - make->protinfo.nr->condition = 0x00; - make->protinfo.nr->vs = 0; - make->protinfo.nr->va = 0; - make->protinfo.nr->vr = 0; - make->protinfo.nr->vl = 0; - make->protinfo.nr->state = NR_STATE_3; + nr_make->condition = 0x00; + nr_make->vs = 0; + nr_make->va = 0; + nr_make->vr = 0; + nr_make->vl = 0; + nr_make->state = NR_STATE_3; sk->ack_backlog++; make->pair = sk; @@ -971,6 +989,7 @@ static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) { struct sock *sk = sock->sk; + nr_cb *nr = NR_SK(sk); struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name; int err; struct sockaddr_ax25 sax; @@ -989,14 +1008,14 @@ return -EPIPE; } - if (sk->protinfo.nr->device == NULL) + if (nr->device == NULL) return -ENETUNREACH; if (usax) { if (msg->msg_namelen < sizeof(sax)) return -EINVAL; sax = *usax; - if (ax25cmp(&sk->protinfo.nr->dest_addr, &sax.sax25_call) != 0) + if (ax25cmp(&nr->dest_addr, &sax.sax25_call) != 0) return -EISCONN; if (sax.sax25_family != AF_NETROM) return -EINVAL; @@ -1004,7 +1023,7 @@ if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; sax.sax25_family = AF_NETROM; - sax.sax25_call = sk->protinfo.nr->dest_addr; + sax.sax25_call = nr->dest_addr; } SOCK_DEBUG(sk, "NET/ROM: sendto: Addresses built.\n"); @@ -1027,8 +1046,8 @@ /* Build a NET/ROM Transport header */ - *asmptr++ = sk->protinfo.nr->your_index; - *asmptr++ = sk->protinfo.nr->your_id; + *asmptr++ = nr->your_index; + *asmptr++ = nr->your_id; *asmptr++ = 0; /* To be filled in later */ *asmptr++ = 0; /* Ditto */ *asmptr++ = NR_INFO; @@ -1171,37 +1190,39 @@ len += sprintf(buffer, "user_addr dest_node src_node dev my your st vs vr va t1 t2 t4 idle n2 wnd Snd-Q Rcv-Q inode\n"); for (s = nr_list; s != NULL; s = s->next) { - if ((dev = s->protinfo.nr->device) == NULL) + nr_cb *nr = NR_SK(s); + + if ((dev = nr->device) == NULL) devname = "???"; else devname = dev->name; len += sprintf(buffer + len, "%-9s ", - ax2asc(&s->protinfo.nr->user_addr)); + ax2asc(&nr->user_addr)); len += sprintf(buffer + len, "%-9s ", - ax2asc(&s->protinfo.nr->dest_addr)); + ax2asc(&nr->dest_addr)); len += sprintf(buffer + len, "%-9s %-3s %02X/%02X %02X/%02X %2d %3d %3d %3d %3lu/%03lu %2lu/%02lu %3lu/%03lu %3lu/%03lu %2d/%02d %3d %5d %5d %ld\n", - ax2asc(&s->protinfo.nr->source_addr), + ax2asc(&nr->source_addr), devname, - s->protinfo.nr->my_index, - s->protinfo.nr->my_id, - s->protinfo.nr->your_index, - s->protinfo.nr->your_id, - s->protinfo.nr->state, - s->protinfo.nr->vs, - s->protinfo.nr->vr, - s->protinfo.nr->va, - ax25_display_timer(&s->protinfo.nr->t1timer) / HZ, - s->protinfo.nr->t1 / HZ, - ax25_display_timer(&s->protinfo.nr->t2timer) / HZ, - s->protinfo.nr->t2 / HZ, - ax25_display_timer(&s->protinfo.nr->t4timer) / HZ, - s->protinfo.nr->t4 / HZ, - ax25_display_timer(&s->protinfo.nr->idletimer) / (60 * HZ), - s->protinfo.nr->idle / (60 * HZ), - s->protinfo.nr->n2count, - s->protinfo.nr->n2, - s->protinfo.nr->window, + nr->my_index, + nr->my_id, + nr->your_index, + nr->your_id, + nr->state, + nr->vs, + nr->vr, + nr->va, + ax25_display_timer(&nr->t1timer) / HZ, + nr->t1 / HZ, + ax25_display_timer(&nr->t2timer) / HZ, + nr->t2 / HZ, + ax25_display_timer(&nr->t4timer) / HZ, + nr->t4 / HZ, + ax25_display_timer(&nr->idletimer) / (60 * HZ), + nr->idle / (60 * HZ), + nr->n2count, + nr->n2, + nr->window, atomic_read(&s->wmem_alloc), atomic_read(&s->rmem_alloc), s->socket != NULL ? s->socket->inode->i_ino : 0L); Index: kernel-acme/net/netrom/nr_in.c diff -u kernel-acme/net/netrom/nr_in.c:1.1.1.1 kernel-acme/net/netrom/nr_in.c:1.1.1.1.12.1 --- kernel-acme/net/netrom/nr_in.c:1.1.1.1 Tue Jun 26 17:29:41 2001 +++ kernel-acme/net/netrom/nr_in.c Tue Dec 11 00:26:47 2001 @@ -50,32 +50,33 @@ static int nr_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) { struct sk_buff *skbo, *skbn = skb; + nr_cb *nr = NR_SK(sk); skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN); nr_start_idletimer(sk); if (more) { - sk->protinfo.nr->fraglen += skb->len; - skb_queue_tail(&sk->protinfo.nr->frag_queue, skb); + nr->fraglen += skb->len; + skb_queue_tail(&nr->frag_queue, skb); return 0; } - if (!more && sk->protinfo.nr->fraglen > 0) { /* End of fragment */ - sk->protinfo.nr->fraglen += skb->len; - skb_queue_tail(&sk->protinfo.nr->frag_queue, skb); + if (!more && nr->fraglen > 0) { /* End of fragment */ + nr->fraglen += skb->len; + skb_queue_tail(&nr->frag_queue, skb); - if ((skbn = alloc_skb(sk->protinfo.nr->fraglen, GFP_ATOMIC)) == NULL) + if ((skbn = alloc_skb(nr->fraglen, GFP_ATOMIC)) == NULL) return 1; skbn->h.raw = skbn->data; - while ((skbo = skb_dequeue(&sk->protinfo.nr->frag_queue)) != NULL) { + while ((skbo = skb_dequeue(&nr->frag_queue)) != NULL) { memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len); kfree_skb(skbo); } - sk->protinfo.nr->fraglen = 0; + nr->fraglen = 0; } return sock_queue_rcv_skb(sk, skbn); @@ -90,22 +91,25 @@ { switch (frametype) { - case NR_CONNACK: + case NR_CONNACK: { + nr_cb *nr = NR_SK(sk); + nr_stop_t1timer(sk); nr_start_idletimer(sk); - sk->protinfo.nr->your_index = skb->data[17]; - sk->protinfo.nr->your_id = skb->data[18]; - sk->protinfo.nr->vs = 0; - sk->protinfo.nr->va = 0; - sk->protinfo.nr->vr = 0; - sk->protinfo.nr->vl = 0; - sk->protinfo.nr->state = NR_STATE_3; - sk->protinfo.nr->n2count = 0; - sk->protinfo.nr->window = skb->data[20]; - sk->state = TCP_ESTABLISHED; + nr->your_index = skb->data[17]; + nr->your_id = skb->data[18]; + nr->vs = 0; + nr->va = 0; + nr->vr = 0; + nr->vl = 0; + nr->state = NR_STATE_3; + nr->n2count = 0; + nr->window = skb->data[20]; + sk->state = TCP_ESTABLISHED; if (!sk->dead) sk->state_change(sk); break; + } case NR_CONNACK | NR_CHOKE_FLAG: nr_disconnect(sk, ECONNREFUSED); @@ -152,6 +156,7 @@ */ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype) { + nr_cb *nrom = NR_SK(sk); struct sk_buff_head temp_queue; struct sk_buff *skbn; unsigned short save_vr; @@ -182,10 +187,10 @@ case NR_INFOACK | NR_NAK_FLAG: case NR_INFOACK | NR_NAK_FLAG | NR_CHOKE_FLAG: if (frametype & NR_CHOKE_FLAG) { - sk->protinfo.nr->condition |= NR_COND_PEER_RX_BUSY; + nrom->condition |= NR_COND_PEER_RX_BUSY; nr_start_t4timer(sk); } else { - sk->protinfo.nr->condition &= ~NR_COND_PEER_RX_BUSY; + nrom->condition &= ~NR_COND_PEER_RX_BUSY; nr_stop_t4timer(sk); } if (!nr_validate_nr(sk, nr)) { @@ -195,7 +200,7 @@ nr_frames_acked(sk, nr); nr_send_nak_frame(sk); } else { - if (sk->protinfo.nr->condition & NR_COND_PEER_RX_BUSY) { + if (nrom->condition & NR_COND_PEER_RX_BUSY) { nr_frames_acked(sk, nr); } else { nr_check_iframes_acked(sk, nr); @@ -212,10 +217,10 @@ case NR_INFO | NR_NAK_FLAG | NR_MORE_FLAG: case NR_INFO | NR_NAK_FLAG | NR_CHOKE_FLAG | NR_MORE_FLAG: if (frametype & NR_CHOKE_FLAG) { - sk->protinfo.nr->condition |= NR_COND_PEER_RX_BUSY; + nrom->condition |= NR_COND_PEER_RX_BUSY; nr_start_t4timer(sk); } else { - sk->protinfo.nr->condition &= ~NR_COND_PEER_RX_BUSY; + nrom->condition &= ~NR_COND_PEER_RX_BUSY; nr_stop_t4timer(sk); } if (nr_validate_nr(sk, nr)) { @@ -223,7 +228,7 @@ nr_frames_acked(sk, nr); nr_send_nak_frame(sk); } else { - if (sk->protinfo.nr->condition & NR_COND_PEER_RX_BUSY) { + if (nrom->condition & NR_COND_PEER_RX_BUSY) { nr_frames_acked(sk, nr); } else { nr_check_iframes_acked(sk, nr); @@ -231,19 +236,19 @@ } } queued = 1; - skb_queue_head(&sk->protinfo.nr->reseq_queue, skb); - if (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY) + skb_queue_head(&nrom->reseq_queue, skb); + if (nrom->condition & NR_COND_OWN_RX_BUSY) break; skb_queue_head_init(&temp_queue); do { - save_vr = sk->protinfo.nr->vr; - while ((skbn = skb_dequeue(&sk->protinfo.nr->reseq_queue)) != NULL) { + save_vr = nrom->vr; + while ((skbn = skb_dequeue(&nrom->reseq_queue)) != NULL) { ns = skbn->data[17]; - if (ns == sk->protinfo.nr->vr) { + if (ns == nrom->vr) { if (nr_queue_rx_frame(sk, skbn, frametype & NR_MORE_FLAG) == 0) { - sk->protinfo.nr->vr = (sk->protinfo.nr->vr + 1) % NR_MODULUS; + nrom->vr = (nrom->vr + 1) % NR_MODULUS; } else { - sk->protinfo.nr->condition |= NR_COND_OWN_RX_BUSY; + nrom->condition |= NR_COND_OWN_RX_BUSY; skb_queue_tail(&temp_queue, skbn); } } else if (nr_in_rx_window(sk, ns)) { @@ -253,17 +258,17 @@ } } while ((skbn = skb_dequeue(&temp_queue)) != NULL) { - skb_queue_tail(&sk->protinfo.nr->reseq_queue, skbn); + skb_queue_tail(&nrom->reseq_queue, skbn); } - } while (save_vr != sk->protinfo.nr->vr); + } while (save_vr != nrom->vr); /* * Window is full, ack it immediately. */ - if (((sk->protinfo.nr->vl + sk->protinfo.nr->window) % NR_MODULUS) == sk->protinfo.nr->vr) { + if (((nrom->vl + nrom->window) % NR_MODULUS) == nrom->vr) { nr_enquiry_response(sk); } else { - if (!(sk->protinfo.nr->condition & NR_COND_ACK_PENDING)) { - sk->protinfo.nr->condition |= NR_COND_ACK_PENDING; + if (!(nrom->condition & NR_COND_ACK_PENDING)) { + nrom->condition |= NR_COND_ACK_PENDING; nr_start_t2timer(sk); } } @@ -279,14 +284,15 @@ /* Higher level upcall for a LAPB frame */ int nr_process_rx_frame(struct sock *sk, struct sk_buff *skb) { + nr_cb *nr = NR_SK(sk); int queued = 0, frametype; - if (sk->protinfo.nr->state == NR_STATE_0) + if (nr->state == NR_STATE_0) return 0; frametype = skb->data[19]; - switch (sk->protinfo.nr->state) { + switch (nr->state) { case NR_STATE_1: queued = nr_state1_machine(sk, skb, frametype); break; Index: kernel-acme/net/netrom/nr_out.c diff -u kernel-acme/net/netrom/nr_out.c:1.1.1.1 kernel-acme/net/netrom/nr_out.c:1.1.1.1.12.1 --- kernel-acme/net/netrom/nr_out.c:1.1.1.1 Tue Jun 26 17:29:40 2001 +++ kernel-acme/net/netrom/nr_out.c Tue Dec 11 00:26:47 2001 @@ -91,13 +91,15 @@ */ static void nr_send_iframe(struct sock *sk, struct sk_buff *skb) { + nr_cb *nr = NR_SK(sk); + if (skb == NULL) return; - skb->data[2] = sk->protinfo.nr->vs; - skb->data[3] = sk->protinfo.nr->vr; + skb->data[2] = nr->vs; + skb->data[3] = nr->vr; - if (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY) + if (nr->condition & NR_COND_OWN_RX_BUSY) skb->data[4] |= NR_CHOKE_FLAG; nr_start_idletimer(sk); @@ -108,48 +110,50 @@ void nr_send_nak_frame(struct sock *sk) { struct sk_buff *skb, *skbn; + nr_cb *nr = NR_SK(sk); - if ((skb = skb_peek(&sk->protinfo.nr->ack_queue)) == NULL) + if ((skb = skb_peek(&nr->ack_queue)) == NULL) return; if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) return; - skbn->data[2] = sk->protinfo.nr->va; - skbn->data[3] = sk->protinfo.nr->vr; + skbn->data[2] = nr->va; + skbn->data[3] = nr->vr; - if (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY) + if (nr->condition & NR_COND_OWN_RX_BUSY) skbn->data[4] |= NR_CHOKE_FLAG; nr_transmit_buffer(sk, skbn); - sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING; - sk->protinfo.nr->vl = sk->protinfo.nr->vr; + nr->condition &= ~NR_COND_ACK_PENDING; + nr->vl = nr->vr; nr_stop_t1timer(sk); } void nr_kick(struct sock *sk) { + nr_cb *nr = NR_SK(sk); struct sk_buff *skb, *skbn; unsigned short start, end; - if (sk->protinfo.nr->state != NR_STATE_3) + if (nr->state != NR_STATE_3) return; - if (sk->protinfo.nr->condition & NR_COND_PEER_RX_BUSY) + if (nr->condition & NR_COND_PEER_RX_BUSY) return; if (skb_peek(&sk->write_queue) == NULL) return; - start = (skb_peek(&sk->protinfo.nr->ack_queue) == NULL) ? sk->protinfo.nr->va : sk->protinfo.nr->vs; - end = (sk->protinfo.nr->va + sk->protinfo.nr->window) % NR_MODULUS; + start = (skb_peek(&nr->ack_queue) == NULL) ? nr->va : nr->vs; + end = (nr->va + nr->window) % NR_MODULUS; if (start == end) return; - sk->protinfo.nr->vs = start; + nr->vs = start; /* * Transmit data until either we're out of data to send or @@ -174,17 +178,17 @@ */ nr_send_iframe(sk, skbn); - sk->protinfo.nr->vs = (sk->protinfo.nr->vs + 1) % NR_MODULUS; + nr->vs = (nr->vs + 1) % NR_MODULUS; /* * Requeue the original data frame. */ - skb_queue_tail(&sk->protinfo.nr->ack_queue, skb); + skb_queue_tail(&nr->ack_queue, skb); - } while (sk->protinfo.nr->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL); + } while (nr->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL); - sk->protinfo.nr->vl = sk->protinfo.nr->vr; - sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING; + nr->vl = nr->vr; + nr->condition &= ~NR_COND_ACK_PENDING; if (!nr_t1timer_running(sk)) nr_start_t1timer(sk); @@ -192,6 +196,7 @@ void nr_transmit_buffer(struct sock *sk, struct sk_buff *skb) { + nr_cb *nr = nr; unsigned char *dptr; /* @@ -199,13 +204,13 @@ */ dptr = skb_push(skb, NR_NETWORK_LEN); - memcpy(dptr, &sk->protinfo.nr->source_addr, AX25_ADDR_LEN); + memcpy(dptr, &nr->source_addr, AX25_ADDR_LEN); dptr[6] &= ~AX25_CBIT; dptr[6] &= ~AX25_EBIT; dptr[6] |= AX25_SSSID_SPARE; dptr += AX25_ADDR_LEN; - memcpy(dptr, &sk->protinfo.nr->dest_addr, AX25_ADDR_LEN); + memcpy(dptr, &nr->dest_addr, AX25_ADDR_LEN); dptr[6] &= ~AX25_CBIT; dptr[6] |= AX25_EBIT; dptr[6] |= AX25_SSSID_SPARE; @@ -226,8 +231,10 @@ void nr_establish_data_link(struct sock *sk) { - sk->protinfo.nr->condition = 0x00; - sk->protinfo.nr->n2count = 0; + nr_cb *nr = NR_SK(sk); + + nr->condition = 0x00; + nr->n2count = 0; nr_write_internal(sk, NR_CONNREQ); @@ -242,29 +249,32 @@ */ void nr_enquiry_response(struct sock *sk) { + nr_cb *nr = NR_SK(sk); int frametype = NR_INFOACK; - if (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY) { + if (nr->condition & NR_COND_OWN_RX_BUSY) { frametype |= NR_CHOKE_FLAG; } else { - if (skb_peek(&sk->protinfo.nr->reseq_queue) != NULL) + if (skb_peek(&nr->reseq_queue) != NULL) frametype |= NR_NAK_FLAG; } nr_write_internal(sk, frametype); - sk->protinfo.nr->vl = sk->protinfo.nr->vr; - sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING; + nr->vl = nr->vr; + nr->condition &= ~NR_COND_ACK_PENDING; } void nr_check_iframes_acked(struct sock *sk, unsigned short nr) { - if (sk->protinfo.nr->vs == nr) { + nr_cb *nrom = NR_SK(sk); + + if (nrom->vs == nr) { nr_frames_acked(sk, nr); nr_stop_t1timer(sk); - sk->protinfo.nr->n2count = 0; + nrom->n2count = 0; } else { - if (sk->protinfo.nr->va != nr) { + if (nrom->va != nr) { nr_frames_acked(sk, nr); nr_start_t1timer(sk); } Index: kernel-acme/net/netrom/nr_subr.c diff -u kernel-acme/net/netrom/nr_subr.c:1.1.1.2 kernel-acme/net/netrom/nr_subr.c:1.1.1.2.10.2 --- kernel-acme/net/netrom/nr_subr.c:1.1.1.2 Thu Aug 16 18:44:24 2001 +++ kernel-acme/net/netrom/nr_subr.c Mon Dec 17 15:04:52 2001 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -42,10 +43,12 @@ */ void nr_clear_queues(struct sock *sk) { + nr_cb *nr = NR_SK(sk); + skb_queue_purge(&sk->write_queue); - skb_queue_purge(&sk->protinfo.nr->ack_queue); - skb_queue_purge(&sk->protinfo.nr->reseq_queue); - skb_queue_purge(&sk->protinfo.nr->frag_queue); + skb_queue_purge(&nr->ack_queue); + skb_queue_purge(&nr->reseq_queue); + skb_queue_purge(&nr->frag_queue); } /* @@ -55,16 +58,17 @@ */ void nr_frames_acked(struct sock *sk, unsigned short nr) { + nr_cb *nrom = NR_SK(sk); struct sk_buff *skb; /* * Remove all the ack-ed frames from the ack queue. */ - if (sk->protinfo.nr->va != nr) { - while (skb_peek(&sk->protinfo.nr->ack_queue) != NULL && sk->protinfo.nr->va != nr) { - skb = skb_dequeue(&sk->protinfo.nr->ack_queue); + if (nrom->va != nr) { + while (skb_peek(&nrom->ack_queue) != NULL && nrom->va != nr) { + skb = skb_dequeue(&nrom->ack_queue); kfree_skb(skb); - sk->protinfo.nr->va = (sk->protinfo.nr->va + 1) % NR_MODULUS; + nrom->va = (nrom->va + 1) % NR_MODULUS; } } } @@ -78,7 +82,7 @@ { struct sk_buff *skb, *skb_prev = NULL; - while ((skb = skb_dequeue(&sk->protinfo.nr->ack_queue)) != NULL) { + while ((skb = skb_dequeue(&NR_SK(sk)->ack_queue)) != NULL) { if (skb_prev == NULL) skb_queue_head(&sk->write_queue, skb); else @@ -93,16 +97,15 @@ */ int nr_validate_nr(struct sock *sk, unsigned short nr) { - unsigned short vc = sk->protinfo.nr->va; + nr_cb *nrom = NR_SK(sk); + unsigned short vc = nrom->va; - while (vc != sk->protinfo.nr->vs) { + while (vc != nrom->vs) { if (nr == vc) return 1; vc = (vc + 1) % NR_MODULUS; } - - if (nr == sk->protinfo.nr->vs) return 1; - return 0; + return nr == nrom->vs; } /* @@ -110,8 +113,9 @@ */ int nr_in_rx_window(struct sock *sk, unsigned short ns) { - unsigned short vc = sk->protinfo.nr->vr; - unsigned short vt = (sk->protinfo.nr->vl + sk->protinfo.nr->window) % NR_MODULUS; + nr_cb *nr = NR_SK(sk); + unsigned short vc = nr->vr; + unsigned short vt = (nr->vl + nr->window) % NR_MODULUS; while (vc != vt) { if (ns == vc) return 1; @@ -127,6 +131,7 @@ */ void nr_write_internal(struct sock *sk, int frametype) { + nr_cb *nr = NR_SK(sk); struct sk_buff *skb; unsigned char *dptr; int len, timeout; @@ -138,7 +143,7 @@ len += 17; break; case NR_CONNACK: - len += (sk->protinfo.nr->bpqext) ? 2 : 1; + len += (nr->bpqext) ? 2 : 1; break; case NR_DISCREQ: case NR_DISCACK: @@ -162,19 +167,19 @@ switch (frametype & 0x0F) { case NR_CONNREQ: - timeout = sk->protinfo.nr->t1 / HZ; - *dptr++ = sk->protinfo.nr->my_index; - *dptr++ = sk->protinfo.nr->my_id; + timeout = nr->t1 / HZ; + *dptr++ = nr->my_index; + *dptr++ = nr->my_id; *dptr++ = 0; *dptr++ = 0; *dptr++ = frametype; - *dptr++ = sk->protinfo.nr->window; - memcpy(dptr, &sk->protinfo.nr->user_addr, AX25_ADDR_LEN); + *dptr++ = nr->window; + memcpy(dptr, &nr->user_addr, AX25_ADDR_LEN); dptr[6] &= ~AX25_CBIT; dptr[6] &= ~AX25_EBIT; dptr[6] |= AX25_SSSID_SPARE; dptr += AX25_ADDR_LEN; - memcpy(dptr, &sk->protinfo.nr->source_addr, AX25_ADDR_LEN); + memcpy(dptr, &nr->source_addr, AX25_ADDR_LEN); dptr[6] &= ~AX25_CBIT; dptr[6] &= ~AX25_EBIT; dptr[6] |= AX25_SSSID_SPARE; @@ -184,29 +189,29 @@ break; case NR_CONNACK: - *dptr++ = sk->protinfo.nr->your_index; - *dptr++ = sk->protinfo.nr->your_id; - *dptr++ = sk->protinfo.nr->my_index; - *dptr++ = sk->protinfo.nr->my_id; + *dptr++ = nr->your_index; + *dptr++ = nr->your_id; + *dptr++ = nr->my_index; + *dptr++ = nr->my_id; *dptr++ = frametype; - *dptr++ = sk->protinfo.nr->window; - if (sk->protinfo.nr->bpqext) *dptr++ = sysctl_netrom_network_ttl_initialiser; + *dptr++ = nr->window; + if (nr->bpqext) *dptr++ = sysctl_netrom_network_ttl_initialiser; break; case NR_DISCREQ: case NR_DISCACK: - *dptr++ = sk->protinfo.nr->your_index; - *dptr++ = sk->protinfo.nr->your_id; + *dptr++ = nr->your_index; + *dptr++ = nr->your_id; *dptr++ = 0; *dptr++ = 0; *dptr++ = frametype; break; case NR_INFOACK: - *dptr++ = sk->protinfo.nr->your_index; - *dptr++ = sk->protinfo.nr->your_id; + *dptr++ = nr->your_index; + *dptr++ = nr->your_id; *dptr++ = 0; - *dptr++ = sk->protinfo.nr->vr; + *dptr++ = nr->vr; *dptr++ = frametype; break; } @@ -275,7 +280,7 @@ nr_clear_queues(sk); - sk->protinfo.nr->state = NR_STATE_0; + NR_SK(sk)->state = NR_STATE_0; sk->state = TCP_CLOSE; sk->err = reason; Index: kernel-acme/net/netrom/nr_timer.c diff -u kernel-acme/net/netrom/nr_timer.c:1.1.1.1 kernel-acme/net/netrom/nr_timer.c:1.1.1.1.12.2 --- kernel-acme/net/netrom/nr_timer.c:1.1.1.1 Tue Jun 26 17:29:45 2001 +++ kernel-acme/net/netrom/nr_timer.c Mon Dec 17 15:04:52 2001 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -45,47 +46,55 @@ void nr_start_t1timer(struct sock *sk) { - del_timer(&sk->protinfo.nr->t1timer); + nr_cb *nr = NR_SK(sk); - sk->protinfo.nr->t1timer.data = (unsigned long)sk; - sk->protinfo.nr->t1timer.function = &nr_t1timer_expiry; - sk->protinfo.nr->t1timer.expires = jiffies + sk->protinfo.nr->t1; + del_timer(&nr->t1timer); - add_timer(&sk->protinfo.nr->t1timer); + nr->t1timer.data = (unsigned long)sk; + nr->t1timer.function = &nr_t1timer_expiry; + nr->t1timer.expires = jiffies + nr->t1; + + add_timer(&nr->t1timer); } void nr_start_t2timer(struct sock *sk) { - del_timer(&sk->protinfo.nr->t2timer); + nr_cb *nr = NR_SK(sk); + + del_timer(&nr->t2timer); - sk->protinfo.nr->t2timer.data = (unsigned long)sk; - sk->protinfo.nr->t2timer.function = &nr_t2timer_expiry; - sk->protinfo.nr->t2timer.expires = jiffies + sk->protinfo.nr->t2; + nr->t2timer.data = (unsigned long)sk; + nr->t2timer.function = &nr_t2timer_expiry; + nr->t2timer.expires = jiffies + nr->t2; - add_timer(&sk->protinfo.nr->t2timer); + add_timer(&nr->t2timer); } void nr_start_t4timer(struct sock *sk) { - del_timer(&sk->protinfo.nr->t4timer); + nr_cb *nr = NR_SK(sk); + + del_timer(&nr->t4timer); - sk->protinfo.nr->t4timer.data = (unsigned long)sk; - sk->protinfo.nr->t4timer.function = &nr_t4timer_expiry; - sk->protinfo.nr->t4timer.expires = jiffies + sk->protinfo.nr->t4; + nr->t4timer.data = (unsigned long)sk; + nr->t4timer.function = &nr_t4timer_expiry; + nr->t4timer.expires = jiffies + nr->t4; - add_timer(&sk->protinfo.nr->t4timer); + add_timer(&nr->t4timer); } void nr_start_idletimer(struct sock *sk) { - del_timer(&sk->protinfo.nr->idletimer); + nr_cb *nr = NR_SK(sk); - if (sk->protinfo.nr->idle > 0) { - sk->protinfo.nr->idletimer.data = (unsigned long)sk; - sk->protinfo.nr->idletimer.function = &nr_idletimer_expiry; - sk->protinfo.nr->idletimer.expires = jiffies + sk->protinfo.nr->idle; + del_timer(&nr->idletimer); - add_timer(&sk->protinfo.nr->idletimer); + if (nr->idle > 0) { + nr->idletimer.data = (unsigned long)sk; + nr->idletimer.function = &nr_idletimer_expiry; + nr->idletimer.expires = jiffies + nr->idle; + + add_timer(&nr->idletimer); } } @@ -102,22 +111,22 @@ void nr_stop_t1timer(struct sock *sk) { - del_timer(&sk->protinfo.nr->t1timer); + del_timer(&NR_SK(sk)->t1timer); } void nr_stop_t2timer(struct sock *sk) { - del_timer(&sk->protinfo.nr->t2timer); + del_timer(&NR_SK(sk)->t2timer); } void nr_stop_t4timer(struct sock *sk) { - del_timer(&sk->protinfo.nr->t4timer); + del_timer(&NR_SK(sk)->t4timer); } void nr_stop_idletimer(struct sock *sk) { - del_timer(&sk->protinfo.nr->idletimer); + del_timer(&NR_SK(sk)->idletimer); } void nr_stop_heartbeat(struct sock *sk) @@ -127,14 +136,14 @@ int nr_t1timer_running(struct sock *sk) { - return timer_pending(&sk->protinfo.nr->t1timer); + return timer_pending(&NR_SK(sk)->t1timer); } static void nr_heartbeat_expiry(unsigned long param) { struct sock *sk = (struct sock *)param; - switch (sk->protinfo.nr->state) { + switch (NR_SK(sk)->state) { case NR_STATE_0: /* Magic here: If we listen() and a new link dies before it @@ -145,19 +154,21 @@ } break; - case NR_STATE_3: + case NR_STATE_3: { + nr_cb *nr = NR_SK(sk); /* * Check for the state of the receive buffer. */ if (atomic_read(&sk->rmem_alloc) < (sk->rcvbuf / 2) && - (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY)) { - sk->protinfo.nr->condition &= ~NR_COND_OWN_RX_BUSY; - sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING; - sk->protinfo.nr->vl = sk->protinfo.nr->vr; + (nr->condition & NR_COND_OWN_RX_BUSY)) { + nr->condition &= ~NR_COND_OWN_RX_BUSY; + nr->condition &= ~NR_COND_ACK_PENDING; + nr->vl = nr->vr; nr_write_internal(sk, NR_INFOACK); break; } break; + } } nr_start_heartbeat(sk); @@ -166,9 +177,10 @@ static void nr_t2timer_expiry(unsigned long param) { struct sock *sk = (struct sock *)param; + nr_cb *nr = NR_SK(sk); - if (sk->protinfo.nr->condition & NR_COND_ACK_PENDING) { - sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING; + if (nr->condition & NR_COND_ACK_PENDING) { + nr->condition &= ~NR_COND_ACK_PENDING; nr_enquiry_response(sk); } } @@ -177,18 +189,19 @@ { struct sock *sk = (struct sock *)param; - sk->protinfo.nr->condition &= ~NR_COND_PEER_RX_BUSY; + NR_SK(sk)->condition &= ~NR_COND_PEER_RX_BUSY; } static void nr_idletimer_expiry(unsigned long param) { struct sock *sk = (struct sock *)param; + nr_cb *nr = NR_SK(sk); nr_clear_queues(sk); - sk->protinfo.nr->n2count = 0; + nr->n2count = 0; nr_write_internal(sk, NR_DISCREQ); - sk->protinfo.nr->state = NR_STATE_2; + nr->state = NR_STATE_2; nr_start_t1timer(sk); nr_stop_t2timer(sk); @@ -207,35 +220,36 @@ static void nr_t1timer_expiry(unsigned long param) { struct sock *sk = (struct sock *)param; + nr_cb *nr = NR_SK(sk); - switch (sk->protinfo.nr->state) { + switch (nr->state) { case NR_STATE_1: - if (sk->protinfo.nr->n2count == sk->protinfo.nr->n2) { + if (nr->n2count == nr->n2) { nr_disconnect(sk, ETIMEDOUT); return; } else { - sk->protinfo.nr->n2count++; + nr->n2count++; nr_write_internal(sk, NR_CONNREQ); } break; case NR_STATE_2: - if (sk->protinfo.nr->n2count == sk->protinfo.nr->n2) { + if (nr->n2count == nr->n2) { nr_disconnect(sk, ETIMEDOUT); return; } else { - sk->protinfo.nr->n2count++; + nr->n2count++; nr_write_internal(sk, NR_DISCREQ); } break; case NR_STATE_3: - if (sk->protinfo.nr->n2count == sk->protinfo.nr->n2) { + if (nr->n2count == nr->n2) { nr_disconnect(sk, ETIMEDOUT); return; } else { - sk->protinfo.nr->n2count++; + nr->n2count++; nr_requeue_frames(sk); } break; Index: kernel-acme/net/packet/af_packet.c diff -u kernel-acme/net/packet/af_packet.c:1.1.1.4 kernel-acme/net/packet/af_packet.c:1.1.1.4.6.3 --- kernel-acme/net/packet/af_packet.c:1.1.1.4 Tue Nov 6 21:30:49 2001 +++ kernel-acme/net/packet/af_packet.c Fri Dec 21 02:12:17 2001 @@ -5,7 +5,7 @@ * * PACKET - implements raw packet sockets. * - * Version: $Id: af_packet.c,v 1.1.1.4 2001/11/06 21:30:49 acme Exp $ + * Version: $Id: af_packet.c,v 1.1.1.4.6.3 2001/12/21 02:12:17 acme Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -199,6 +199,8 @@ #endif }; +#define PKT_SK(__sk) ((struct packet_opt *)(__sk)->protinfo) + void packet_sock_destruct(struct sock *sk) { BUG_TRAP(atomic_read(&sk->rmem_alloc)==0); @@ -209,8 +211,8 @@ return; } - if (sk->protinfo.destruct_hook) - kfree(sk->protinfo.destruct_hook); + if (PKT_SK(sk)) + kfree(PKT_SK(sk)); atomic_dec(&packet_socks_nr); #ifdef PACKET_REFCNT_DEBUG printk(KERN_DEBUG "PACKET socket %p is free, %d are alive\n", sk, atomic_read(&packet_socks_nr)); @@ -413,7 +415,7 @@ goto drop; sk = (struct sock *) pt->data; - po = sk->protinfo.af_packet; + po = PKT_SK(sk); skb->dev = dev; @@ -528,7 +530,7 @@ goto drop; sk = (struct sock *) pt->data; - po = sk->protinfo.af_packet; + po = PKT_SK(sk); if (dev->hard_header) { if (sk->type != SOCK_DGRAM) @@ -676,7 +678,7 @@ */ if (saddr == NULL) { - ifindex = sk->protinfo.af_packet->ifindex; + ifindex = PKT_SK(sk)->ifindex; proto = sk->num; addr = NULL; } else { @@ -780,12 +782,12 @@ * Unhook packet receive handler. */ - if (sk->protinfo.af_packet->running) { + if (PKT_SK(sk)->running) { /* * Remove the protocol hook */ - dev_remove_pack(&sk->protinfo.af_packet->prot_hook); - sk->protinfo.af_packet->running = 0; + dev_remove_pack(&PKT_SK(sk)->prot_hook); + PKT_SK(sk)->running = 0; __sock_put(sk); } @@ -794,7 +796,7 @@ #endif #ifdef CONFIG_PACKET_MMAP - if (sk->protinfo.af_packet->pg_vec) { + if (PKT_SK(sk)->pg_vec) { struct tpacket_req req; memset(&req, 0, sizeof(req)); packet_set_ring(sk, &req, 1); @@ -828,40 +830,40 @@ lock_sock(sk); - spin_lock(&sk->protinfo.af_packet->bind_lock); - if (sk->protinfo.af_packet->running) { - dev_remove_pack(&sk->protinfo.af_packet->prot_hook); + spin_lock(&PKT_SK(sk)->bind_lock); + if (PKT_SK(sk)->running) { + dev_remove_pack(&PKT_SK(sk)->prot_hook); __sock_put(sk); - sk->protinfo.af_packet->running = 0; + PKT_SK(sk)->running = 0; } sk->num = protocol; - sk->protinfo.af_packet->prot_hook.type = protocol; - sk->protinfo.af_packet->prot_hook.dev = dev; + PKT_SK(sk)->prot_hook.type = protocol; + PKT_SK(sk)->prot_hook.dev = dev; - sk->protinfo.af_packet->ifindex = dev ? dev->ifindex : 0; + PKT_SK(sk)->ifindex = dev ? dev->ifindex : 0; if (protocol == 0) goto out_unlock; if (dev) { if (dev->flags&IFF_UP) { - dev_add_pack(&sk->protinfo.af_packet->prot_hook); + dev_add_pack(&PKT_SK(sk)->prot_hook); sock_hold(sk); - sk->protinfo.af_packet->running = 1; + PKT_SK(sk)->running = 1; } else { sk->err = ENETDOWN; if (!sk->dead) sk->error_report(sk); } } else { - dev_add_pack(&sk->protinfo.af_packet->prot_hook); + dev_add_pack(&PKT_SK(sk)->prot_hook); sock_hold(sk); - sk->protinfo.af_packet->running = 1; + PKT_SK(sk)->running = 1; } out_unlock: - spin_unlock(&sk->protinfo.af_packet->bind_lock); + spin_unlock(&PKT_SK(sk)->bind_lock); release_sock(sk); return 0; } @@ -951,7 +953,7 @@ MOD_INC_USE_COUNT; err = -ENOBUFS; - sk = sk_alloc(PF_PACKET, GFP_KERNEL, 1); + sk = sk_alloc(PF_PACKET, GFP_KERNEL, 1, NULL); if (sk == NULL) goto out; @@ -962,10 +964,10 @@ #endif sock_init_data(sock,sk); - sk->protinfo.af_packet = kmalloc(sizeof(struct packet_opt), GFP_KERNEL); - if (sk->protinfo.af_packet == NULL) + PKT_SK(sk) = kmalloc(sizeof(struct packet_opt), GFP_KERNEL); + if (!PKT_SK(sk)) goto out_free; - memset(sk->protinfo.af_packet, 0, sizeof(struct packet_opt)); + memset(PKT_SK(sk), 0, sizeof(struct packet_opt)); sk->family = PF_PACKET; sk->num = protocol; @@ -976,19 +978,19 @@ * Attach a protocol block */ - spin_lock_init(&sk->protinfo.af_packet->bind_lock); - sk->protinfo.af_packet->prot_hook.func = packet_rcv; + spin_lock_init(&PKT_SK(sk)->bind_lock); + PKT_SK(sk)->prot_hook.func = packet_rcv; #ifdef CONFIG_SOCK_PACKET if (sock->type == SOCK_PACKET) - sk->protinfo.af_packet->prot_hook.func = packet_rcv_spkt; + PKT_SK(sk)->prot_hook.func = packet_rcv_spkt; #endif - sk->protinfo.af_packet->prot_hook.data = (void *)sk; + PKT_SK(sk)->prot_hook.data = (void *)sk; if (protocol) { - sk->protinfo.af_packet->prot_hook.type = protocol; - dev_add_pack(&sk->protinfo.af_packet->prot_hook); + PKT_SK(sk)->prot_hook.type = protocol; + dev_add_pack(&PKT_SK(sk)->prot_hook); sock_hold(sk); - sk->protinfo.af_packet->running = 1; + PKT_SK(sk)->running = 1; } write_lock_bh(&packet_sklist_lock); @@ -1023,7 +1025,7 @@ #if 0 /* What error should we return now? EUNATTACH? */ - if (sk->protinfo.af_packet->ifindex < 0) + if (PKT_SK(sk)->ifindex < 0) return -ENODEV; #endif @@ -1101,7 +1103,7 @@ return -EOPNOTSUPP; uaddr->sa_family = AF_PACKET; - dev = dev_get_by_index(sk->protinfo.af_packet->ifindex); + dev = dev_get_by_index(PKT_SK(sk)->ifindex); if (dev) { strncpy(uaddr->sa_data, dev->name, 15); dev_put(dev); @@ -1124,9 +1126,9 @@ return -EOPNOTSUPP; sll->sll_family = AF_PACKET; - sll->sll_ifindex = sk->protinfo.af_packet->ifindex; + sll->sll_ifindex = PKT_SK(sk)->ifindex; sll->sll_protocol = sk->num; - dev = dev_get_by_index(sk->protinfo.af_packet->ifindex); + dev = dev_get_by_index(PKT_SK(sk)->ifindex); if (dev) { sll->sll_hatype = dev->type; sll->sll_halen = dev->addr_len; @@ -1192,7 +1194,7 @@ goto done; err = 0; - for (ml=sk->protinfo.af_packet->mclist; ml; ml=ml->next) { + for (ml=PKT_SK(sk)->mclist; ml; ml=ml->next) { if (ml->ifindex == mreq->mr_ifindex && ml->type == mreq->mr_type && ml->alen == mreq->mr_alen && @@ -1209,8 +1211,8 @@ i->alen = mreq->mr_alen; memcpy(i->addr, mreq->mr_address, i->alen); i->count = 1; - i->next = sk->protinfo.af_packet->mclist; - sk->protinfo.af_packet->mclist = i; + i->next = PKT_SK(sk)->mclist; + PKT_SK(sk)->mclist = i; packet_dev_mc(dev, i, +1); done: @@ -1224,7 +1226,7 @@ rtnl_lock(); - for (mlp=&sk->protinfo.af_packet->mclist; (ml=*mlp)!=NULL; mlp=&ml->next) { + for (mlp=&PKT_SK(sk)->mclist; (ml=*mlp)!=NULL; mlp=&ml->next) { if (ml->ifindex == mreq->mr_ifindex && ml->type == mreq->mr_type && ml->alen == mreq->mr_alen && @@ -1251,13 +1253,13 @@ { struct packet_mclist *ml; - if (sk->protinfo.af_packet->mclist == NULL) + if (PKT_SK(sk)->mclist == NULL) return; rtnl_lock(); - while ((ml=sk->protinfo.af_packet->mclist) != NULL) { + while ((ml=PKT_SK(sk)->mclist) != NULL) { struct net_device *dev; - sk->protinfo.af_packet->mclist = ml->next; + PKT_SK(sk)->mclist = ml->next; if ((dev = dev_get_by_index(ml->ifindex)) != NULL) { packet_dev_mc(dev, ml, -1); dev_put(dev); @@ -1314,7 +1316,7 @@ if (copy_from_user(&val,optval,sizeof(val))) return -EFAULT; - sk->protinfo.af_packet->copy_thresh = val; + PKT_SK(sk)->copy_thresh = val; return 0; } #endif @@ -1346,8 +1348,8 @@ if (len > sizeof(struct tpacket_stats)) len = sizeof(struct tpacket_stats); spin_lock_bh(&sk->receive_queue.lock); - st = sk->protinfo.af_packet->stats; - memset(&sk->protinfo.af_packet->stats, 0, sizeof(st)); + st = PKT_SK(sk)->stats; + memset(&PKT_SK(sk)->stats, 0, sizeof(st)); spin_unlock_bh(&sk->receive_queue.lock); st.tp_packets += st.tp_drops; @@ -1373,7 +1375,7 @@ read_lock(&packet_sklist_lock); for (sk = packet_sklist; sk; sk = sk->next) { - po = sk->protinfo.af_packet; + po = PKT_SK(sk); switch (msg) { case NETDEV_DOWN: @@ -1552,7 +1554,7 @@ unsigned int packet_poll(struct file * file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; - struct packet_opt *po = sk->protinfo.af_packet; + struct packet_opt *po = PKT_SK(sk); unsigned int mask = datagram_poll(file, sock, wait); spin_lock_bh(&sk->receive_queue.lock); @@ -1579,7 +1581,7 @@ struct sock *sk = sock->sk; if (sk) - atomic_inc(&sk->protinfo.af_packet->mapped); + atomic_inc(&PKT_SK(sk)->mapped); } static void packet_mm_close(struct vm_area_struct *vma) @@ -1590,7 +1592,7 @@ struct sock *sk = sock->sk; if (sk) - atomic_dec(&sk->protinfo.af_packet->mapped); + atomic_dec(&PKT_SK(sk)->mapped); } static struct vm_operations_struct packet_mmap_ops = { @@ -1620,7 +1622,7 @@ { unsigned long *pg_vec = NULL; struct tpacket_hdr **io_vec = NULL; - struct packet_opt *po = sk->protinfo.af_packet; + struct packet_opt *po = PKT_SK(sk); int order = 0; int err = 0; @@ -1742,7 +1744,7 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_struct *vma) { struct sock *sk = sock->sk; - struct packet_opt *po = sk->protinfo.af_packet; + struct packet_opt *po = PKT_SK(sk); unsigned long size; unsigned long start; int err = -EINVAL; @@ -1851,8 +1853,8 @@ atomic_read(&s->refcnt), s->type, ntohs(s->num), - s->protinfo.af_packet->ifindex, - s->protinfo.af_packet->running, + PKT_SK(s)->ifindex, + PKT_SK(s)->running, atomic_read(&s->rmem_alloc), sock_i_uid(s), sock_i_ino(s) Index: kernel-acme/net/rose/af_rose.c diff -u kernel-acme/net/rose/af_rose.c:1.1.1.3 kernel-acme/net/rose/af_rose.c:1.1.1.3.8.2 --- kernel-acme/net/rose/af_rose.c:1.1.1.3 Wed Sep 26 22:00:30 2001 +++ kernel-acme/net/rose/af_rose.c Fri Dec 21 02:12:17 2001 @@ -149,7 +149,7 @@ struct sock *sk; rose_cb *rose; - if ((sk = sk_alloc(PF_ROSE, GFP_ATOMIC, 1)) == NULL) + if ((sk = sk_alloc(PF_ROSE, GFP_ATOMIC, 1, NULL)) == NULL) return NULL; if ((rose = kmalloc(sizeof(*rose), GFP_ATOMIC)) == NULL) { @@ -161,8 +161,8 @@ memset(rose, 0x00, sizeof(*rose)); - sk->protinfo.rose = rose; - rose->sk = sk; + ROSE_SK(sk) = rose; + rose->sk = sk; return sk; } @@ -205,10 +205,12 @@ struct sock *s; for (s = rose_list; s != NULL; s = s->next) { - if (s->protinfo.rose->neighbour == neigh) { + rose_cb *rose = ROSE_SK(s); + + if (rose->neighbour == neigh) { rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); - s->protinfo.rose->neighbour->use--; - s->protinfo.rose->neighbour = NULL; + rose->neighbour->use--; + rose->neighbour = NULL; } } } @@ -221,10 +223,12 @@ struct sock *s; for (s = rose_list; s != NULL; s = s->next) { - if (s->protinfo.rose->device == dev) { + rose_cb *rose = ROSE_SK(s); + + if (rose->device == dev) { rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); - s->protinfo.rose->neighbour->use--; - s->protinfo.rose->device = NULL; + rose->neighbour->use--; + rose->device = NULL; } } } @@ -279,14 +283,22 @@ save_flags(flags); cli(); for (s = rose_list; s != NULL; s = s->next) { - if (rosecmp(&s->protinfo.rose->source_addr, addr) == 0 && ax25cmp(&s->protinfo.rose->source_call, call) == 0 && s->protinfo.rose->source_ndigis == 0 && s->state == TCP_LISTEN) { + rose_cb *rose = ROSE_SK(s); + + if (!rosecmp(&rose->source_addr, addr) && + !ax25cmp(&rose->source_call, call) && + !rose->source_ndigis && s->state == TCP_LISTEN) { restore_flags(flags); return s; } } for (s = rose_list; s != NULL; s = s->next) { - if (rosecmp(&s->protinfo.rose->source_addr, addr) == 0 && ax25cmp(&s->protinfo.rose->source_call, &null_ax25_address) == 0 && s->state == TCP_LISTEN) { + rose_cb *rose = ROSE_SK(s); + + if (!rosecmp(&rose->source_addr, addr) && + !ax25cmp(&rose->source_call, &null_ax25_address) && + s->state == TCP_LISTEN) { restore_flags(flags); return s; } @@ -307,7 +319,9 @@ save_flags(flags); cli(); for (s = rose_list; s != NULL; s = s->next) { - if (s->protinfo.rose->lci == lci && s->protinfo.rose->neighbour == neigh) { + rose_cb *rose = ROSE_SK(s); + + if (rose->lci == lci && rose->neighbour == neigh) { restore_flags(flags); return s; } @@ -375,7 +389,7 @@ if (skb->sk != sk) { /* A pending connection */ skb->sk->dead = 1; /* Queue the unaccepted socket for death */ rose_start_heartbeat(skb->sk); - skb->sk->protinfo.rose->state = ROSE_STATE_0; + ROSE_SK(skb->sk)->state = ROSE_STATE_0; } kfree_skb(skb); @@ -404,6 +418,7 @@ char *optval, int optlen) { struct sock *sk = sock->sk; + rose_cb *rose = ROSE_SK(sk); int opt; if (level != SOL_ROSE) @@ -417,41 +432,41 @@ switch (optname) { case ROSE_DEFER: - sk->protinfo.rose->defer = opt ? 1 : 0; + rose->defer = opt ? 1 : 0; return 0; case ROSE_T1: if (opt < 1) return -EINVAL; - sk->protinfo.rose->t1 = opt * HZ; + rose->t1 = opt * HZ; return 0; case ROSE_T2: if (opt < 1) return -EINVAL; - sk->protinfo.rose->t2 = opt * HZ; + rose->t2 = opt * HZ; return 0; case ROSE_T3: if (opt < 1) return -EINVAL; - sk->protinfo.rose->t3 = opt * HZ; + rose->t3 = opt * HZ; return 0; case ROSE_HOLDBACK: if (opt < 1) return -EINVAL; - sk->protinfo.rose->hb = opt * HZ; + rose->hb = opt * HZ; return 0; case ROSE_IDLE: if (opt < 0) return -EINVAL; - sk->protinfo.rose->idle = opt * 60 * HZ; + rose->idle = opt * 60 * HZ; return 0; case ROSE_QBITINCL: - sk->protinfo.rose->qbitincl = opt ? 1 : 0; + rose->qbitincl = opt ? 1 : 0; return 0; default: @@ -463,6 +478,7 @@ char *optval, int *optlen) { struct sock *sk = sock->sk; + rose_cb *rose = ROSE_SK(sk); int val = 0; int len; @@ -477,31 +493,31 @@ switch (optname) { case ROSE_DEFER: - val = sk->protinfo.rose->defer; + val = rose->defer; break; case ROSE_T1: - val = sk->protinfo.rose->t1 / HZ; + val = rose->t1 / HZ; break; case ROSE_T2: - val = sk->protinfo.rose->t2 / HZ; + val = rose->t2 / HZ; break; case ROSE_T3: - val = sk->protinfo.rose->t3 / HZ; + val = rose->t3 / HZ; break; case ROSE_HOLDBACK: - val = sk->protinfo.rose->hb / HZ; + val = rose->hb / HZ; break; case ROSE_IDLE: - val = sk->protinfo.rose->idle / (60 * HZ); + val = rose->idle / (60 * HZ); break; case ROSE_QBITINCL: - val = sk->protinfo.rose->qbitincl; + val = rose->qbitincl; break; default: @@ -521,10 +537,12 @@ struct sock *sk = sock->sk; if (sk->state != TCP_LISTEN) { - sk->protinfo.rose->dest_ndigis = 0; - memset(&sk->protinfo.rose->dest_addr, '\0', ROSE_ADDR_LEN); - memset(&sk->protinfo.rose->dest_call, '\0', AX25_ADDR_LEN); - memset(sk->protinfo.rose->dest_digis, '\0', AX25_ADDR_LEN*ROSE_MAX_DIGIS); + rose_cb *rose = ROSE_SK(sk); + + rose->dest_ndigis = 0; + memset(&rose->dest_addr, 0, ROSE_ADDR_LEN); + memset(&rose->dest_call, 0, AX25_ADDR_LEN); + memset(rose->dest_digis, 0, AX25_ADDR_LEN * ROSE_MAX_DIGIS); sk->max_ack_backlog = backlog; sk->state = TCP_LISTEN; return 0; @@ -544,7 +562,7 @@ if ((sk = rose_alloc_sock()) == NULL) return -ENOMEM; - rose = sk->protinfo.rose; + rose = ROSE_SK(sk); sock_init_data(sock, sk); @@ -574,7 +592,7 @@ static struct sock *rose_make_new(struct sock *osk) { struct sock *sk; - rose_cb *rose; + rose_cb *rose, *orose; if (osk->type != SOCK_SEQPACKET) return NULL; @@ -582,7 +600,7 @@ if ((sk = rose_alloc_sock()) == NULL) return NULL; - rose = sk->protinfo.rose; + rose = ROSE_SK(sk); sock_init_data(NULL, sk); @@ -606,15 +624,15 @@ init_timer(&rose->timer); init_timer(&rose->idletimer); - rose->t1 = osk->protinfo.rose->t1; - rose->t2 = osk->protinfo.rose->t2; - rose->t3 = osk->protinfo.rose->t3; - rose->hb = osk->protinfo.rose->hb; - rose->idle = osk->protinfo.rose->idle; - - rose->defer = osk->protinfo.rose->defer; - rose->device = osk->protinfo.rose->device; - rose->qbitincl = osk->protinfo.rose->qbitincl; + orose = ROSE_SK(osk); + rose->t1 = orose->t1; + rose->t2 = orose->t2; + rose->t3 = orose->t3; + rose->hb = orose->hb; + rose->idle = orose->idle; + rose->defer = orose->defer; + rose->device = orose->device; + rose->qbitincl = orose->qbitincl; return sk; } @@ -622,18 +640,21 @@ static int rose_release(struct socket *sock) { struct sock *sk = sock->sk; + rose_cb *rose; if (sk == NULL) return 0; - switch (sk->protinfo.rose->state) { + rose = ROSE_SK(sk); + switch (rose->state) { + case ROSE_STATE_0: rose_disconnect(sk, 0, -1, -1); rose_destroy_socket(sk); break; case ROSE_STATE_2: - sk->protinfo.rose->neighbour->use--; + rose->neighbour->use--; rose_disconnect(sk, 0, -1, -1); rose_destroy_socket(sk); break; @@ -646,12 +667,12 @@ rose_stop_idletimer(sk); rose_write_internal(sk, ROSE_CLEAR_REQUEST); rose_start_t3timer(sk); - sk->protinfo.rose->state = ROSE_STATE_2; - sk->state = TCP_CLOSE; - sk->shutdown |= SEND_SHUTDOWN; + rose->state = ROSE_STATE_2; + sk->state = TCP_CLOSE; + sk->shutdown |= SEND_SHUTDOWN; sk->state_change(sk); - sk->dead = 1; - sk->destroy = 1; + sk->dead = 1; + sk->destroy = 1; break; default: @@ -667,6 +688,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; + rose_cb *rose = ROSE_SK(sk); struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; struct net_device *dev; ax25_address *user, *source; @@ -700,18 +722,18 @@ user = source; } - sk->protinfo.rose->source_addr = addr->srose_addr; - sk->protinfo.rose->source_call = *user; - sk->protinfo.rose->device = dev; - sk->protinfo.rose->source_ndigis = addr->srose_ndigis; + rose->source_addr = addr->srose_addr; + rose->source_call = *user; + rose->device = dev; + rose->source_ndigis = addr->srose_ndigis; if (addr_len == sizeof(struct full_sockaddr_rose)) { struct full_sockaddr_rose *full_addr = (struct full_sockaddr_rose *)uaddr; for (n = 0 ; n < addr->srose_ndigis ; n++) - sk->protinfo.rose->source_digis[n] = full_addr->srose_digis[n]; + rose->source_digis[n] = full_addr->srose_digis[n]; } else { - if (sk->protinfo.rose->source_ndigis == 1) { - sk->protinfo.rose->source_digis[0] = addr->srose_digi; + if (rose->source_ndigis == 1) { + rose->source_digis[0] = addr->srose_digi; } } @@ -725,6 +747,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { struct sock *sk = sock->sk; + rose_cb *rose = ROSE_SK(sk); struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; unsigned char cause, diagnostic; ax25_address *user; @@ -760,13 +783,16 @@ return -EINVAL; /* Source + Destination digis should not exceed ROSE_MAX_DIGIS */ - if ((sk->protinfo.rose->source_ndigis + addr->srose_ndigis) > ROSE_MAX_DIGIS) + if ((rose->source_ndigis + addr->srose_ndigis) > ROSE_MAX_DIGIS) return -EINVAL; - if ((sk->protinfo.rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic)) == NULL) + rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, + &diagnostic); + if (!rose->neighbour) return -ENETUNREACH; - if ((sk->protinfo.rose->lci = rose_new_lci(sk->protinfo.rose->neighbour)) == 0) + rose->lci = rose_new_lci(rose->neighbour); + if (!rose->lci) return -ENETUNREACH; if (sk->zapped) { /* Must bind first - autobinding in this may or may not work */ @@ -778,25 +804,25 @@ if ((user = ax25_findbyuid(current->euid)) == NULL) return -EINVAL; - memcpy(&sk->protinfo.rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN); - sk->protinfo.rose->source_call = *user; - sk->protinfo.rose->device = dev; + memcpy(&rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN); + rose->source_call = *user; + rose->device = dev; rose_insert_socket(sk); /* Finish the bind */ } - sk->protinfo.rose->dest_addr = addr->srose_addr; - sk->protinfo.rose->dest_call = addr->srose_call; - sk->protinfo.rose->rand = ((int)sk->protinfo.rose & 0xFFFF) + sk->protinfo.rose->lci; - sk->protinfo.rose->dest_ndigis = addr->srose_ndigis; + rose->dest_addr = addr->srose_addr; + rose->dest_call = addr->srose_call; + rose->rand = ((int)rose & 0xFFFF) + rose->lci; + rose->dest_ndigis = addr->srose_ndigis; if (addr_len == sizeof(struct full_sockaddr_rose)) { struct full_sockaddr_rose *full_addr = (struct full_sockaddr_rose *)uaddr; for (n = 0 ; n < addr->srose_ndigis ; n++) - sk->protinfo.rose->dest_digis[n] = full_addr->srose_digis[n]; + rose->dest_digis[n] = full_addr->srose_digis[n]; } else { - if (sk->protinfo.rose->dest_ndigis == 1) { - sk->protinfo.rose->dest_digis[0] = addr->srose_digi; + if (rose->dest_ndigis == 1) { + rose->dest_digis[0] = addr->srose_digi; } } @@ -804,9 +830,9 @@ sock->state = SS_CONNECTING; sk->state = TCP_SYN_SENT; - sk->protinfo.rose->state = ROSE_STATE_1; + rose->state = ROSE_STATE_1; - sk->protinfo.rose->neighbour->use++; + rose->neighbour->use++; rose_write_internal(sk, ROSE_CALL_REQUEST); rose_start_heartbeat(sk); @@ -896,24 +922,25 @@ { struct full_sockaddr_rose *srose = (struct full_sockaddr_rose *)uaddr; struct sock *sk = sock->sk; + rose_cb *rose = ROSE_SK(sk); int n; if (peer != 0) { if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; srose->srose_family = AF_ROSE; - srose->srose_addr = sk->protinfo.rose->dest_addr; - srose->srose_call = sk->protinfo.rose->dest_call; - srose->srose_ndigis = sk->protinfo.rose->dest_ndigis; - for (n = 0 ; n < sk->protinfo.rose->dest_ndigis ; n++) - srose->srose_digis[n] = sk->protinfo.rose->dest_digis[n]; + srose->srose_addr = rose->dest_addr; + srose->srose_call = rose->dest_call; + srose->srose_ndigis = rose->dest_ndigis; + for (n = 0; n < rose->dest_ndigis; n++) + srose->srose_digis[n] = rose->dest_digis[n]; } else { srose->srose_family = AF_ROSE; - srose->srose_addr = sk->protinfo.rose->source_addr; - srose->srose_call = sk->protinfo.rose->source_call; - srose->srose_ndigis = sk->protinfo.rose->source_ndigis; - for (n = 0 ; n < sk->protinfo.rose->source_ndigis ; n++) - srose->srose_digis[n] = sk->protinfo.rose->source_digis[n]; + srose->srose_addr = rose->source_addr; + srose->srose_call = rose->source_call; + srose->srose_ndigis = rose->source_ndigis; + for (n = 0; n < rose->source_ndigis; n++) + srose->srose_digis[n] = rose->source_digis[n]; } *uaddr_len = sizeof(struct full_sockaddr_rose); @@ -924,6 +951,7 @@ { struct sock *sk; struct sock *make; + rose_cb *make_rose; struct rose_facilities_struct facilities; int n, len; @@ -953,37 +981,38 @@ skb->sk = make; make->state = TCP_ESTABLISHED; + make_rose = ROSE_SK(make); - make->protinfo.rose->lci = lci; - make->protinfo.rose->dest_addr = facilities.dest_addr; - make->protinfo.rose->dest_call = facilities.dest_call; - make->protinfo.rose->dest_ndigis = facilities.dest_ndigis; + make_rose->lci = lci; + make_rose->dest_addr = facilities.dest_addr; + make_rose->dest_call = facilities.dest_call; + make_rose->dest_ndigis = facilities.dest_ndigis; for (n = 0 ; n < facilities.dest_ndigis ; n++) - make->protinfo.rose->dest_digis[n] = facilities.dest_digis[n]; - make->protinfo.rose->source_addr = facilities.source_addr; - make->protinfo.rose->source_call = facilities.source_call; - make->protinfo.rose->source_ndigis = facilities.source_ndigis; + make_rose->dest_digis[n] = facilities.dest_digis[n]; + make_rose->source_addr = facilities.source_addr; + make_rose->source_call = facilities.source_call; + make_rose->source_ndigis = facilities.source_ndigis; for (n = 0 ; n < facilities.source_ndigis ; n++) - make->protinfo.rose->source_digis[n]= facilities.source_digis[n]; - make->protinfo.rose->neighbour = neigh; - make->protinfo.rose->device = dev; - make->protinfo.rose->facilities = facilities; + make_rose->source_digis[n]= facilities.source_digis[n]; + make_rose->neighbour = neigh; + make_rose->device = dev; + make_rose->facilities = facilities; - make->protinfo.rose->neighbour->use++; + make_rose->neighbour->use++; - if (sk->protinfo.rose->defer) { - make->protinfo.rose->state = ROSE_STATE_5; + if (ROSE_SK(sk)->defer) { + make_rose->state = ROSE_STATE_5; } else { rose_write_internal(make, ROSE_CALL_ACCEPTED); - make->protinfo.rose->state = ROSE_STATE_3; + make_rose->state = ROSE_STATE_3; rose_start_idletimer(make); } - make->protinfo.rose->condition = 0x00; - make->protinfo.rose->vs = 0; - make->protinfo.rose->va = 0; - make->protinfo.rose->vr = 0; - make->protinfo.rose->vl = 0; + make_rose->condition = 0x00; + make_rose->vs = 0; + make_rose->va = 0; + make_rose->vr = 0; + make_rose->vl = 0; sk->ack_backlog++; make->pair = sk; @@ -1003,6 +1032,7 @@ struct scm_cookie *scm) { struct sock *sk = sock->sk; + rose_cb *rose = ROSE_SK(sk); struct sockaddr_rose *usrose = (struct sockaddr_rose *)msg->msg_name; int err; struct full_sockaddr_rose srose; @@ -1021,7 +1051,7 @@ return -EPIPE; } - if (sk->protinfo.rose->neighbour == NULL || sk->protinfo.rose->device == NULL) + if (rose->neighbour == NULL || rose->device == NULL) return -ENETUNREACH; if (usrose != NULL) { @@ -1029,14 +1059,15 @@ return -EINVAL; memset(&srose, 0, sizeof(struct full_sockaddr_rose)); memcpy(&srose, usrose, msg->msg_namelen); - if (rosecmp(&sk->protinfo.rose->dest_addr, &srose.srose_addr) != 0 || - ax25cmp(&sk->protinfo.rose->dest_call, &srose.srose_call) != 0) + if (rosecmp(&rose->dest_addr, &srose.srose_addr) != 0 || + ax25cmp(&rose->dest_call, &srose.srose_call) != 0) return -EISCONN; - if (srose.srose_ndigis != sk->protinfo.rose->dest_ndigis) + if (srose.srose_ndigis != rose->dest_ndigis) return -EISCONN; - if (srose.srose_ndigis == sk->protinfo.rose->dest_ndigis) { + if (srose.srose_ndigis == rose->dest_ndigis) { for (n = 0 ; n < srose.srose_ndigis ; n++) - if (ax25cmp(&sk->protinfo.rose->dest_digis[n], &srose.srose_digis[n]) != 0) + if (ax25cmp(&rose->dest_digis[n], + &srose.srose_digis[n])) return -EISCONN; } if (srose.srose_family != AF_ROSE) @@ -1046,11 +1077,11 @@ return -ENOTCONN; srose.srose_family = AF_ROSE; - srose.srose_addr = sk->protinfo.rose->dest_addr; - srose.srose_call = sk->protinfo.rose->dest_call; - srose.srose_ndigis = sk->protinfo.rose->dest_ndigis; - for (n = 0 ; n < sk->protinfo.rose->dest_ndigis ; n++) - srose.srose_digis[n] = sk->protinfo.rose->dest_digis[n]; + srose.srose_addr = rose->dest_addr; + srose.srose_call = rose->dest_call; + srose.srose_ndigis = rose->dest_ndigis; + for (n = 0 ; n < rose->dest_ndigis ; n++) + srose.srose_digis[n] = rose->dest_digis[n]; } SOCK_DEBUG(sk, "ROSE: sendto: Addresses built.\n"); @@ -1077,7 +1108,7 @@ * If the Q BIT Include socket option is in force, the first * byte of the user data is the logical value of the Q Bit. */ - if (sk->protinfo.rose->qbitincl) { + if (rose->qbitincl) { qbit = skb->data[0]; skb_pull(skb, 1); } @@ -1090,8 +1121,8 @@ SOCK_DEBUG(sk, "ROSE: Building Network Header.\n"); /* Build a ROSE Network header */ - asmptr[0] = ((sk->protinfo.rose->lci >> 8) & 0x0F) | ROSE_GFI; - asmptr[1] = (sk->protinfo.rose->lci >> 0) & 0xFF; + asmptr[0] = ((rose->lci >> 8) & 0x0F) | ROSE_GFI; + asmptr[1] = (rose->lci >> 0) & 0xFF; asmptr[2] = ROSE_DATA; if (qbit) @@ -1165,6 +1196,7 @@ int flags, struct scm_cookie *scm) { struct sock *sk = sock->sk; + rose_cb *rose = ROSE_SK(sk); struct sockaddr_rose *srose = (struct sockaddr_rose *)msg->msg_name; int copied, qbit; unsigned char *asmptr; @@ -1186,7 +1218,7 @@ skb_pull(skb, ROSE_MIN_LEN); - if (sk->protinfo.rose->qbitincl) { + if (rose->qbitincl) { asmptr = skb_push(skb, 1); *asmptr = qbit; } @@ -1203,18 +1235,18 @@ if (srose != NULL) { srose->srose_family = AF_ROSE; - srose->srose_addr = sk->protinfo.rose->dest_addr; - srose->srose_call = sk->protinfo.rose->dest_call; - srose->srose_ndigis = sk->protinfo.rose->dest_ndigis; + srose->srose_addr = rose->dest_addr; + srose->srose_call = rose->dest_call; + srose->srose_ndigis = rose->dest_ndigis; if (msg->msg_namelen >= sizeof(struct full_sockaddr_rose)) { struct full_sockaddr_rose *full_srose = (struct full_sockaddr_rose *)msg->msg_name; - for (n = 0 ; n < sk->protinfo.rose->dest_ndigis ; n++) - full_srose->srose_digis[n] = sk->protinfo.rose->dest_digis[n]; + for (n = 0 ; n < rose->dest_ndigis ; n++) + full_srose->srose_digis[n] = rose->dest_digis[n]; msg->msg_namelen = sizeof(struct full_sockaddr_rose); } else { - if (sk->protinfo.rose->dest_ndigis >= 1) { + if (rose->dest_ndigis >= 1) { srose->srose_ndigis = 1; - srose->srose_digi = sk->protinfo.rose->dest_digis[0]; + srose->srose_digi = rose->dest_digis[0]; } msg->msg_namelen = sizeof(struct sockaddr_rose); } @@ -1229,6 +1261,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; + rose_cb *rose = ROSE_SK(sk); switch (cmd) { case TIOCOUTQ: { @@ -1276,8 +1309,8 @@ case SIOCRSGCAUSE: { struct rose_cause_struct rose_cause; - rose_cause.cause = sk->protinfo.rose->cause; - rose_cause.diagnostic = sk->protinfo.rose->diagnostic; + rose_cause.cause = rose->cause; + rose_cause.diagnostic = rose->diagnostic; return copy_to_user((void *)arg, &rose_cause, sizeof(struct rose_cause_struct)) ? -EFAULT : 0; } @@ -1285,8 +1318,8 @@ struct rose_cause_struct rose_cause; if (copy_from_user(&rose_cause, (void *)arg, sizeof(struct rose_cause_struct))) return -EFAULT; - sk->protinfo.rose->cause = rose_cause.cause; - sk->protinfo.rose->diagnostic = rose_cause.diagnostic; + rose->cause = rose_cause.cause; + rose->diagnostic = rose_cause.diagnostic; return 0; } @@ -1304,15 +1337,15 @@ return copy_to_user((void *)arg, &rose_callsign, sizeof(ax25_address)) ? -EFAULT : 0; case SIOCRSACCEPT: - if (sk->protinfo.rose->state == ROSE_STATE_5) { + if (rose->state == ROSE_STATE_5) { rose_write_internal(sk, ROSE_CALL_ACCEPTED); rose_start_idletimer(sk); - sk->protinfo.rose->condition = 0x00; - sk->protinfo.rose->vs = 0; - sk->protinfo.rose->va = 0; - sk->protinfo.rose->vr = 0; - sk->protinfo.rose->vl = 0; - sk->protinfo.rose->state = ROSE_STATE_3; + rose->condition = 0x00; + rose->vs = 0; + rose->va = 0; + rose->vr = 0; + rose->vl = 0; + rose->state = ROSE_STATE_3; } return 0; @@ -1338,37 +1371,39 @@ len += sprintf(buffer, "dest_addr dest_call src_addr src_call dev lci neigh st vs vr va t t1 t2 t3 hb idle Snd-Q Rcv-Q inode\n"); for (s = rose_list; s != NULL; s = s->next) { - if ((dev = s->protinfo.rose->device) == NULL) + rose_cb *rose = ROSE_SK(s); + + if ((dev = rose->device) == NULL) devname = "???"; else devname = dev->name; len += sprintf(buffer + len, "%-10s %-9s ", - rose2asc(&s->protinfo.rose->dest_addr), - ax2asc(&s->protinfo.rose->dest_call)); + rose2asc(&rose->dest_addr), + ax2asc(&rose->dest_call)); - if (ax25cmp(&s->protinfo.rose->source_call, &null_ax25_address) == 0) + if (ax25cmp(&rose->source_call, &null_ax25_address) == 0) callsign = "??????-?"; else - callsign = ax2asc(&s->protinfo.rose->source_call); + callsign = ax2asc(&rose->source_call); len += sprintf(buffer + len, "%-10s %-9s %-5s %3.3X %05d %d %d %d %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d %ld\n", - rose2asc(&s->protinfo.rose->source_addr), + rose2asc(&rose->source_addr), callsign, devname, - s->protinfo.rose->lci & 0x0FFF, - (s->protinfo.rose->neighbour) ? s->protinfo.rose->neighbour->number : 0, - s->protinfo.rose->state, - s->protinfo.rose->vs, - s->protinfo.rose->vr, - s->protinfo.rose->va, - ax25_display_timer(&s->protinfo.rose->timer) / HZ, - s->protinfo.rose->t1 / HZ, - s->protinfo.rose->t2 / HZ, - s->protinfo.rose->t3 / HZ, - s->protinfo.rose->hb / HZ, - ax25_display_timer(&s->protinfo.rose->idletimer) / (60 * HZ), - s->protinfo.rose->idle / (60 * HZ), + rose->lci & 0x0FFF, + (rose->neighbour) ? rose->neighbour->number : 0, + rose->state, + rose->vs, + rose->vr, + rose->va, + ax25_display_timer(&rose->timer) / HZ, + rose->t1 / HZ, + rose->t2 / HZ, + rose->t3 / HZ, + rose->hb / HZ, + ax25_display_timer(&rose->idletimer) / (60 * HZ), + rose->idle / (60 * HZ), atomic_read(&s->wmem_alloc), atomic_read(&s->rmem_alloc), s->socket != NULL ? s->socket->inode->i_ino : 0L); Index: kernel-acme/net/rose/rose_in.c diff -u kernel-acme/net/rose/rose_in.c:1.1.1.1 kernel-acme/net/rose/rose_in.c:1.1.1.1.12.1 --- kernel-acme/net/rose/rose_in.c:1.1.1.1 Tue Jun 26 17:29:25 2001 +++ kernel-acme/net/rose/rose_in.c Tue Dec 11 00:26:47 2001 @@ -52,17 +52,19 @@ */ static int rose_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) { + rose_cb *rose = ROSE_SK(sk); + switch (frametype) { case ROSE_CALL_ACCEPTED: rose_stop_timer(sk); rose_start_idletimer(sk); - sk->protinfo.rose->condition = 0x00; - sk->protinfo.rose->vs = 0; - sk->protinfo.rose->va = 0; - sk->protinfo.rose->vr = 0; - sk->protinfo.rose->vl = 0; - sk->protinfo.rose->state = ROSE_STATE_3; + rose->condition = 0x00; + rose->vs = 0; + rose->va = 0; + rose->vr = 0; + rose->vl = 0; + rose->state = ROSE_STATE_3; sk->state = TCP_ESTABLISHED; if (!sk->dead) sk->state_change(sk); @@ -71,7 +73,7 @@ case ROSE_CLEAR_REQUEST: rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); rose_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]); - sk->protinfo.rose->neighbour->use--; + rose->neighbour->use--; break; default: @@ -88,17 +90,19 @@ */ static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int frametype) { + rose_cb *rose = ROSE_SK(sk); + switch (frametype) { case ROSE_CLEAR_REQUEST: rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); rose_disconnect(sk, 0, skb->data[3], skb->data[4]); - sk->protinfo.rose->neighbour->use--; + rose->neighbour->use--; break; case ROSE_CLEAR_CONFIRMATION: rose_disconnect(sk, 0, -1, -1); - sk->protinfo.rose->neighbour->use--; + rose->neighbour->use--; break; default: @@ -115,6 +119,7 @@ */ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype, int ns, int nr, int q, int d, int m) { + rose_cb *rose = ROSE_SK(sk); int queued = 0; switch (frametype) { @@ -123,88 +128,88 @@ rose_stop_timer(sk); rose_start_idletimer(sk); rose_write_internal(sk, ROSE_RESET_CONFIRMATION); - sk->protinfo.rose->condition = 0x00; - sk->protinfo.rose->vs = 0; - sk->protinfo.rose->vr = 0; - sk->protinfo.rose->va = 0; - sk->protinfo.rose->vl = 0; + rose->condition = 0x00; + rose->vs = 0; + rose->vr = 0; + rose->va = 0; + rose->vl = 0; rose_requeue_frames(sk); break; case ROSE_CLEAR_REQUEST: rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); rose_disconnect(sk, 0, skb->data[3], skb->data[4]); - sk->protinfo.rose->neighbour->use--; + rose->neighbour->use--; break; case ROSE_RR: case ROSE_RNR: if (!rose_validate_nr(sk, nr)) { rose_write_internal(sk, ROSE_RESET_REQUEST); - sk->protinfo.rose->condition = 0x00; - sk->protinfo.rose->vs = 0; - sk->protinfo.rose->vr = 0; - sk->protinfo.rose->va = 0; - sk->protinfo.rose->vl = 0; - sk->protinfo.rose->state = ROSE_STATE_4; + rose->condition = 0x00; + rose->vs = 0; + rose->vr = 0; + rose->va = 0; + rose->vl = 0; + rose->state = ROSE_STATE_4; rose_start_t2timer(sk); rose_stop_idletimer(sk); } else { rose_frames_acked(sk, nr); if (frametype == ROSE_RNR) { - sk->protinfo.rose->condition |= ROSE_COND_PEER_RX_BUSY; + rose->condition |= ROSE_COND_PEER_RX_BUSY; } else { - sk->protinfo.rose->condition &= ~ROSE_COND_PEER_RX_BUSY; + rose->condition &= ~ROSE_COND_PEER_RX_BUSY; } } break; case ROSE_DATA: /* XXX */ - sk->protinfo.rose->condition &= ~ROSE_COND_PEER_RX_BUSY; + rose->condition &= ~ROSE_COND_PEER_RX_BUSY; if (!rose_validate_nr(sk, nr)) { rose_write_internal(sk, ROSE_RESET_REQUEST); - sk->protinfo.rose->condition = 0x00; - sk->protinfo.rose->vs = 0; - sk->protinfo.rose->vr = 0; - sk->protinfo.rose->va = 0; - sk->protinfo.rose->vl = 0; - sk->protinfo.rose->state = ROSE_STATE_4; + rose->condition = 0x00; + rose->vs = 0; + rose->vr = 0; + rose->va = 0; + rose->vl = 0; + rose->state = ROSE_STATE_4; rose_start_t2timer(sk); rose_stop_idletimer(sk); break; } rose_frames_acked(sk, nr); - if (ns == sk->protinfo.rose->vr) { + if (ns == rose->vr) { rose_start_idletimer(sk); if (sock_queue_rcv_skb(sk, skb) == 0) { - sk->protinfo.rose->vr = (sk->protinfo.rose->vr + 1) % ROSE_MODULUS; + rose->vr = (rose->vr + 1) % ROSE_MODULUS; queued = 1; } else { /* Should never happen ! */ rose_write_internal(sk, ROSE_RESET_REQUEST); - sk->protinfo.rose->condition = 0x00; - sk->protinfo.rose->vs = 0; - sk->protinfo.rose->vr = 0; - sk->protinfo.rose->va = 0; - sk->protinfo.rose->vl = 0; - sk->protinfo.rose->state = ROSE_STATE_4; + rose->condition = 0x00; + rose->vs = 0; + rose->vr = 0; + rose->va = 0; + rose->vl = 0; + rose->state = ROSE_STATE_4; rose_start_t2timer(sk); rose_stop_idletimer(sk); break; } if (atomic_read(&sk->rmem_alloc) > (sk->rcvbuf / 2)) - sk->protinfo.rose->condition |= ROSE_COND_OWN_RX_BUSY; + rose->condition |= ROSE_COND_OWN_RX_BUSY; } /* * If the window is full, ack the frame, else start the * acknowledge hold back timer. */ - if (((sk->protinfo.rose->vl + sysctl_rose_window_size) % ROSE_MODULUS) == sk->protinfo.rose->vr) { - sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; + if (((rose->vl + sysctl_rose_window_size) % ROSE_MODULUS) == rose->vr) { + rose->condition &= ~ROSE_COND_ACK_PENDING; rose_stop_timer(sk); rose_enquiry_response(sk); } else { - sk->protinfo.rose->condition |= ROSE_COND_ACK_PENDING; + rose->condition |= ROSE_COND_ACK_PENDING; rose_start_hbtimer(sk); } break; @@ -224,6 +229,8 @@ */ static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int frametype) { + rose_cb *rose = ROSE_SK(sk); + switch (frametype) { case ROSE_RESET_REQUEST: @@ -231,19 +238,19 @@ case ROSE_RESET_CONFIRMATION: rose_stop_timer(sk); rose_start_idletimer(sk); - sk->protinfo.rose->condition = 0x00; - sk->protinfo.rose->va = 0; - sk->protinfo.rose->vr = 0; - sk->protinfo.rose->vs = 0; - sk->protinfo.rose->vl = 0; - sk->protinfo.rose->state = ROSE_STATE_3; + rose->condition = 0x00; + rose->va = 0; + rose->vr = 0; + rose->vs = 0; + rose->vl = 0; + rose->state = ROSE_STATE_3; rose_requeue_frames(sk); break; case ROSE_CLEAR_REQUEST: rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); rose_disconnect(sk, 0, skb->data[3], skb->data[4]); - sk->protinfo.rose->neighbour->use--; + rose->neighbour->use--; break; default: @@ -263,7 +270,7 @@ if (frametype == ROSE_CLEAR_REQUEST) { rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); rose_disconnect(sk, 0, skb->data[3], skb->data[4]); - sk->protinfo.rose->neighbour->use--; + ROSE_SK(sk)->neighbour->use--; } return 0; @@ -274,12 +281,12 @@ { int queued = 0, frametype, ns, nr, q, d, m; - if (sk->protinfo.rose->state == ROSE_STATE_0) + if (ROSE_SK(sk)->state == ROSE_STATE_0) return 0; frametype = rose_decode(skb, &ns, &nr, &q, &d, &m); - switch (sk->protinfo.rose->state) { + switch (ROSE_SK(sk)->state) { case ROSE_STATE_1: queued = rose_state1_machine(sk, skb, frametype); break; Index: kernel-acme/net/rose/rose_out.c diff -u kernel-acme/net/rose/rose_out.c:1.1.1.1 kernel-acme/net/rose/rose_out.c:1.1.1.1.12.1 --- kernel-acme/net/rose/rose_out.c:1.1.1.1 Tue Jun 26 17:29:24 2001 +++ kernel-acme/net/rose/rose_out.c Tue Dec 11 00:26:47 2001 @@ -43,38 +43,41 @@ */ static void rose_send_iframe(struct sock *sk, struct sk_buff *skb) { + rose_cb *rose = ROSE_SK(sk); + if (skb == NULL) return; - skb->data[2] |= (sk->protinfo.rose->vr << 5) & 0xE0; - skb->data[2] |= (sk->protinfo.rose->vs << 1) & 0x0E; + skb->data[2] |= (rose->vr << 5) & 0xE0; + skb->data[2] |= (rose->vs << 1) & 0x0E; rose_start_idletimer(sk); - rose_transmit_link(skb, sk->protinfo.rose->neighbour); + rose_transmit_link(skb, rose->neighbour); } void rose_kick(struct sock *sk) { + rose_cb *rose = ROSE_SK(sk); struct sk_buff *skb, *skbn; unsigned short start, end; - if (sk->protinfo.rose->state != ROSE_STATE_3) + if (rose->state != ROSE_STATE_3) return; - if (sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY) + if (rose->condition & ROSE_COND_PEER_RX_BUSY) return; if (skb_peek(&sk->write_queue) == NULL) return; - start = (skb_peek(&sk->protinfo.rose->ack_queue) == NULL) ? sk->protinfo.rose->va : sk->protinfo.rose->vs; - end = (sk->protinfo.rose->va + sysctl_rose_window_size) % ROSE_MODULUS; + start = (skb_peek(&rose->ack_queue) == NULL) ? rose->va : rose->vs; + end = (rose->va + sysctl_rose_window_size) % ROSE_MODULUS; if (start == end) return; - sk->protinfo.rose->vs = start; + rose->vs = start; /* * Transmit data until either we're out of data to send or @@ -96,17 +99,17 @@ */ rose_send_iframe(sk, skbn); - sk->protinfo.rose->vs = (sk->protinfo.rose->vs + 1) % ROSE_MODULUS; + rose->vs = (rose->vs + 1) % ROSE_MODULUS; /* * Requeue the original data frame. */ - skb_queue_tail(&sk->protinfo.rose->ack_queue, skb); + skb_queue_tail(&rose->ack_queue, skb); - } while (sk->protinfo.rose->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL); + } while (rose->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL); - sk->protinfo.rose->vl = sk->protinfo.rose->vr; - sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; + rose->vl = rose->vr; + rose->condition &= ~ROSE_COND_ACK_PENDING; rose_stop_timer(sk); } @@ -118,13 +121,15 @@ void rose_enquiry_response(struct sock *sk) { - if (sk->protinfo.rose->condition & ROSE_COND_OWN_RX_BUSY) + rose_cb *rose = ROSE_SK(sk); + + if (rose->condition & ROSE_COND_OWN_RX_BUSY) rose_write_internal(sk, ROSE_RNR); else rose_write_internal(sk, ROSE_RR); - sk->protinfo.rose->vl = sk->protinfo.rose->vr; - sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; + rose->vl = rose->vr; + rose->condition &= ~ROSE_COND_ACK_PENDING; rose_stop_timer(sk); } Index: kernel-acme/net/rose/rose_route.c diff -u kernel-acme/net/rose/rose_route.c:1.1.1.2 kernel-acme/net/rose/rose_route.c:1.1.1.2.10.2 --- kernel-acme/net/rose/rose_route.c:1.1.1.2 Thu Aug 16 18:44:19 2001 +++ kernel-acme/net/rose/rose_route.c Mon Dec 17 15:04:53 2001 @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -810,14 +811,15 @@ */ if ((sk = rose_find_socket(lci, rose_neigh)) != NULL) { if (frametype == ROSE_CALL_REQUEST) { + rose_cb *rose = ROSE_SK(sk); /* Remove an existing unused socket */ rose_clear_queues(sk); - sk->protinfo.rose->cause = ROSE_NETWORK_CONGESTION; - sk->protinfo.rose->diagnostic = 0; - sk->protinfo.rose->neighbour->use--; - sk->protinfo.rose->neighbour = NULL; - sk->protinfo.rose->lci = 0; - sk->protinfo.rose->state = ROSE_STATE_0; + rose->cause = ROSE_NETWORK_CONGESTION; + rose->diagnostic = 0; + rose->neighbour->use--; + rose->neighbour = NULL; + rose->lci = 0; + rose->state = ROSE_STATE_0; sk->state = TCP_CLOSE; sk->err = 0; sk->shutdown |= SEND_SHUTDOWN; Index: kernel-acme/net/rose/rose_subr.c diff -u kernel-acme/net/rose/rose_subr.c:1.1.1.2 kernel-acme/net/rose/rose_subr.c:1.1.1.2.10.2 --- kernel-acme/net/rose/rose_subr.c:1.1.1.2 Thu Aug 16 18:44:19 2001 +++ kernel-acme/net/rose/rose_subr.c Mon Dec 17 15:04:53 2001 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +44,7 @@ void rose_clear_queues(struct sock *sk) { skb_queue_purge(&sk->write_queue); - skb_queue_purge(&sk->protinfo.rose->ack_queue); + skb_queue_purge(&ROSE_SK(sk)->ack_queue); } /* @@ -54,15 +55,16 @@ void rose_frames_acked(struct sock *sk, unsigned short nr) { struct sk_buff *skb; + rose_cb *rose = ROSE_SK(sk); /* * Remove all the ack-ed frames from the ack queue. */ - if (sk->protinfo.rose->va != nr) { - while (skb_peek(&sk->protinfo.rose->ack_queue) != NULL && sk->protinfo.rose->va != nr) { - skb = skb_dequeue(&sk->protinfo.rose->ack_queue); + if (rose->va != nr) { + while (skb_peek(&rose->ack_queue) != NULL && rose->va != nr) { + skb = skb_dequeue(&rose->ack_queue); kfree_skb(skb); - sk->protinfo.rose->va = (sk->protinfo.rose->va + 1) % ROSE_MODULUS; + rose->va = (rose->va + 1) % ROSE_MODULUS; } } } @@ -76,7 +78,7 @@ * up by rose_kick. This arrangement handles the possibility of an * empty output queue. */ - while ((skb = skb_dequeue(&sk->protinfo.rose->ack_queue)) != NULL) { + while ((skb = skb_dequeue(&ROSE_SK(sk)->ack_queue)) != NULL) { if (skb_prev == NULL) skb_queue_head(&sk->write_queue, skb); else @@ -91,16 +93,15 @@ */ int rose_validate_nr(struct sock *sk, unsigned short nr) { - unsigned short vc = sk->protinfo.rose->va; + rose_cb *rose = ROSE_SK(sk); + unsigned short vc = rose->va; - while (vc != sk->protinfo.rose->vs) { + while (vc != rose->vs) { if (nr == vc) return 1; vc = (vc + 1) % ROSE_MODULUS; } - if (nr == sk->protinfo.rose->vs) return 1; - - return 0; + return nr == rose->vs; } /* @@ -109,6 +110,7 @@ */ void rose_write_internal(struct sock *sk, int frametype) { + rose_cb *rose = ROSE_SK(sk); struct sk_buff *skb; unsigned char *dptr; unsigned char lci1, lci2; @@ -120,7 +122,7 @@ switch (frametype) { case ROSE_CALL_REQUEST: len += 1 + ROSE_ADDR_LEN + ROSE_ADDR_LEN; - faclen = rose_create_facilities(buffer, sk->protinfo.rose); + faclen = rose_create_facilities(buffer, rose); len += faclen; break; case ROSE_CALL_ACCEPTED: @@ -140,8 +142,8 @@ dptr = skb_put(skb, skb_tailroom(skb)); - lci1 = (sk->protinfo.rose->lci >> 8) & 0x0F; - lci2 = (sk->protinfo.rose->lci >> 0) & 0xFF; + lci1 = (rose->lci >> 8) & 0x0F; + lci2 = (rose->lci >> 0) & 0xFF; switch (frametype) { @@ -150,9 +152,9 @@ *dptr++ = lci2; *dptr++ = frametype; *dptr++ = 0xAA; - memcpy(dptr, &sk->protinfo.rose->dest_addr, ROSE_ADDR_LEN); + memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN); dptr += ROSE_ADDR_LEN; - memcpy(dptr, &sk->protinfo.rose->source_addr, ROSE_ADDR_LEN); + memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN); dptr += ROSE_ADDR_LEN; memcpy(dptr, buffer, faclen); dptr += faclen; @@ -170,8 +172,8 @@ *dptr++ = ROSE_GFI | lci1; *dptr++ = lci2; *dptr++ = frametype; - *dptr++ = sk->protinfo.rose->cause; - *dptr++ = sk->protinfo.rose->diagnostic; + *dptr++ = rose->cause; + *dptr++ = rose->diagnostic; break; case ROSE_RESET_REQUEST: @@ -187,7 +189,7 @@ *dptr++ = ROSE_GFI | lci1; *dptr++ = lci2; *dptr = frametype; - *dptr++ |= (sk->protinfo.rose->vr << 5) & 0xE0; + *dptr++ |= (rose->vr << 5) & 0xE0; break; case ROSE_CLEAR_CONFIRMATION: @@ -203,7 +205,7 @@ return; } - rose_transmit_link(skb, sk->protinfo.rose->neighbour); + rose_transmit_link(skb, rose->neighbour); } int rose_decode(struct sk_buff *skb, int *ns, int *nr, int *q, int *d, int *m) @@ -498,19 +500,21 @@ void rose_disconnect(struct sock *sk, int reason, int cause, int diagnostic) { + rose_cb *rose = ROSE_SK(sk); + rose_stop_timer(sk); rose_stop_idletimer(sk); rose_clear_queues(sk); - sk->protinfo.rose->lci = 0; - sk->protinfo.rose->state = ROSE_STATE_0; + rose->lci = 0; + rose->state = ROSE_STATE_0; if (cause != -1) - sk->protinfo.rose->cause = cause; + rose->cause = cause; if (diagnostic != -1) - sk->protinfo.rose->diagnostic = diagnostic; + rose->diagnostic = diagnostic; sk->state = TCP_CLOSE; sk->err = reason; Index: kernel-acme/net/rose/rose_timer.c diff -u kernel-acme/net/rose/rose_timer.c:1.1.1.1 kernel-acme/net/rose/rose_timer.c:1.1.1.1.12.2 --- kernel-acme/net/rose/rose_timer.c:1.1.1.1 Tue Jun 26 17:29:26 2001 +++ kernel-acme/net/rose/rose_timer.c Mon Dec 17 15:04:53 2001 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -54,58 +55,68 @@ void rose_start_t1timer(struct sock *sk) { - del_timer(&sk->protinfo.rose->timer); + rose_cb *rose = ROSE_SK(sk); - sk->protinfo.rose->timer.data = (unsigned long)sk; - sk->protinfo.rose->timer.function = &rose_timer_expiry; - sk->protinfo.rose->timer.expires = jiffies + sk->protinfo.rose->t1; + del_timer(&rose->timer); - add_timer(&sk->protinfo.rose->timer); + rose->timer.data = (unsigned long)sk; + rose->timer.function = &rose_timer_expiry; + rose->timer.expires = jiffies + rose->t1; + + add_timer(&rose->timer); } void rose_start_t2timer(struct sock *sk) { - del_timer(&sk->protinfo.rose->timer); + rose_cb *rose = ROSE_SK(sk); + + del_timer(&rose->timer); - sk->protinfo.rose->timer.data = (unsigned long)sk; - sk->protinfo.rose->timer.function = &rose_timer_expiry; - sk->protinfo.rose->timer.expires = jiffies + sk->protinfo.rose->t2; + rose->timer.data = (unsigned long)sk; + rose->timer.function = &rose_timer_expiry; + rose->timer.expires = jiffies + rose->t2; - add_timer(&sk->protinfo.rose->timer); + add_timer(&rose->timer); } void rose_start_t3timer(struct sock *sk) { - del_timer(&sk->protinfo.rose->timer); + rose_cb *rose = ROSE_SK(sk); + + del_timer(&rose->timer); - sk->protinfo.rose->timer.data = (unsigned long)sk; - sk->protinfo.rose->timer.function = &rose_timer_expiry; - sk->protinfo.rose->timer.expires = jiffies + sk->protinfo.rose->t3; + rose->timer.data = (unsigned long)sk; + rose->timer.function = &rose_timer_expiry; + rose->timer.expires = jiffies + rose->t3; - add_timer(&sk->protinfo.rose->timer); + add_timer(&rose->timer); } void rose_start_hbtimer(struct sock *sk) { - del_timer(&sk->protinfo.rose->timer); + rose_cb *rose = ROSE_SK(sk); - sk->protinfo.rose->timer.data = (unsigned long)sk; - sk->protinfo.rose->timer.function = &rose_timer_expiry; - sk->protinfo.rose->timer.expires = jiffies + sk->protinfo.rose->hb; + del_timer(&rose->timer); - add_timer(&sk->protinfo.rose->timer); + rose->timer.data = (unsigned long)sk; + rose->timer.function = &rose_timer_expiry; + rose->timer.expires = jiffies + rose->hb; + + add_timer(&rose->timer); } void rose_start_idletimer(struct sock *sk) { - del_timer(&sk->protinfo.rose->idletimer); + rose_cb *rose = ROSE_SK(sk); + + del_timer(&rose->idletimer); - if (sk->protinfo.rose->idle > 0) { - sk->protinfo.rose->idletimer.data = (unsigned long)sk; - sk->protinfo.rose->idletimer.function = &rose_idletimer_expiry; - sk->protinfo.rose->idletimer.expires = jiffies + sk->protinfo.rose->idle; + if (rose->idle > 0) { + rose->idletimer.data = (unsigned long)sk; + rose->idletimer.function = &rose_idletimer_expiry; + rose->idletimer.expires = jiffies + rose->idle; - add_timer(&sk->protinfo.rose->idletimer); + add_timer(&rose->idletimer); } } @@ -116,19 +127,20 @@ void rose_stop_timer(struct sock *sk) { - del_timer(&sk->protinfo.rose->timer); + del_timer(&ROSE_SK(sk)->timer); } void rose_stop_idletimer(struct sock *sk) { - del_timer(&sk->protinfo.rose->idletimer); + del_timer(&ROSE_SK(sk)->idletimer); } static void rose_heartbeat_expiry(unsigned long param) { struct sock *sk = (struct sock *)param; + rose_cb *rose = ROSE_SK(sk); - switch (sk->protinfo.rose->state) { + switch (rose->state) { case ROSE_STATE_0: /* Magic here: If we listen() and a new link dies before it @@ -144,10 +156,10 @@ * Check for the state of the receive buffer. */ if (atomic_read(&sk->rmem_alloc) < (sk->rcvbuf / 2) && - (sk->protinfo.rose->condition & ROSE_COND_OWN_RX_BUSY)) { - sk->protinfo.rose->condition &= ~ROSE_COND_OWN_RX_BUSY; - sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; - sk->protinfo.rose->vl = sk->protinfo.rose->vr; + (rose->condition & ROSE_COND_OWN_RX_BUSY)) { + rose->condition &= ~ROSE_COND_OWN_RX_BUSY; + rose->condition &= ~ROSE_COND_ACK_PENDING; + rose->vl = rose->vr; rose_write_internal(sk, ROSE_RR); rose_stop_timer(sk); /* HB */ break; @@ -161,24 +173,25 @@ static void rose_timer_expiry(unsigned long param) { struct sock *sk = (struct sock *)param; + rose_cb *rose = ROSE_SK(sk); - switch (sk->protinfo.rose->state) { + switch (rose->state) { case ROSE_STATE_1: /* T1 */ case ROSE_STATE_4: /* T2 */ rose_write_internal(sk, ROSE_CLEAR_REQUEST); - sk->protinfo.rose->state = ROSE_STATE_2; + rose->state = ROSE_STATE_2; rose_start_t3timer(sk); break; case ROSE_STATE_2: /* T3 */ - sk->protinfo.rose->neighbour->use--; + rose->neighbour->use--; rose_disconnect(sk, ETIMEDOUT, -1, -1); break; case ROSE_STATE_3: /* HB */ - if (sk->protinfo.rose->condition & ROSE_COND_ACK_PENDING) { - sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; + if (rose->condition & ROSE_COND_ACK_PENDING) { + rose->condition &= ~ROSE_COND_ACK_PENDING; rose_enquiry_response(sk); } break; @@ -192,7 +205,7 @@ rose_clear_queues(sk); rose_write_internal(sk, ROSE_CLEAR_REQUEST); - sk->protinfo.rose->state = ROSE_STATE_2; + ROSE_SK(sk)->state = ROSE_STATE_2; rose_start_t3timer(sk); Index: kernel-acme/net/unix/af_unix.c diff -u kernel-acme/net/unix/af_unix.c:1.1.1.7 kernel-acme/net/unix/af_unix.c:1.1.1.7.6.3 --- kernel-acme/net/unix/af_unix.c:1.1.1.7 Tue Nov 6 21:30:46 2001 +++ kernel-acme/net/unix/af_unix.c Fri Dec 21 02:12:17 2001 @@ -8,7 +8,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Version: $Id: af_unix.c,v 1.1.1.7 2001/11/06 21:30:46 acme Exp $ + * Version: $Id: af_unix.c,v 1.1.1.7.6.3 2001/12/21 02:12:17 acme Exp $ * * Fixes: * Linus Torvalds : Assorted bug cures. @@ -113,13 +113,15 @@ int sysctl_unix_max_dgram_qlen = 10; +kmem_cache_t *unix_sk_cachep; + unix_socket *unix_socket_table[UNIX_HASH_SIZE+1]; rwlock_t unix_table_lock = RW_LOCK_UNLOCKED; static atomic_t unix_nr_socks = ATOMIC_INIT(0); #define unix_sockets_unbound (unix_socket_table[UNIX_HASH_SIZE]) -#define UNIX_ABSTRACT(sk) ((sk)->protinfo.af_unix.addr->hash!=UNIX_HASH_SIZE) +#define UNIX_ABSTRACT(sk) (UNIX_SK(sk)->addr->hash!=UNIX_HASH_SIZE) /* * SMP locking strategy: @@ -200,7 +202,7 @@ static void __unix_remove_socket(unix_socket *sk) { - unix_socket **list = sk->protinfo.af_unix.list; + unix_socket **list = UNIX_SK(sk)->list; if (list) { if (sk->next) sk->next->prev = sk->prev; @@ -208,7 +210,7 @@ sk->prev->next = sk->next; if (*list == sk) *list = sk->next; - sk->protinfo.af_unix.list = NULL; + UNIX_SK(sk)->list = NULL; sk->prev = NULL; sk->next = NULL; __sock_put(sk); @@ -217,9 +219,9 @@ static void __unix_insert_socket(unix_socket **list, unix_socket *sk) { - BUG_TRAP(sk->protinfo.af_unix.list==NULL); + BUG_TRAP(UNIX_SK(sk)->list==NULL); - sk->protinfo.af_unix.list = list; + UNIX_SK(sk)->list = list; sk->prev = NULL; sk->next = *list; if (*list) @@ -248,8 +250,8 @@ unix_socket *s; for (s=unix_socket_table[hash^type]; s; s=s->next) { - if(s->protinfo.af_unix.addr->len==len && - memcmp(s->protinfo.af_unix.addr->name, sunname, len) == 0) + if(UNIX_SK(s)->addr->len==len && + memcmp(UNIX_SK(s)->addr->name, sunname, len) == 0) return s; } return NULL; @@ -276,7 +278,7 @@ read_lock(&unix_table_lock); for (s=unix_socket_table[i->i_ino & (UNIX_HASH_SIZE-1)]; s; s=s->next) { - struct dentry *dentry = s->protinfo.af_unix.dentry; + struct dentry *dentry = UNIX_SK(s)->dentry; if(dentry && dentry->d_inode == i) { @@ -312,7 +314,7 @@ { if (skb_queue_len(&sk->receive_queue)) { skb_queue_purge(&sk->receive_queue); - wake_up_interruptible_all(&sk->protinfo.af_unix.peer_wait); + wake_up_interruptible_all(&UNIX_SK(sk)->peer_wait); /* If one link of bidirectional dgram pipe is disconnected, * we signal error. Messages are lost. Do not make this, @@ -330,15 +332,15 @@ skb_queue_purge(&sk->receive_queue); BUG_TRAP(atomic_read(&sk->wmem_alloc) == 0); - BUG_TRAP(sk->protinfo.af_unix.list==NULL); + BUG_TRAP(UNIX_SK(sk)->list==NULL); BUG_TRAP(sk->socket==NULL); if (sk->dead==0) { printk("Attempt to release alive unix socket: %p\n", sk); return; } - if (sk->protinfo.af_unix.addr) - unix_release_addr(sk->protinfo.af_unix.addr); + if (UNIX_SK(sk)->addr) + unix_release_addr(UNIX_SK(sk)->addr); atomic_dec(&unix_nr_socks); #ifdef UNIX_REFCNT_DEBUG @@ -361,15 +363,15 @@ unix_state_wlock(sk); sock_orphan(sk); sk->shutdown = SHUTDOWN_MASK; - dentry = sk->protinfo.af_unix.dentry; - sk->protinfo.af_unix.dentry=NULL; - mnt = sk->protinfo.af_unix.mnt; - sk->protinfo.af_unix.mnt=NULL; + dentry = UNIX_SK(sk)->dentry; + UNIX_SK(sk)->dentry=NULL; + mnt = UNIX_SK(sk)->mnt; + UNIX_SK(sk)->mnt=NULL; state = sk->state; sk->state = TCP_CLOSE; unix_state_wunlock(sk); - wake_up_interruptible_all(&sk->protinfo.af_unix.peer_wait); + wake_up_interruptible_all(&UNIX_SK(sk)->peer_wait); skpair=unix_peer(sk); @@ -434,13 +436,13 @@ if (sock->type!=SOCK_STREAM) goto out; /* Only stream sockets accept */ err = -EINVAL; - if (!sk->protinfo.af_unix.addr) + if (!UNIX_SK(sk)->addr) goto out; /* No listens on an unbound socket */ unix_state_wlock(sk); if (sk->state != TCP_CLOSE && sk->state != TCP_LISTEN) goto out_unlock; if (backlog > sk->max_ack_backlog) - wake_up_interruptible_all(&sk->protinfo.af_unix.peer_wait); + wake_up_interruptible_all(&UNIX_SK(sk)->peer_wait); sk->max_ack_backlog=backlog; sk->state=TCP_LISTEN; /* set credentials so connect can copy them */ @@ -466,7 +468,7 @@ return NULL; MOD_INC_USE_COUNT; - sk = sk_alloc(PF_UNIX, GFP_KERNEL, 1); + sk = sk_alloc(PF_UNIX, GFP_KERNEL, UNIX_SK_SIZE, unix_sk_cachep); if (!sk) { MOD_DEC_USE_COUNT; return NULL; @@ -480,13 +482,13 @@ sk->max_ack_backlog = sysctl_unix_max_dgram_qlen; sk->destruct = unix_sock_destructor; - sk->protinfo.af_unix.dentry=NULL; - sk->protinfo.af_unix.mnt=NULL; - sk->protinfo.af_unix.lock = RW_LOCK_UNLOCKED; - atomic_set(&sk->protinfo.af_unix.inflight, 0); - init_MUTEX(&sk->protinfo.af_unix.readsem);/* single task reading lock */ - init_waitqueue_head(&sk->protinfo.af_unix.peer_wait); - sk->protinfo.af_unix.list=NULL; + UNIX_SK(sk)->dentry=NULL; + UNIX_SK(sk)->mnt=NULL; + UNIX_SK(sk)->lock = RW_LOCK_UNLOCKED; + atomic_set(&UNIX_SK(sk)->inflight, 0); + init_MUTEX(&UNIX_SK(sk)->readsem);/* single task reading lock */ + init_waitqueue_head(&UNIX_SK(sk)->peer_wait); + UNIX_SK(sk)->list=NULL; unix_insert_socket(&unix_sockets_unbound, sk); return sk; @@ -538,10 +540,10 @@ struct unix_address * addr; int err; - down(&sk->protinfo.af_unix.readsem); + down(&UNIX_SK(sk)->readsem); err = 0; - if (sk->protinfo.af_unix.addr) + if (UNIX_SK(sk)->addr) goto out; err = -ENOMEM; @@ -573,13 +575,13 @@ addr->hash ^= sk->type; __unix_remove_socket(sk); - sk->protinfo.af_unix.addr = addr; + UNIX_SK(sk)->addr = addr; __unix_insert_socket(&unix_socket_table[addr->hash], sk); write_unlock(&unix_table_lock); err = 0; out: - up(&sk->protinfo.af_unix.readsem); + up(&UNIX_SK(sk)->readsem); return err; } @@ -655,10 +657,10 @@ goto out; addr_len = err; - down(&sk->protinfo.af_unix.readsem); + down(&UNIX_SK(sk)->readsem); err = -EINVAL; - if (sk->protinfo.af_unix.addr) + if (UNIX_SK(sk)->addr) goto out_up; err = -ENOMEM; @@ -736,19 +738,19 @@ list = &unix_socket_table[addr->hash]; } else { list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)]; - sk->protinfo.af_unix.dentry = nd.dentry; - sk->protinfo.af_unix.mnt = nd.mnt; + UNIX_SK(sk)->dentry = nd.dentry; + UNIX_SK(sk)->mnt = nd.mnt; } err = 0; __unix_remove_socket(sk); - sk->protinfo.af_unix.addr = addr; + UNIX_SK(sk)->addr = addr; __unix_insert_socket(list, sk); out_unlock: write_unlock(&unix_table_lock); out_up: - up(&sk->protinfo.af_unix.readsem); + up(&UNIX_SK(sk)->readsem); out: return err; @@ -780,7 +782,7 @@ goto out; alen = err; - if (sock->passcred && !sk->protinfo.af_unix.addr && + if (sock->passcred && !UNIX_SK(sk)->addr && (err = unix_autobind(sock)) != 0) goto out; @@ -831,7 +833,7 @@ DECLARE_WAITQUEUE(wait, current); __set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue_exclusive(&other->protinfo.af_unix.peer_wait, &wait); + add_wait_queue_exclusive(&UNIX_SK(other)->peer_wait, &wait); sched = (!other->dead && !(other->shutdown&RCV_SHUTDOWN) && @@ -843,7 +845,7 @@ timeo = schedule_timeout(timeo); __set_current_state(TASK_RUNNING); - remove_wait_queue(&other->protinfo.af_unix.peer_wait, &wait); + remove_wait_queue(&UNIX_SK(other)->peer_wait, &wait); return timeo; } @@ -865,7 +867,7 @@ goto out; addr_len = err; - if (sock->passcred && !sk->protinfo.af_unix.addr && + if (sock->passcred && !UNIX_SK(sk)->addr && (err = unix_autobind(sock)) != 0) goto out; @@ -966,17 +968,17 @@ newsk->peercred.pid = current->pid; newsk->peercred.uid = current->euid; newsk->peercred.gid = current->egid; - newsk->sleep = &newsk->protinfo.af_unix.peer_wait; + newsk->sleep = &UNIX_SK(newsk)->peer_wait; /* copy address information from listening to new sock*/ - if (other->protinfo.af_unix.addr) + if (UNIX_SK(other)->addr) { - atomic_inc(&other->protinfo.af_unix.addr->refcnt); - newsk->protinfo.af_unix.addr=other->protinfo.af_unix.addr; + atomic_inc(&UNIX_SK(other)->addr->refcnt); + UNIX_SK(newsk)->addr=UNIX_SK(other)->addr; } - if (other->protinfo.af_unix.dentry) { - newsk->protinfo.af_unix.dentry=dget(other->protinfo.af_unix.dentry); - newsk->protinfo.af_unix.mnt=mntget(other->protinfo.af_unix.mnt); + if (UNIX_SK(other)->dentry) { + UNIX_SK(newsk)->dentry=dget(UNIX_SK(other)->dentry); + UNIX_SK(newsk)->mnt=mntget(UNIX_SK(other)->mnt); } /* Set credentials */ @@ -1058,7 +1060,7 @@ tsk = skb->sk; skb_free_datagram(sk, skb); - wake_up_interruptible(&sk->protinfo.af_unix.peer_wait); + wake_up_interruptible(&UNIX_SK(sk)->peer_wait); /* attach accepted sock to socket */ unix_state_wlock(tsk); @@ -1090,12 +1092,12 @@ } unix_state_rlock(sk); - if (!sk->protinfo.af_unix.addr) { + if (!UNIX_SK(sk)->addr) { sunaddr->sun_family = AF_UNIX; sunaddr->sun_path[0] = 0; *uaddr_len = sizeof(short); } else { - struct unix_address *addr = sk->protinfo.af_unix.addr; + struct unix_address *addr = UNIX_SK(sk)->addr; *uaddr_len = addr->len; memcpy(sunaddr, addr->name, *uaddr_len); @@ -1173,7 +1175,7 @@ goto out; } - if (sock->passcred && !sk->protinfo.af_unix.addr && + if (sock->passcred && !UNIX_SK(sk)->addr && (err = unix_autobind(sock)) != 0) goto out; @@ -1376,11 +1378,11 @@ static void unix_copy_addr(struct msghdr *msg, struct sock *sk) { msg->msg_namelen = sizeof(short); - if (sk->protinfo.af_unix.addr) { - msg->msg_namelen=sk->protinfo.af_unix.addr->len; + if (UNIX_SK(sk)->addr) { + msg->msg_namelen=UNIX_SK(sk)->addr->len; memcpy(msg->msg_name, - sk->protinfo.af_unix.addr->name, - sk->protinfo.af_unix.addr->len); + UNIX_SK(sk)->addr->name, + UNIX_SK(sk)->addr->len); } } @@ -1402,7 +1404,7 @@ if (!skb) goto out; - wake_up_interruptible(&sk->protinfo.af_unix.peer_wait); + wake_up_interruptible(&UNIX_SK(sk)->peer_wait); if (msg->msg_name) unix_copy_addr(msg, skb->sk); @@ -1513,7 +1515,7 @@ * while sleeps in memcpy_tomsg */ - down(&sk->protinfo.af_unix.readsem); + down(&UNIX_SK(sk)->readsem); do { @@ -1537,7 +1539,7 @@ err = -EAGAIN; if (!timeo) break; - up(&sk->protinfo.af_unix.readsem); + up(&UNIX_SK(sk)->readsem); timeo = unix_stream_data_wait(sk, timeo); @@ -1545,7 +1547,7 @@ err = sock_intr_errno(timeo); goto out; } - down(&sk->protinfo.af_unix.readsem); + down(&UNIX_SK(sk)->readsem); continue; } @@ -1611,7 +1613,7 @@ } } while (size); - up(&sk->protinfo.af_unix.readsem); + up(&UNIX_SK(sk)->readsem); out: return copied ? : err; } @@ -1753,16 +1755,16 @@ (s->state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING), sock_i_ino(s)); - if (s->protinfo.af_unix.addr) + if (UNIX_SK(s)->addr) { buffer[len++] = ' '; - memcpy(buffer+len, s->protinfo.af_unix.addr->name->sun_path, - s->protinfo.af_unix.addr->len-sizeof(short)); + memcpy(buffer+len, UNIX_SK(s)->addr->name->sun_path, + UNIX_SK(s)->addr->len-sizeof(short)); if (!UNIX_ABSTRACT(s)) len--; else buffer[len] = '@'; - len += s->protinfo.af_unix.addr->len - sizeof(short); + len += UNIX_SK(s)->addr->len - sizeof(short); } unix_state_runlock(s); @@ -1833,8 +1835,8 @@ }; struct net_proto_family unix_family_ops = { - family: PF_UNIX, - create: unix_create + family: PF_UNIX, + create: unix_create, }; #ifdef CONFIG_SYSCTL @@ -1857,6 +1859,13 @@ printk(KERN_CRIT "unix_proto_init: panic\n"); return -1; } + /* allocate our sock slab cache */ + unix_sk_cachep = kmem_cache_create("unix_sock", UNIX_SK_SIZE, 0, + SLAB_HWCACHE_ALIGN, 0, 0); + if (!unix_sk_cachep) + printk(KERN_CRIT __FUNCTION__ + ": Cannot create unix_sock SLAB cache!\n"); + sock_register(&unix_family_ops); #ifdef CONFIG_PROC_FS create_proc_read_entry("net/unix", 0, 0, unix_read_proc, NULL); @@ -1870,6 +1879,7 @@ sock_unregister(PF_UNIX); unix_sysctl_unregister(); remove_proc_entry("net/unix", 0); + kmem_cache_destroy(unix_sk_cachep); } module_init(af_unix_init); Index: kernel-acme/net/unix/garbage.c diff -u kernel-acme/net/unix/garbage.c:1.1.1.2 kernel-acme/net/unix/garbage.c:1.1.1.2.10.1 --- kernel-acme/net/unix/garbage.c:1.1.1.2 Thu Aug 16 18:44:21 2001 +++ kernel-acme/net/unix/garbage.c Mon Dec 17 15:04:53 2001 @@ -122,7 +122,7 @@ { unix_socket *s=unix_get_socket(fp); if(s) { - atomic_inc(&s->protinfo.af_unix.inflight); + atomic_inc(&UNIX_SK(s)->inflight); atomic_inc(&unix_tot_inflight); } } @@ -131,7 +131,7 @@ { unix_socket *s=unix_get_socket(fp); if(s) { - atomic_dec(&s->protinfo.af_unix.inflight); + atomic_dec(&UNIX_SK(s)->inflight); atomic_dec(&unix_tot_inflight); } } @@ -144,7 +144,7 @@ extern inline unix_socket *pop_stack(void) { unix_socket *p=gc_current; - gc_current = p->protinfo.af_unix.gc_tree; + gc_current = UNIX_SK(p)->gc_tree; return p; } @@ -155,10 +155,10 @@ extern inline void maybe_unmark_and_push(unix_socket *x) { - if (x->protinfo.af_unix.gc_tree != GC_ORPHAN) + if (UNIX_SK(x)->gc_tree != GC_ORPHAN) return; sock_hold(x); - x->protinfo.af_unix.gc_tree = gc_current; + UNIX_SK(x)->gc_tree = gc_current; gc_current = x; } @@ -184,7 +184,7 @@ forall_unix_sockets(i, s) { - s->protinfo.af_unix.gc_tree=GC_ORPHAN; + UNIX_SK(s)->gc_tree=GC_ORPHAN; } /* * Everything is now marked @@ -210,7 +210,7 @@ * in flight we are in use. */ if(s->socket && s->socket->file && - file_count(s->socket->file) > atomic_read(&s->protinfo.af_unix.inflight)) + file_count(s->socket->file) > atomic_read(&UNIX_SK(s)->inflight)) maybe_unmark_and_push(s); } @@ -268,7 +268,7 @@ forall_unix_sockets(i, s) { - if (s->protinfo.af_unix.gc_tree == GC_ORPHAN) + if (UNIX_SK(s)->gc_tree == GC_ORPHAN) { struct sk_buff *nextsk; spin_lock(&s->receive_queue.lock); @@ -288,7 +288,7 @@ } spin_unlock(&s->receive_queue.lock); } - s->protinfo.af_unix.gc_tree = GC_ORPHAN; + UNIX_SK(s)->gc_tree = GC_ORPHAN; } read_unlock(&unix_table_lock); Index: kernel-acme/net/wanrouter/af_wanpipe.c diff -u kernel-acme/net/wanrouter/af_wanpipe.c:1.1.1.3 kernel-acme/net/wanrouter/af_wanpipe.c:1.1.1.3.6.3 --- kernel-acme/net/wanrouter/af_wanpipe.c:1.1.1.3 Tue Nov 6 18:55:18 2001 +++ kernel-acme/net/wanrouter/af_wanpipe.c Fri Dec 21 02:12:17 2001 @@ -326,7 +326,7 @@ static int wanpipe_listen_rcv (struct sk_buff *skb, struct sock *sk) { - + wanpipe_opt *wp = WP_SK(sk), *newwp; struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)skb->cb; struct sock *newsk; netdevice_t *dev; @@ -337,7 +337,7 @@ /* Find a free device, if none found, all svc's are busy */ - card = (sdla_t*)sk->protinfo.af_wanpipe->card; + card = (sdla_t*)wp->card; if (!card){ printk(KERN_INFO "wansock: LISTEN ERROR, No Card\n"); return -ENODEV; @@ -364,7 +364,8 @@ /* Initialize the new sock structure */ newsk->bound_dev_if = dev->ifindex; - newsk->protinfo.af_wanpipe->card = sk->protinfo.af_wanpipe->card; + newwp = WP_SK(newsk); + newwp->card = wp->card; /* Insert the sock into the main wanpipe * sock list. @@ -389,8 +390,8 @@ * whic lcn to clear */ - newsk->protinfo.af_wanpipe->lcn = mbox_ptr->cmd.lcn; - newsk->protinfo.af_wanpipe->mbox = (void *)mbox_ptr; + newwp->lcn = mbox_ptr->cmd.lcn; + newwp->mbox = (void *)mbox_ptr; DBG_PRINTK(KERN_INFO "NEWSOCK : Device %s, bind to lcn %i\n", dev->name,mbox_ptr->cmd.lcn); @@ -497,7 +498,7 @@ struct sock *sk; struct wanpipe_opt *wan_opt; - if ((sk = sk_alloc(PF_WANPIPE, GFP_ATOMIC, 1)) == NULL) + if ((sk = sk_alloc(PF_WANPIPE, GFP_ATOMIC, 1, NULL)) == NULL) return NULL; if ((wan_opt = kmalloc(sizeof(struct wanpipe_opt), GFP_ATOMIC)) == NULL) { @@ -506,13 +507,12 @@ } memset(wan_opt, 0x00, sizeof(struct wanpipe_opt)); - sk->protinfo.af_wanpipe = wan_opt; - sk->protinfo.destruct_hook = wan_opt; + WP_SK(sk) = wan_opt; /* Use timer to send data to the driver. This will act * as a BH handler for sendmsg functions */ - sk->protinfo.af_wanpipe->tx_timer.data=(unsigned long)sk; - sk->protinfo.af_wanpipe->tx_timer.function=wanpipe_delayed_transmit; + wan_opt->tx_timer.data = (unsigned long)sk; + wan_opt->tx_timer.function = wanpipe_delayed_transmit; MOD_INC_USE_COUNT; @@ -542,6 +542,7 @@ static int wanpipe_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) { + wanpipe_opt *wp; struct sock *sk = sock->sk; struct wan_sockaddr_ll *saddr=(struct wan_sockaddr_ll *)msg->msg_name; struct sk_buff *skb; @@ -647,12 +648,13 @@ } skb_queue_tail(&sk->write_queue,skb); - atomic_inc(&sk->protinfo.af_wanpipe->packet_sent); + wp = WP_SK(sk); + atomic_inc(&wp->packet_sent); - if (!(test_and_set_bit(0,&sk->protinfo.af_wanpipe->timer))){ - del_timer(&sk->protinfo.af_wanpipe->tx_timer); - sk->protinfo.af_wanpipe->tx_timer.expires=jiffies+1; - add_timer(&sk->protinfo.af_wanpipe->tx_timer); + if (!(test_and_set_bit(0, &wp->timer))){ + del_timer(&wp->tx_timer); + wp->tx_timer.expires = jiffies + 1; + add_timer(&wp->tx_timer); } return(len); @@ -683,17 +685,18 @@ { struct sock *sk=(struct sock *)data; struct sk_buff *skb; - netdevice_t *dev = sk->protinfo.af_wanpipe->dev; - sdla_t *card = (sdla_t*)sk->protinfo.af_wanpipe->card; + wanpipe_opt *wp = WP_SK(sk); + netdevice_t *dev = wp->dev; + sdla_t *card = (sdla_t*)wp->card; if (!card || !dev){ - clear_bit (0,&sk->protinfo.af_wanpipe->timer); + clear_bit(0, &wp->timer); DBG_PRINTK(KERN_INFO "wansock: Transmit delay, no dev or card\n"); return; } if (sk->state != WANSOCK_CONNECTED || !sk->zapped){ - clear_bit (0,&sk->protinfo.af_wanpipe->timer); + clear_bit(0, &wp->timer); DBG_PRINTK(KERN_INFO "wansock: Tx Timer, State not CONNECTED\n"); return; } @@ -703,8 +706,8 @@ * pending command will never get a free buffer * to execute */ if (atomic_read(&card->u.x.command_busy)){ - sk->protinfo.af_wanpipe->tx_timer.expires=jiffies+SLOW_BACKOFF; - add_timer(&sk->protinfo.af_wanpipe->tx_timer); + wp->tx_timer.expires = jiffies + SLOW_BACKOFF; + add_timer(&wp->tx_timer); DBG_PRINTK(KERN_INFO "wansock: Tx Timer, command bys BACKOFF\n"); return; } @@ -712,8 +715,8 @@ if (test_and_set_bit(0,&wanpipe_tx_critical)){ printk(KERN_INFO "WanSock: Tx timer critical %s\n",dev->name); - sk->protinfo.af_wanpipe->tx_timer.expires=jiffies+SLOW_BACKOFF; - add_timer(&sk->protinfo.af_wanpipe->tx_timer); + wp->tx_timer.expires = jiffies + SLOW_BACKOFF; + add_timer(&wp->tx_timer); return; } @@ -733,18 +736,18 @@ * if more packets, re-trigger the transmit routine * other wise exit */ - atomic_dec(&sk->protinfo.af_wanpipe->packet_sent); + atomic_dec(&wp->packet_sent); if (skb_peek(&sk->write_queue) == NULL){ /* If there is nothing to send, kick * the poll routine, which will trigger * the application to send more data */ sk->data_ready(sk,0); - clear_bit (0,&sk->protinfo.af_wanpipe->timer); + clear_bit(0, &wp->timer); }else{ /* Reschedule as fast as possible */ - sk->protinfo.af_wanpipe->tx_timer.expires=jiffies+1; - add_timer(&sk->protinfo.af_wanpipe->tx_timer); + wp->tx_timer.expires = jiffies + 1; + add_timer(&wp->tx_timer); } } } @@ -758,7 +761,7 @@ * chan->command is used to indicate to the driver that * command is pending for exection. The acutal command * structure is placed into a sock mbox structure - * (sk->protinfo.af_wanpipe->mbox). + * (WP_SK(sk)->mbox). * * The sock private structure, mbox is * used as shared memory between sock and the driver. @@ -774,6 +777,7 @@ static int execute_command(struct sock *sk, unsigned char cmd, unsigned int flags) { + wanpipe_opt *wp = WP_SK(sk); netdevice_t *dev; wanpipe_common_t *chan=NULL; int err=0; @@ -798,15 +802,14 @@ return -EINVAL; } - if (!sk->protinfo.af_wanpipe->mbox){ + if (!wp->mbox) { printk(KERN_INFO "wansock: In execute without MBOX\n"); return -EINVAL; } - ((mbox_cmd_t*)sk->protinfo.af_wanpipe->mbox)->cmd.command=cmd; - ((mbox_cmd_t*)sk->protinfo.af_wanpipe->mbox)->cmd.lcn = - sk->protinfo.af_wanpipe->lcn; - ((mbox_cmd_t*)sk->protinfo.af_wanpipe->mbox)->cmd.result=0x7F; + ((mbox_cmd_t*)wp->mbox)->cmd.command = cmd; + ((mbox_cmd_t*)wp->mbox)->cmd.lcn = wp->lcn; + ((mbox_cmd_t*)wp->mbox)->cmd.result = 0x7F; if (flags & O_NONBLOCK){ @@ -819,7 +822,7 @@ add_wait_queue(sk->sleep,&wait); current->state = TASK_INTERRUPTIBLE; for (;;){ - if (((mbox_cmd_t*)sk->protinfo.af_wanpipe->mbox)->cmd.result != 0x7F) { + if (((mbox_cmd_t*)wp->mbox)->cmd.result != 0x7F) { err = 0; break; } @@ -845,17 +848,16 @@ static void wanpipe_destroy_timer(unsigned long data) { struct sock *sk=(struct sock *)data; + wanpipe_opt *wp = WP_SK(sk); if ((!atomic_read(&sk->wmem_alloc) && !atomic_read(&sk->rmem_alloc)) || - (++sk->protinfo.af_wanpipe->force == 5)) { + (++wp->force == 5)) { if (atomic_read(&sk->wmem_alloc) || atomic_read(&sk->rmem_alloc)) printk(KERN_INFO "wansock: Warning, Packet Discarded due to sock shutdown!\n"); - if (sk->protinfo.af_wanpipe){ - kfree(sk->protinfo.af_wanpipe); - sk->protinfo.af_wanpipe=NULL; - } + kfree(wp); + WP_SK(sk) = NULL; #ifdef LINUX_2_4 if (atomic_read(&sk->refcnt) != 1){ @@ -891,7 +893,7 @@ sk->zapped=0; sk->state = WANSOCK_DISCONNECTED; - sk->protinfo.af_wanpipe->dev = NULL; + WP_SK(sk)->dev = NULL; dev = dev_get_by_index(sk->bound_dev_if); if (!dev){ @@ -928,15 +930,16 @@ static void wanpipe_link_driver (netdevice_t *dev, struct sock *sk) { + wanpipe_opt *wp = WP_SK(sk); wanpipe_common_t *chan = dev->priv; if (!chan) return; set_bit(0,&chan->common_critical); chan->sk=sk; chan->func=wanpipe_rcv; - chan->mbox=sk->protinfo.af_wanpipe->mbox; - chan->tx_timer = &sk->protinfo.af_wanpipe->tx_timer; - sk->protinfo.af_wanpipe->dev=dev; + chan->mbox = wp->mbox; + chan->tx_timer = &wp->tx_timer; + wp->dev = dev; sk->zapped = 1; clear_bit(0,&chan->common_critical); } @@ -974,12 +977,14 @@ #ifndef LINUX_2_4 struct sk_buff *skb; #endif + wanpipe_opt *wp; struct sock *sk = sock->sk; struct sock **skp; if (!sk) return 0; + wp = WP_SK(sk); check_write_queue(sk); /* Kill the tx timer, if we don't kill it now, the timer @@ -987,7 +992,7 @@ * try to access the sock which has been killed and cause * kernel panic */ - del_timer(&sk->protinfo.af_wanpipe->tx_timer); + del_timer(&wp->tx_timer); /* * Unhook packet receive handler. @@ -1060,10 +1065,8 @@ return 0; } - if (sk->protinfo.af_wanpipe){ - kfree(sk->protinfo.af_wanpipe); - sk->protinfo.af_wanpipe=NULL; - } + kfree(wp); + WP_SK(sk) = NULL; #ifdef LINUX_2_4 if (atomic_read(&sk->refcnt) != 1){ @@ -1113,6 +1116,7 @@ static void release_driver(struct sock *sk) { + wanpipe_opt *wp; struct sk_buff *skb=NULL; struct sock *deadsk=NULL; @@ -1134,12 +1138,11 @@ sk->state = WANSOCK_DISCONNECTED; sk->bound_dev_if = 0; sk->zapped=0; + wp = WP_SK(sk); - if (sk->protinfo.af_wanpipe){ - if (sk->protinfo.af_wanpipe->mbox){ - kfree(sk->protinfo.af_wanpipe->mbox); - sk->protinfo.af_wanpipe->mbox=NULL; - } + if (wp && wp->mbox) { + kfree(wp->mbox); + wp->mbox = NULL; } } @@ -1244,9 +1247,9 @@ return; } - if (sk->protinfo.af_wanpipe){ - kfree(sk->protinfo.af_wanpipe); - sk->protinfo.af_wanpipe=NULL; + if (WP_SK(sk)){ + kfree(WP_SK(sk)); + WP_SK(sk)=NULL; } #ifdef LINUX_2_4 @@ -1288,9 +1291,9 @@ sk->socket = NULL; - if (sk->protinfo.af_wanpipe){ - kfree(sk->protinfo.af_wanpipe); - sk->protinfo.af_wanpipe=NULL; + if (WP_SK(sk)){ + kfree(WP_SK(sk)); + WP_SK(sk)=NULL; } #ifdef LINUX_2_4 @@ -1317,9 +1320,9 @@ sk->socket = NULL; - if (sk->protinfo.af_wanpipe){ - kfree(sk->protinfo.af_wanpipe); - sk->protinfo.af_wanpipe=NULL; + if (WP_SK(sk)){ + kfree(WP_SK(sk)); + WP_SK(sk)=NULL; } #ifdef LINUX_2_4 @@ -1386,7 +1389,7 @@ /* X25 Specific option */ if (sk->num == htons(X25_PROT)) - sk->protinfo.af_wanpipe->svc = chan->svc; + WP_SK(sk)->svc = chan->svc; } else { sk->err = ENETDOWN; @@ -1440,7 +1443,7 @@ printk(KERN_INFO "wansock: Wanpipe card not found: %s\n",sll->sll_card); return -ENODEV; }else{ - sk->protinfo.af_wanpipe->card = (void *)card; + WP_SK(sk)->card = (void *)card; } if (!strcmp(sll->sll_device,"svc_listen")){ @@ -1808,7 +1811,7 @@ for (sk = wanpipe_sklist; sk; sk = sk->next) { - if ((po = sk->protinfo.af_wanpipe)==NULL) + if ((po = WP_SK(sk))==NULL) continue; if (dev == NULL) continue; @@ -2005,6 +2008,7 @@ wan_debug_t *dbg_data = (wan_debug_t *)arg; for (sk = wanpipe_sklist; sk; sk = sk->next){ + wanpipe_opt *wp = WP_SK(sk); if (sk == origsk){ continue; @@ -2024,8 +2028,7 @@ return err; if ((err=put_user(sk_count, &dbg_data->debug[cnt].sk_count))) return err; - if ((err=put_user(sk->protinfo.af_wanpipe->poll_cnt, - &dbg_data->debug[cnt].poll_cnt))) + if ((err=put_user(wp->poll_cnt, &dbg_data->debug[cnt].poll_cnt))) return err; if ((err=put_user(sk->bound_dev_if, &dbg_data->debug[cnt].bound))) return err; @@ -2048,8 +2051,8 @@ return err; - if (sk->protinfo.af_wanpipe){ - sdla_t *card = (sdla_t*)sk->protinfo.af_wanpipe->card; + if (wp){ + sdla_t *card = (sdla_t*)wp->card; if (card){ if ((err=put_user(atomic_read(&card->u.x.command_busy), @@ -2057,11 +2060,11 @@ return err; } - if ((err=put_user(sk->protinfo.af_wanpipe->lcn, - &dbg_data->debug[cnt].lcn))) + if ((err=put_user(wp->lcn, + &dbg_data->debug[cnt].lcn))) return err; - if (sk->protinfo.af_wanpipe->mbox){ + if (wp->mbox) { if ((err=put_user(1, &dbg_data->debug[cnt].mbox))) return err; } @@ -2096,11 +2099,11 @@ if (usr_data == NULL) return -EINVAL; - if (!sk->protinfo.af_wanpipe->mbox){ + if (!WP_SK(sk)->mbox){ return -EINVAL; } - mbox_ptr = (mbox_cmd_t *)sk->protinfo.af_wanpipe->mbox; + mbox_ptr = (mbox_cmd_t *)WP_SK(sk)->mbox; if ((err=put_user(mbox_ptr->cmd.qdm, &usr_data->hdr.qdm))) return err; @@ -2140,7 +2143,7 @@ mbox_cmd_t *mbox_ptr; int err; - if (!sk->protinfo.af_wanpipe->mbox){ + if (!WP_SK(sk)->mbox){ void *mbox_ptr; netdevice_t *dev = dev_get_by_index(sk->bound_dev_if); if (!dev) @@ -2152,12 +2155,12 @@ return -ENOMEM; memset(mbox_ptr, 0, sizeof(mbox_cmd_t)); - sk->protinfo.af_wanpipe->mbox = mbox_ptr; + WP_SK(sk)->mbox = mbox_ptr; wanpipe_link_driver(dev,sk); } - mbox_ptr = (mbox_cmd_t*)sk->protinfo.af_wanpipe->mbox; + mbox_ptr = (mbox_cmd_t*)WP_SK(sk)->mbox; memset(mbox_ptr, 0, sizeof(mbox_cmd_t)); if (usr_data == NULL){ @@ -2204,7 +2207,7 @@ struct sock *sk = sock->sk; unsigned int mask; - ++sk->protinfo.af_wanpipe->poll_cnt; + ++WP_SK(sk)->poll_cnt; poll_wait(file, sk->sleep, wait); mask = 0; @@ -2240,7 +2243,7 @@ * transmit queue */ if (sk->num == htons(X25_PROT)){ - if (atomic_read(&sk->protinfo.af_wanpipe->packet_sent)) + if (atomic_read(&WP_SK(sk)->packet_sent)) return mask; } @@ -2296,7 +2299,7 @@ { sdla_t *card; - card = (sdla_t*)sk->protinfo.af_wanpipe->card; + card = (sdla_t*)WP_SK(sk)->card; if (!card) return -ENOMEM; @@ -2321,9 +2324,7 @@ static void wanpipe_unlink_card (struct sock *sk) { - sdla_t *card; - - card = (sdla_t*)sk->protinfo.af_wanpipe->card; + sdla_t *card = (sdla_t*)WP_SK(sk)->card; if (card){ card->sk=NULL; @@ -2342,7 +2343,8 @@ static int wanpipe_exec_cmd(struct sock *sk, int cmd, unsigned int flags) { int err = -EINVAL; - mbox_cmd_t *mbox_ptr = (mbox_cmd_t*)sk->protinfo.af_wanpipe->mbox; + wanpipe_opt *wp = WP_SK(sk); + mbox_cmd_t *mbox_ptr = (mbox_cmd_t*)wp->mbox; if (!mbox_ptr){ printk(KERN_INFO "NO MBOX PTR !!!!!\n"); @@ -2373,16 +2375,15 @@ * it is done in wanpipe_listen_rcv(). */ if (sk->state == WANSOCK_CONNECTED){ - sk->protinfo.af_wanpipe->lcn = - ((mbox_cmd_t*)sk->protinfo.af_wanpipe->mbox)->cmd.lcn; + wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn; DBG_PRINTK(KERN_INFO "\nwansock: Accept OK %i\n", - sk->protinfo.af_wanpipe->lcn ); + wp->lcn); err = 0; }else{ DBG_PRINTK (KERN_INFO "\nwansock: Accept Failed %i\n", - sk->protinfo.af_wanpipe->lcn); - sk->protinfo.af_wanpipe->lcn = 0; + wp->lcn); + wp->lcn = 0; err = -ECONNREFUSED; } break; @@ -2400,7 +2401,7 @@ * is transmitted, or clear a call and drop packets */ if (atomic_read(&sk->wmem_alloc) || check_driver_busy(sk)){ - mbox_cmd_t *mbox = sk->protinfo.af_wanpipe->mbox; + mbox_cmd_t *mbox = wp->mbox; if (mbox->cmd.qdm & 0x80){ mbox->cmd.result = 0x35; err = -EAGAIN; @@ -2417,8 +2418,8 @@ err = -ECONNREFUSED; if (sk->state == WANSOCK_DISCONNECTED){ DBG_PRINTK(KERN_INFO "\nwansock: CLEAR OK %i\n", - sk->protinfo.af_wanpipe->lcn); - sk->protinfo.af_wanpipe->lcn=0; + wp->lcn); + wp->lcn = 0; err = 0; } break; @@ -2436,7 +2437,7 @@ * is transmitted, or reset a call and drop packets */ if (atomic_read(&sk->wmem_alloc) || check_driver_busy(sk)){ - mbox_cmd_t *mbox = sk->protinfo.af_wanpipe->mbox; + mbox_cmd_t *mbox = wp->mbox; if (mbox->cmd.qdm & 0x80){ mbox->cmd.result = 0x35; err = -EAGAIN; @@ -2461,18 +2462,16 @@ if (sk->state == WANSOCK_CONNECTED){ - sk->protinfo.af_wanpipe->lcn = - ((mbox_cmd_t*)sk->protinfo.af_wanpipe->mbox)->cmd.lcn; + wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn; DBG_PRINTK(KERN_INFO "\nwansock: PLACE CALL OK %i\n", - sk->protinfo.af_wanpipe->lcn); + wp->lcn); err = 0; }else if (sk->state == WANSOCK_CONNECTING && (flags & O_NONBLOCK)){ - sk->protinfo.af_wanpipe->lcn = - ((mbox_cmd_t*)sk->protinfo.af_wanpipe->mbox)->cmd.lcn; + wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn; DBG_PRINTK(KERN_INFO "\nwansock: Place Call OK: Waiting %i\n", - sk->protinfo.af_wanpipe->lcn); + wp->lcn); err = 0; @@ -2583,7 +2582,7 @@ kfree_skb(skb); - DBG_PRINTK(KERN_INFO "\nwansock: ACCEPT Got LCN %i\n",newsk->protinfo.af_wanpipe->lcn); + DBG_PRINTK(KERN_INFO "\nwansock: ACCEPT Got LCN %i\n",WP_SK(newsk)->lcn); return 0; } @@ -2660,8 +2659,8 @@ sock->state = SS_CONNECTING; sk->state = WANSOCK_CONNECTING; - if (!sk->protinfo.af_wanpipe->mbox){ - if (sk->protinfo.af_wanpipe->svc){ + if (!WP_SK(sk)->mbox){ + if (WP_SK(sk)->svc){ return -EINVAL; }else{ int err; @@ -2733,14 +2732,12 @@ static struct net_proto_family wanpipe_family_ops = { - PF_WANPIPE, - wanpipe_create + family: PF_WANPIPE, + create: wanpipe_create, }; -struct notifier_block wanpipe_netdev_notifier={ - wanpipe_notifier, - NULL, - 0 +struct notifier_block wanpipe_netdev_notifier = { + notifier_call: wanpipe_notifier, }; Index: kernel-acme/net/x25/af_x25.c diff -u kernel-acme/net/x25/af_x25.c:1.1.1.3 kernel-acme/net/x25/af_x25.c:1.1.1.3.8.3 --- kernel-acme/net/x25/af_x25.c:1.1.1.3 Wed Sep 26 22:00:20 2001 +++ kernel-acme/net/x25/af_x25.c Fri Dec 21 02:12:17 2001 @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -182,8 +183,7 @@ struct sock *s; for (s = x25_list; s != NULL; s = s->next) - if (s->protinfo.x25->neighbour && - s->protinfo.x25->neighbour->dev == dev) + if (X25_SK(s)->neighbour && X25_SK(s)->neighbour->dev == dev) x25_disconnect(s, ENETUNREACH, 0, 0); } @@ -248,7 +248,7 @@ cli(); for (s = x25_list; s != NULL; s = s->next) { - if ((strcmp(addr->x25_addr, s->protinfo.x25->source_addr.x25_addr) == 0 || + if ((!strcmp(addr->x25_addr, X25_SK(s)->source_addr.x25_addr) || strcmp(addr->x25_addr, null_x25_address.x25_addr) == 0) && s->state == TCP_LISTEN) { restore_flags(flags); @@ -272,7 +272,7 @@ cli(); for (s = x25_list; s != NULL; s = s->next) { - if (s->protinfo.x25->lci == lci && s->protinfo.x25->neighbour == neigh) { + if (X25_SK(s)->lci == lci && X25_SK(s)->neighbour == neigh) { restore_flags(flags); return s; } @@ -334,7 +334,7 @@ if (skb->sk != sk) { /* A pending connection */ skb->sk->dead = 1; /* Queue the unaccepted socket for death */ x25_start_heartbeat(skb->sk); - skb->sk->protinfo.x25->state = X25_STATE_0; + X25_SK(skb->sk)->state = X25_STATE_0; } kfree_skb(skb); @@ -377,7 +377,7 @@ switch (optname) { case X25_QBITINCL: - sk->protinfo.x25->qbitincl = opt ? 1 : 0; + X25_SK(sk)->qbitincl = opt ? 1 : 0; return 0; default: @@ -400,7 +400,7 @@ switch (optname) { case X25_QBITINCL: - val = sk->protinfo.x25->qbitincl; + val = X25_SK(sk)->qbitincl; break; default: @@ -423,7 +423,7 @@ struct sock *sk = sock->sk; if (sk->state != TCP_LISTEN) { - memset(&sk->protinfo.x25->dest_addr, '\0', X25_ADDR_LEN); + memset(&X25_SK(sk)->dest_addr, '\0', X25_ADDR_LEN); sk->max_ack_backlog = backlog; sk->state = TCP_LISTEN; return 0; @@ -437,7 +437,7 @@ struct sock *sk; x25_cb *x25; - if ((sk = sk_alloc(AF_X25, GFP_ATOMIC, 1)) == NULL) + if ((sk = sk_alloc(AF_X25, GFP_ATOMIC, 1, NULL)) == NULL) return NULL; if ((x25 = kmalloc(sizeof(*x25), GFP_ATOMIC)) == NULL) { @@ -447,8 +447,8 @@ memset(x25, 0x00, sizeof(*x25)); - x25->sk = sk; - sk->protinfo.x25 = x25; + x25->sk = sk; + X25_SK(sk) = x25; MOD_INC_USE_COUNT; @@ -473,7 +473,7 @@ if ((sk = x25_alloc_socket()) == NULL) return -ENOMEM; - x25 = sk->protinfo.x25; + x25 = X25_SK(sk); sock_init_data(sock, sk); @@ -510,7 +510,7 @@ if ((sk = x25_alloc_socket()) == NULL) return NULL; - x25 = sk->protinfo.x25; + x25 = X25_SK(sk); sk->type = osk->type; sk->socket = osk->socket; @@ -524,15 +524,13 @@ sk->zapped = osk->zapped; sk->backlog_rcv = osk->backlog_rcv; - x25->t21 = osk->protinfo.x25->t21; - x25->t22 = osk->protinfo.x25->t22; - x25->t23 = osk->protinfo.x25->t23; - x25->t2 = osk->protinfo.x25->t2; + x25->t21 = X25_SK(osk)->t21; + x25->t22 = X25_SK(osk)->t22; + x25->t23 = X25_SK(osk)->t23; + x25->t2 = X25_SK(osk)->t2; + x25->facilities = X25_SK(osk)->facilities; + x25->qbitincl = X25_SK(osk)->qbitincl; - x25->facilities = osk->protinfo.x25->facilities; - - x25->qbitincl = osk->protinfo.x25->qbitincl; - init_timer(&x25->timer); return sk; @@ -544,7 +542,7 @@ if (sk == NULL) return 0; - switch (sk->protinfo.x25->state) { + switch (X25_SK(sk)->state) { case X25_STATE_0: case X25_STATE_2: @@ -558,7 +556,7 @@ x25_clear_queues(sk); x25_write_internal(sk, X25_CLEAR_REQUEST); x25_start_t23timer(sk); - sk->protinfo.x25->state = X25_STATE_2; + X25_SK(sk)->state = X25_STATE_2; sk->state = TCP_CLOSE; sk->shutdown |= SEND_SHUTDOWN; sk->state_change(sk); @@ -590,7 +588,7 @@ if (addr->sx25_family != AF_X25) return -EINVAL; - sk->protinfo.x25->source_addr = addr->sx25_addr; + X25_SK(sk)->source_addr = addr->sx25_addr; x25_insert_socket(sk); @@ -632,28 +630,28 @@ if ((dev = x25_get_route(&addr->sx25_addr)) == NULL) return -ENETUNREACH; - if ((sk->protinfo.x25->neighbour = x25_get_neigh(dev)) == NULL) + if ((X25_SK(sk)->neighbour = x25_get_neigh(dev)) == NULL) return -ENETUNREACH; - x25_limit_facilities(&sk->protinfo.x25->facilities, - sk->protinfo.x25->neighbour); + x25_limit_facilities(&X25_SK(sk)->facilities, X25_SK(sk)->neighbour); - if ((sk->protinfo.x25->lci = x25_new_lci(sk->protinfo.x25->neighbour)) == 0) + if ((X25_SK(sk)->lci = x25_new_lci(X25_SK(sk)->neighbour)) == 0) return -ENETUNREACH; if (sk->zapped) /* Must bind first - autobinding does not work */ return -EINVAL; - if (strcmp(sk->protinfo.x25->source_addr.x25_addr, null_x25_address.x25_addr) == 0) - memset(&sk->protinfo.x25->source_addr, '\0', X25_ADDR_LEN); + if (!strcmp(X25_SK(sk)->source_addr.x25_addr, + null_x25_address.x25_addr)) + memset(&X25_SK(sk)->source_addr, '\0', X25_ADDR_LEN); - sk->protinfo.x25->dest_addr = addr->sx25_addr; + X25_SK(sk)->dest_addr = addr->sx25_addr; /* Move to connecting socket, start sending Connect Requests */ sock->state = SS_CONNECTING; sk->state = TCP_SYN_SENT; - sk->protinfo.x25->state = X25_STATE_1; + X25_SK(sk)->state = X25_STATE_1; x25_write_internal(sk, X25_CALL_REQUEST); @@ -748,9 +746,9 @@ if (peer != 0) { if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; - sx25->sx25_addr = sk->protinfo.x25->dest_addr; + sx25->sx25_addr = X25_SK(sk)->dest_addr; } else { - sx25->sx25_addr = sk->protinfo.x25->source_addr; + sx25->sx25_addr = X25_SK(sk)->source_addr; } sx25->sx25_family = AF_X25; @@ -822,12 +820,12 @@ skb->sk = make; make->state = TCP_ESTABLISHED; - make->protinfo.x25->lci = lci; - make->protinfo.x25->dest_addr = dest_addr; - make->protinfo.x25->source_addr = source_addr; - make->protinfo.x25->neighbour = neigh; - make->protinfo.x25->facilities = facilities; - make->protinfo.x25->vc_facil_mask = sk->protinfo.x25->vc_facil_mask; + X25_SK(make)->lci = lci; + X25_SK(make)->dest_addr = dest_addr; + X25_SK(make)->source_addr = source_addr; + X25_SK(make)->neighbour = neigh; + X25_SK(make)->facilities = facilities; + X25_SK(make)->vc_facil_mask = X25_SK(sk)->vc_facil_mask; x25_write_internal(make, X25_CALL_ACCEPTED); @@ -835,11 +833,11 @@ * Incoming Call User Data. */ if (skb->len >= 0) { - memcpy(make->protinfo.x25->calluserdata.cuddata, skb->data, skb->len); - make->protinfo.x25->calluserdata.cudlength = skb->len; + memcpy(X25_SK(make)->calluserdata.cuddata, skb->data, skb->len); + X25_SK(make)->calluserdata.cudlength = skb->len; } - make->protinfo.x25->state = X25_STATE_3; + X25_SK(make)->state = X25_STATE_3; sk->ack_backlog++; make->pair = sk; @@ -881,14 +879,15 @@ return -EPIPE; } - if (sk->protinfo.x25->neighbour == NULL) + if (X25_SK(sk)->neighbour == NULL) return -ENETUNREACH; if (usx25 != NULL) { if (msg->msg_namelen < sizeof(sx25)) return -EINVAL; sx25 = *usx25; - if (strcmp(sk->protinfo.x25->dest_addr.x25_addr, sx25.sx25_addr.x25_addr) != 0) + if (strcmp(X25_SK(sk)->dest_addr.x25_addr, + sx25.sx25_addr.x25_addr)) return -EISCONN; if (sx25.sx25_family != AF_X25) return -EINVAL; @@ -902,7 +901,7 @@ return -ENOTCONN; sx25.sx25_family = AF_X25; - sx25.sx25_addr = sk->protinfo.x25->dest_addr; + sx25.sx25_addr = X25_SK(sk)->dest_addr; } SOCK_DEBUG(sk, "x25_sendmsg: sendto: Addresses built.\n"); @@ -934,7 +933,7 @@ * If the Q BIT Include socket option is in force, the first * byte of the user data is the logical value of the Q Bit. */ - if (sk->protinfo.x25->qbitincl) { + if (X25_SK(sk)->qbitincl) { qbit = skb->data[0]; skb_pull(skb, 1); } @@ -945,30 +944,34 @@ SOCK_DEBUG(sk, "x25_sendmsg: Building X.25 Header.\n"); if (msg->msg_flags & MSG_OOB) { - if (sk->protinfo.x25->neighbour->extended) { + if (X25_SK(sk)->neighbour->extended) { asmptr = skb_push(skb, X25_STD_MIN_LEN); - *asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ; - *asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF; + *asmptr++ = ((X25_SK(sk)->lci >> 8) & 0x0F) | + X25_GFI_EXTSEQ; + *asmptr++ = (X25_SK(sk)->lci >> 0) & 0xFF; *asmptr++ = X25_INTERRUPT; } else { asmptr = skb_push(skb, X25_STD_MIN_LEN); - *asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ; - *asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF; + *asmptr++ = ((X25_SK(sk)->lci >> 8) & 0x0F) | + X25_GFI_STDSEQ; + *asmptr++ = (X25_SK(sk)->lci >> 0) & 0xFF; *asmptr++ = X25_INTERRUPT; } } else { - if (sk->protinfo.x25->neighbour->extended) { + if (X25_SK(sk)->neighbour->extended) { /* Build an Extended X.25 header */ asmptr = skb_push(skb, X25_EXT_MIN_LEN); - *asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ; - *asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF; + *asmptr++ = ((X25_SK(sk)->lci >> 8) & 0x0F) | + X25_GFI_EXTSEQ; + *asmptr++ = (X25_SK(sk)->lci >> 0) & 0xFF; *asmptr++ = X25_DATA; *asmptr++ = X25_DATA; } else { /* Build an Standard X.25 header */ asmptr = skb_push(skb, X25_STD_MIN_LEN); - *asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ; - *asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF; + *asmptr++ = ((X25_SK(sk)->lci >> 8) & 0x0F) | + X25_GFI_STDSEQ; + *asmptr++ = (X25_SK(sk)->lci >> 0) & 0xFF; *asmptr++ = X25_DATA; } @@ -985,13 +988,14 @@ } if (msg->msg_flags & MSG_OOB) { - skb_queue_tail(&sk->protinfo.x25->interrupt_out_queue, skb); + skb_queue_tail(&X25_SK(sk)->interrupt_out_queue, skb); } else { len = x25_output(sk, skb); if(len<0){ kfree_skb(skb); } else { - if(sk->protinfo.x25->qbitincl) len++; + if (X25_SK(sk)->qbitincl) + len++; } } @@ -1034,17 +1038,17 @@ return -ENOTCONN; if (flags & MSG_OOB) { - if (sk->urginline || skb_peek(&sk->protinfo.x25->interrupt_in_queue) == NULL) + if (sk->urginline || !skb_peek(&X25_SK(sk)->interrupt_in_queue)) return -EINVAL; - skb = skb_dequeue(&sk->protinfo.x25->interrupt_in_queue); + skb = skb_dequeue(&X25_SK(sk)->interrupt_in_queue); skb_pull(skb, X25_STD_MIN_LEN); /* * No Q bit information on Interrupt data. */ - if (sk->protinfo.x25->qbitincl) { + if (X25_SK(sk)->qbitincl) { asmptr = skb_push(skb, 1); *asmptr = 0x00; } @@ -1057,9 +1061,10 @@ qbit = (skb->data[0] & X25_Q_BIT) == X25_Q_BIT; - skb_pull(skb, (sk->protinfo.x25->neighbour->extended) ? X25_EXT_MIN_LEN : X25_STD_MIN_LEN); + skb_pull(skb, (X25_SK(sk)->neighbour->extended) ? + X25_EXT_MIN_LEN : X25_STD_MIN_LEN); - if (sk->protinfo.x25->qbitincl) { + if (X25_SK(sk)->qbitincl) { asmptr = skb_push(skb, 1); *asmptr = qbit; } @@ -1081,7 +1086,7 @@ if (sx25 != NULL) { sx25->sx25_family = AF_X25; - sx25->sx25_addr = sk->protinfo.x25->dest_addr; + sx25->sx25_addr = X25_SK(sk)->dest_addr; } msg->msg_namelen = sizeof(struct sockaddr_x25); @@ -1151,7 +1156,7 @@ case SIOCX25GFACILITIES: { struct x25_facilities facilities; - facilities = sk->protinfo.x25->facilities; + facilities = X25_SK(sk)->facilities; return copy_to_user((void *)arg, &facilities, sizeof(facilities)) ? -EFAULT : 0; } @@ -1171,13 +1176,13 @@ return -EINVAL; if (facilities.reverse != 0 && facilities.reverse != 1) return -EINVAL; - sk->protinfo.x25->facilities = facilities; + X25_SK(sk)->facilities = facilities; return 0; } case SIOCX25GCALLUSERDATA: { struct x25_calluserdata calluserdata; - calluserdata = sk->protinfo.x25->calluserdata; + calluserdata = X25_SK(sk)->calluserdata; return copy_to_user((void *)arg, &calluserdata, sizeof(calluserdata)) ? -EFAULT : 0; } @@ -1187,13 +1192,13 @@ return -EFAULT; if (calluserdata.cudlength > X25_MAX_CUD_LEN) return -EINVAL; - sk->protinfo.x25->calluserdata = calluserdata; + X25_SK(sk)->calluserdata = calluserdata; return 0; } case SIOCX25GCAUSEDIAG: { struct x25_causediag causediag; - causediag = sk->protinfo.x25->causediag; + causediag = X25_SK(sk)->causediag; return copy_to_user((void *)arg, &causediag, sizeof(causediag)) ? -EFAULT : 0; } @@ -1219,25 +1224,28 @@ len += sprintf(buffer, "dest_addr src_addr dev lci st vs vr va t t2 t21 t22 t23 Snd-Q Rcv-Q inode\n"); for (s = x25_list; s != NULL; s = s->next) { - if (s->protinfo.x25->neighbour == NULL || (dev = s->protinfo.x25->neighbour->dev) == NULL) + if (!X25_SK(s)->neighbour || + (dev = X25_SK(s)->neighbour->dev) == NULL) devname = "???"; else - devname = s->protinfo.x25->neighbour->dev->name; + devname = X25_SK(s)->neighbour->dev->name; len += sprintf(buffer + len, "%-10s %-10s %-5s %3.3X %d %d %d %d %3lu %3lu %3lu %3lu %3lu %5d %5d %ld\n", - (s->protinfo.x25->dest_addr.x25_addr[0] == '\0') ? "*" : s->protinfo.x25->dest_addr.x25_addr, - (s->protinfo.x25->source_addr.x25_addr[0] == '\0') ? "*" : s->protinfo.x25->source_addr.x25_addr, + (X25_SK(s)->dest_addr.x25_addr[0] == '\0') ? "*" : + X25_SK(s)->dest_addr.x25_addr, + (X25_SK(s)->source_addr.x25_addr[0] == '\0') ? "*" : + X25_SK(s)->source_addr.x25_addr, devname, - s->protinfo.x25->lci & 0x0FFF, - s->protinfo.x25->state, - s->protinfo.x25->vs, - s->protinfo.x25->vr, - s->protinfo.x25->va, + X25_SK(s)->lci & 0x0FFF, + X25_SK(s)->state, + X25_SK(s)->vs, + X25_SK(s)->vr, + X25_SK(s)->va, x25_display_timer(s) / HZ, - s->protinfo.x25->t2 / HZ, - s->protinfo.x25->t21 / HZ, - s->protinfo.x25->t22 / HZ, - s->protinfo.x25->t23 / HZ, + X25_SK(s)->t2 / HZ, + X25_SK(s)->t21 / HZ, + X25_SK(s)->t22 / HZ, + X25_SK(s)->t23 / HZ, atomic_read(&s->wmem_alloc), atomic_read(&s->rmem_alloc), s->socket != NULL ? s->socket->inode->i_ino : 0L); @@ -1307,7 +1315,7 @@ struct sock *s; for( s=x25_list; s != NULL; s=s->next){ - if( s->protinfo.x25->neighbour == neigh ) + if (X25_SK(s)->neighbour == neigh) x25_disconnect(s, ENETUNREACH, 0, 0); } } Index: kernel-acme/net/x25/x25_facilities.c diff -u kernel-acme/net/x25/x25_facilities.c:1.1.1.1 kernel-acme/net/x25/x25_facilities.c:1.1.1.1.12.1 --- kernel-acme/net/x25/x25_facilities.c:1.1.1.1 Tue Jun 26 17:28:55 2001 +++ kernel-acme/net/x25/x25_facilities.c Tue Dec 11 00:26:47 2001 @@ -163,11 +163,11 @@ memset(&theirs, 0x00, sizeof(struct x25_facilities)); - ours = &sk->protinfo.x25->facilities; + ours = &X25_SK(sk)->facilities; *new = *ours; - len = x25_parse_facilities(skb, &theirs, &sk->protinfo.x25->vc_facil_mask); + len = x25_parse_facilities(skb, &theirs, &X25_SK(sk)->vc_facil_mask); /* * They want reverse charging, we won't accept it. Index: kernel-acme/net/x25/x25_in.c diff -u kernel-acme/net/x25/x25_in.c:1.1.1.1 kernel-acme/net/x25/x25_in.c:1.1.1.1.12.1 --- kernel-acme/net/x25/x25_in.c:1.1.1.1 Tue Jun 26 17:28:55 2001 +++ kernel-acme/net/x25/x25_in.c Tue Dec 11 00:26:47 2001 @@ -47,37 +47,40 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) { struct sk_buff *skbo, *skbn = skb; + x25_cb *x25 = X25_SK(sk); if (more) { - sk->protinfo.x25->fraglen += skb->len; - skb_queue_tail(&sk->protinfo.x25->fragment_queue, skb); + x25->fraglen += skb->len; + skb_queue_tail(&x25->fragment_queue, skb); skb_set_owner_r(skb, sk); return 0; } - if (!more && sk->protinfo.x25->fraglen > 0) { /* End of fragment */ - int len = sk->protinfo.x25->fraglen + skb->len; + if (!more && x25->fraglen > 0) { /* End of fragment */ + int len = x25->fraglen + skb->len; if ((skbn = alloc_skb(len, GFP_ATOMIC)) == NULL){ kfree_skb(skb); return 1; } - skb_queue_tail(&sk->protinfo.x25->fragment_queue, skb); + skb_queue_tail(&x25->fragment_queue, skb); skbn->h.raw = skbn->data; - skbo = skb_dequeue(&sk->protinfo.x25->fragment_queue); + skbo = skb_dequeue(&x25->fragment_queue); memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len); kfree_skb(skbo); - while ((skbo = skb_dequeue(&sk->protinfo.x25->fragment_queue)) != NULL) { - skb_pull(skbo, (sk->protinfo.x25->neighbour->extended) ? X25_EXT_MIN_LEN : X25_STD_MIN_LEN); + while ((skbo = + skb_dequeue(&x25->fragment_queue)) != NULL) { + skb_pull(skbo, (x25->neighbour->extended) ? + X25_EXT_MIN_LEN : X25_STD_MIN_LEN); memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len); kfree_skb(skbo); } - sk->protinfo.x25->fraglen = 0; + x25->fraglen = 0; } skb_set_owner_r(skbn, sk); @@ -98,33 +101,37 @@ x25_address source_addr, dest_addr; switch (frametype) { + case X25_CALL_ACCEPTED: { + x25_cb *x25 = X25_SK(sk); - case X25_CALL_ACCEPTED: x25_stop_timer(sk); - sk->protinfo.x25->condition = 0x00; - sk->protinfo.x25->vs = 0; - sk->protinfo.x25->va = 0; - sk->protinfo.x25->vr = 0; - sk->protinfo.x25->vl = 0; - sk->protinfo.x25->state = X25_STATE_3; - sk->state = TCP_ESTABLISHED; + x25->condition = 0x00; + x25->vs = 0; + x25->va = 0; + x25->vr = 0; + x25->vl = 0; + x25->state = X25_STATE_3; + sk->state = TCP_ESTABLISHED; /* * Parse the data in the frame. */ skb_pull(skb, X25_STD_MIN_LEN); skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); - skb_pull(skb, x25_parse_facilities(skb, &sk->protinfo.x25->facilities, &sk->protinfo.x25->vc_facil_mask)); + skb_pull(skb, + x25_parse_facilities(skb, &x25->facilities, + &x25->vc_facil_mask)); /* * Copy any Call User Data. */ if (skb->len >= 0) { - memcpy(sk->protinfo.x25->calluserdata.cuddata, skb->data, skb->len); - sk->protinfo.x25->calluserdata.cudlength = skb->len; + memcpy(x25->calluserdata.cuddata, skb->data, + skb->len); + x25->calluserdata.cudlength = skb->len; } if (!sk->dead) sk->state_change(sk); break; - + } case X25_CLEAR_REQUEST: x25_write_internal(sk, X25_CLEAR_CONFIRMATION); x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]); @@ -171,19 +178,20 @@ { int queued = 0; int modulus; + x25_cb *x25 = X25_SK(sk); - modulus = (sk->protinfo.x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS; + modulus = (x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS; switch (frametype) { case X25_RESET_REQUEST: x25_write_internal(sk, X25_RESET_CONFIRMATION); x25_stop_timer(sk); - sk->protinfo.x25->condition = 0x00; - sk->protinfo.x25->vs = 0; - sk->protinfo.x25->vr = 0; - sk->protinfo.x25->va = 0; - sk->protinfo.x25->vl = 0; + x25->condition = 0x00; + x25->vs = 0; + x25->vr = 0; + x25->va = 0; + x25->vl = 0; x25_requeue_frames(sk); break; @@ -198,74 +206,73 @@ x25_clear_queues(sk); x25_write_internal(sk, X25_RESET_REQUEST); x25_start_t22timer(sk); - sk->protinfo.x25->condition = 0x00; - sk->protinfo.x25->vs = 0; - sk->protinfo.x25->vr = 0; - sk->protinfo.x25->va = 0; - sk->protinfo.x25->vl = 0; - sk->protinfo.x25->state = X25_STATE_4; + x25->condition = 0x00; + x25->vs = 0; + x25->vr = 0; + x25->va = 0; + x25->vl = 0; + x25->state = X25_STATE_4; } else { x25_frames_acked(sk, nr); if (frametype == X25_RNR) { - sk->protinfo.x25->condition |= X25_COND_PEER_RX_BUSY; + x25->condition |= X25_COND_PEER_RX_BUSY; } else { - sk->protinfo.x25->condition &= ~X25_COND_PEER_RX_BUSY; + x25->condition &= ~X25_COND_PEER_RX_BUSY; } } break; case X25_DATA: /* XXX */ - sk->protinfo.x25->condition &= ~X25_COND_PEER_RX_BUSY; - if ((ns!=sk->protinfo.x25->vr) || - !x25_validate_nr(sk, nr)) { + x25->condition &= ~X25_COND_PEER_RX_BUSY; + if ((ns != x25->vr) || !x25_validate_nr(sk, nr)) { x25_clear_queues(sk); x25_write_internal(sk, X25_RESET_REQUEST); x25_start_t22timer(sk); - sk->protinfo.x25->condition = 0x00; - sk->protinfo.x25->vs = 0; - sk->protinfo.x25->vr = 0; - sk->protinfo.x25->va = 0; - sk->protinfo.x25->vl = 0; - sk->protinfo.x25->state = X25_STATE_4; + x25->condition = 0x00; + x25->vs = 0; + x25->vr = 0; + x25->va = 0; + x25->vl = 0; + x25->state = X25_STATE_4; break; } x25_frames_acked(sk, nr); - if (ns == sk->protinfo.x25->vr) { + if (ns == x25->vr) { if (x25_queue_rx_frame(sk, skb, m) == 0) { - sk->protinfo.x25->vr = (sk->protinfo.x25->vr + 1) % modulus; + x25->vr = (x25->vr + 1) % modulus; queued = 1; } else { /* Should never happen */ x25_clear_queues(sk); x25_write_internal(sk, X25_RESET_REQUEST); x25_start_t22timer(sk); - sk->protinfo.x25->condition = 0x00; - sk->protinfo.x25->vs = 0; - sk->protinfo.x25->vr = 0; - sk->protinfo.x25->va = 0; - sk->protinfo.x25->vl = 0; - sk->protinfo.x25->state = X25_STATE_4; + x25->condition = 0x00; + x25->vs = 0; + x25->vr = 0; + x25->va = 0; + x25->vl = 0; + x25->state = X25_STATE_4; break; } if (atomic_read(&sk->rmem_alloc) > (sk->rcvbuf / 2)) - sk->protinfo.x25->condition |= X25_COND_OWN_RX_BUSY; + x25->condition |= X25_COND_OWN_RX_BUSY; } /* * If the window is full Ack it immediately, else * start the holdback timer. */ - if (((sk->protinfo.x25->vl + sk->protinfo.x25->facilities.winsize_in) % modulus) == sk->protinfo.x25->vr) { - sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING; + if (((x25->vl + x25->facilities.winsize_in) % modulus) == x25->vr) { + x25->condition &= ~X25_COND_ACK_PENDING; x25_stop_timer(sk); x25_enquiry_response(sk); } else { - sk->protinfo.x25->condition |= X25_COND_ACK_PENDING; + x25->condition |= X25_COND_ACK_PENDING; x25_start_t2timer(sk); } break; case X25_INTERRUPT_CONFIRMATION: - sk->protinfo.x25->intflag = 0; + x25->intflag = 0; break; case X25_INTERRUPT: @@ -273,7 +280,7 @@ queued = (sock_queue_rcv_skb(sk, skb) == 0); } else { skb_set_owner_r(skb, sk); - skb_queue_tail(&sk->protinfo.x25->interrupt_in_queue, skb); + skb_queue_tail(&x25->interrupt_in_queue, skb); queued = 1; } if (sk->proc != 0) { @@ -305,17 +312,19 @@ case X25_RESET_REQUEST: x25_write_internal(sk, X25_RESET_CONFIRMATION); - case X25_RESET_CONFIRMATION: + case X25_RESET_CONFIRMATION: { + x25_cb *x25 = X25_SK(sk); + x25_stop_timer(sk); - sk->protinfo.x25->condition = 0x00; - sk->protinfo.x25->va = 0; - sk->protinfo.x25->vr = 0; - sk->protinfo.x25->vs = 0; - sk->protinfo.x25->vl = 0; - sk->protinfo.x25->state = X25_STATE_3; + x25->condition = 0x00; + x25->va = 0; + x25->vr = 0; + x25->vs = 0; + x25->vl = 0; + x25->state = X25_STATE_3; x25_requeue_frames(sk); break; - + } case X25_CLEAR_REQUEST: x25_write_internal(sk, X25_CLEAR_CONFIRMATION); x25_disconnect(sk, 0, skb->data[3], skb->data[4]); @@ -333,12 +342,12 @@ { int queued = 0, frametype, ns, nr, q, d, m; - if (sk->protinfo.x25->state == X25_STATE_0) + if (X25_SK(sk)->state == X25_STATE_0) return 0; frametype = x25_decode(sk, skb, &ns, &nr, &q, &d, &m); - switch (sk->protinfo.x25->state) { + switch (X25_SK(sk)->state) { case X25_STATE_1: queued = x25_state1_machine(sk, skb, frametype); break; Index: kernel-acme/net/x25/x25_out.c diff -u kernel-acme/net/x25/x25_out.c:1.1.1.1 kernel-acme/net/x25/x25_out.c:1.1.1.1.12.1 --- kernel-acme/net/x25/x25_out.c:1.1.1.1 Tue Jun 26 17:28:55 2001 +++ kernel-acme/net/x25/x25_out.c Tue Dec 11 00:26:47 2001 @@ -65,12 +65,13 @@ { struct sk_buff *skbn; unsigned char header[X25_EXT_MIN_LEN]; - int err, frontlen, len, header_len, max_len; + int err, frontlen, len; int sent=0, noblock = X25_SKB_CB(skb)->flags & MSG_DONTWAIT; + x25_cb *x25 = X25_SK(sk); + int header_len = (x25->neighbour->extended) ? X25_EXT_MIN_LEN : + X25_STD_MIN_LEN; + int max_len = x25_pacsize_to_bytes(x25->facilities.pacsize_out); - header_len = (sk->protinfo.x25->neighbour->extended) ? X25_EXT_MIN_LEN : X25_STD_MIN_LEN; - max_len = x25_pacsize_to_bytes(sk->protinfo.x25->facilities.pacsize_out); - if (skb->len - header_len > max_len) { /* Save a copy of the Header */ memcpy(header, skb->data, header_len); @@ -101,7 +102,7 @@ memcpy(skbn->data, header, header_len); if (skb->len > 0) { - if (sk->protinfo.x25->neighbour->extended) + if (x25->neighbour->extended) skbn->data[3] |= X25_EXT_M_BIT; else skbn->data[2] |= X25_STD_M_BIT; @@ -125,20 +126,22 @@ */ static void x25_send_iframe(struct sock *sk, struct sk_buff *skb) { + x25_cb *x25 = X25_SK(sk); + if (skb == NULL) return; - if (sk->protinfo.x25->neighbour->extended) { - skb->data[2] = (sk->protinfo.x25->vs << 1) & 0xFE; + if (x25->neighbour->extended) { + skb->data[2] = (x25->vs << 1) & 0xFE; skb->data[3] &= X25_EXT_M_BIT; - skb->data[3] |= (sk->protinfo.x25->vr << 1) & 0xFE; + skb->data[3] |= (x25->vr << 1) & 0xFE; } else { skb->data[2] &= X25_STD_M_BIT; - skb->data[2] |= (sk->protinfo.x25->vs << 1) & 0x0E; - skb->data[2] |= (sk->protinfo.x25->vr << 5) & 0xE0; + skb->data[2] |= (x25->vs << 1) & 0x0E; + skb->data[2] |= (x25->vr << 5) & 0xE0; } - x25_transmit_link(skb, sk->protinfo.x25->neighbour); + x25_transmit_link(skb, x25->neighbour); } void x25_kick(struct sock *sk) @@ -146,34 +149,35 @@ struct sk_buff *skb, *skbn; unsigned short start, end; int modulus; + x25_cb *x25 = X25_SK(sk); - if (sk->protinfo.x25->state != X25_STATE_3) + if (x25->state != X25_STATE_3) return; /* * Transmit interrupt data. */ - if (!sk->protinfo.x25->intflag && skb_peek(&sk->protinfo.x25->interrupt_out_queue) != NULL) { - sk->protinfo.x25->intflag = 1; - skb = skb_dequeue(&sk->protinfo.x25->interrupt_out_queue); - x25_transmit_link(skb, sk->protinfo.x25->neighbour); + if (!x25->intflag && skb_peek(&x25->interrupt_out_queue) != NULL) { + x25->intflag = 1; + skb = skb_dequeue(&x25->interrupt_out_queue); + x25_transmit_link(skb, x25->neighbour); } - if (sk->protinfo.x25->condition & X25_COND_PEER_RX_BUSY) + if (x25->condition & X25_COND_PEER_RX_BUSY) return; if (skb_peek(&sk->write_queue) == NULL) return; - modulus = (sk->protinfo.x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS; + modulus = (x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS; - start = (skb_peek(&sk->protinfo.x25->ack_queue) == NULL) ? sk->protinfo.x25->va : sk->protinfo.x25->vs; - end = (sk->protinfo.x25->va + sk->protinfo.x25->facilities.winsize_out) % modulus; + start = (skb_peek(&x25->ack_queue) == NULL) ? x25->va : x25->vs; + end = (x25->va + x25->facilities.winsize_out) % modulus; if (start == end) return; - sk->protinfo.x25->vs = start; + x25->vs = start; /* * Transmit data until either we're out of data to send or @@ -195,17 +199,17 @@ */ x25_send_iframe(sk, skbn); - sk->protinfo.x25->vs = (sk->protinfo.x25->vs + 1) % modulus; + x25->vs = (x25->vs + 1) % modulus; /* * Requeue the original data frame. */ - skb_queue_tail(&sk->protinfo.x25->ack_queue, skb); + skb_queue_tail(&x25->ack_queue, skb); - } while (sk->protinfo.x25->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL); + } while (x25->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL); - sk->protinfo.x25->vl = sk->protinfo.x25->vr; - sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING; + x25->vl = x25->vr; + x25->condition &= ~X25_COND_ACK_PENDING; x25_stop_timer(sk); } @@ -217,13 +221,15 @@ void x25_enquiry_response(struct sock *sk) { - if (sk->protinfo.x25->condition & X25_COND_OWN_RX_BUSY) + x25_cb *x25 = X25_SK(sk); + + if (x25->condition & X25_COND_OWN_RX_BUSY) x25_write_internal(sk, X25_RNR); else x25_write_internal(sk, X25_RR); - sk->protinfo.x25->vl = sk->protinfo.x25->vr; - sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING; + x25->vl = x25->vr; + x25->condition &= ~X25_COND_ACK_PENDING; x25_stop_timer(sk); } Index: kernel-acme/net/x25/x25_subr.c diff -u kernel-acme/net/x25/x25_subr.c:1.1.1.2 kernel-acme/net/x25/x25_subr.c:1.1.1.2.10.2 --- kernel-acme/net/x25/x25_subr.c:1.1.1.2 Thu Aug 16 18:44:06 2001 +++ kernel-acme/net/x25/x25_subr.c Mon Dec 17 15:04:53 2001 @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -46,11 +47,13 @@ */ void x25_clear_queues(struct sock *sk) { + x25_cb *x25 = X25_SK(sk); + skb_queue_purge(&sk->write_queue); - skb_queue_purge(&sk->protinfo.x25->ack_queue); - skb_queue_purge(&sk->protinfo.x25->interrupt_in_queue); - skb_queue_purge(&sk->protinfo.x25->interrupt_out_queue); - skb_queue_purge(&sk->protinfo.x25->fragment_queue); + skb_queue_purge(&x25->ack_queue); + skb_queue_purge(&x25->interrupt_in_queue); + skb_queue_purge(&x25->interrupt_out_queue); + skb_queue_purge(&x25->fragment_queue); } @@ -62,19 +65,17 @@ void x25_frames_acked(struct sock *sk, unsigned short nr) { struct sk_buff *skb; - int modulus = sk->protinfo.x25->neighbour->extended ? X25_EMODULUS : - X25_SMODULUS; + x25_cb *x25 = X25_SK(sk); + int modulus = x25->neighbour->extended ? X25_EMODULUS : X25_SMODULUS; /* * Remove all the ack-ed frames from the ack queue. */ - if (sk->protinfo.x25->va != nr) - while (skb_peek(&sk->protinfo.x25->ack_queue) != NULL && - sk->protinfo.x25->va != nr) { - skb = skb_dequeue(&sk->protinfo.x25->ack_queue); + if (x25->va != nr) + while (skb_peek(&x25->ack_queue) && x25->va != nr) { + skb = skb_dequeue(&x25->ack_queue); kfree_skb(skb); - sk->protinfo.x25->va = (sk->protinfo.x25->va + 1) % - modulus; + x25->va = (x25->va + 1) % modulus; } } @@ -87,7 +88,7 @@ * up by x25_kick. This arrangement handles the possibility of an empty * output queue. */ - while ((skb = skb_dequeue(&sk->protinfo.x25->ack_queue)) != NULL) { + while ((skb = skb_dequeue(&X25_SK(sk)->ack_queue)) != NULL) { if (skb_prev == NULL) skb_queue_head(&sk->write_queue, skb); else @@ -102,16 +103,16 @@ */ int x25_validate_nr(struct sock *sk, unsigned short nr) { - unsigned short vc = sk->protinfo.x25->va; - int modulus = sk->protinfo.x25->neighbour->extended ? X25_EMODULUS : - X25_SMODULUS; + x25_cb *x25 = X25_SK(sk); + unsigned short vc = x25->va; + int modulus = x25->neighbour->extended ? X25_EMODULUS : X25_SMODULUS; - while (vc != sk->protinfo.x25->vs) { + while (vc != x25->vs) { if (nr == vc) return 1; vc = (vc + 1) % modulus; } - return nr == sk->protinfo.x25->vs ? 1 : 0; + return nr == x25->vs ? 1 : 0; } /* @@ -120,6 +121,7 @@ */ void x25_write_internal(struct sock *sk, int frametype) { + x25_cb *x25 = X25_SK(sk); struct sk_buff *skb; unsigned char *dptr; unsigned char facilities[X25_MAX_FAC_LEN]; @@ -173,10 +175,10 @@ */ dptr = skb_put(skb, 2); - lci1 = (sk->protinfo.x25->lci >> 8) & 0x0F; - lci2 = (sk->protinfo.x25->lci >> 0) & 0xFF; + lci1 = (x25->lci >> 8) & 0x0F; + lci2 = (x25->lci >> 0) & 0xFF; - if (sk->protinfo.x25->neighbour->extended) { + if (x25->neighbour->extended) { *dptr++ = lci1 | X25_GFI_EXTSEQ; *dptr++ = lci2; } else { @@ -192,27 +194,34 @@ case X25_CALL_REQUEST: dptr = skb_put(skb, 1); *dptr++ = X25_CALL_REQUEST; - len = x25_addr_aton(addresses, &sk->protinfo.x25->dest_addr, &sk->protinfo.x25->source_addr); + len = x25_addr_aton(addresses, &x25->dest_addr, + &x25->source_addr); dptr = skb_put(skb, len); memcpy(dptr, addresses, len); - len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities, sk->protinfo.x25->neighbour->global_facil_mask); + len = x25_create_facilities(facilities, + &x25->facilities, + x25->neighbour->global_facil_mask); dptr = skb_put(skb, len); memcpy(dptr, facilities, len); - dptr = skb_put(skb, sk->protinfo.x25->calluserdata.cudlength); - memcpy(dptr, sk->protinfo.x25->calluserdata.cuddata, sk->protinfo.x25->calluserdata.cudlength); - sk->protinfo.x25->calluserdata.cudlength = 0; + dptr = skb_put(skb, x25->calluserdata.cudlength); + memcpy(dptr, x25->calluserdata.cuddata, + x25->calluserdata.cudlength); + x25->calluserdata.cudlength = 0; break; case X25_CALL_ACCEPTED: dptr = skb_put(skb, 2); *dptr++ = X25_CALL_ACCEPTED; *dptr++ = 0x00; /* Address lengths */ - len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities, sk->protinfo.x25->vc_facil_mask); + len = x25_create_facilities(facilities, + &x25->facilities, + x25->vc_facil_mask); dptr = skb_put(skb, len); memcpy(dptr, facilities, len); - dptr = skb_put(skb, sk->protinfo.x25->calluserdata.cudlength); - memcpy(dptr, sk->protinfo.x25->calluserdata.cuddata, sk->protinfo.x25->calluserdata.cudlength); - sk->protinfo.x25->calluserdata.cudlength = 0; + dptr = skb_put(skb, x25->calluserdata.cudlength); + memcpy(dptr, x25->calluserdata.cuddata, + x25->calluserdata.cudlength); + x25->calluserdata.cudlength = 0; break; case X25_CLEAR_REQUEST: @@ -226,14 +235,14 @@ case X25_RR: case X25_RNR: case X25_REJ: - if (sk->protinfo.x25->neighbour->extended) { + if (x25->neighbour->extended) { dptr = skb_put(skb, 2); *dptr++ = frametype; - *dptr++ = (sk->protinfo.x25->vr << 1) & 0xFE; + *dptr++ = (x25->vr << 1) & 0xFE; } else { dptr = skb_put(skb, 1); *dptr = frametype; - *dptr++ |= (sk->protinfo.x25->vr << 5) & 0xE0; + *dptr++ |= (x25->vr << 5) & 0xE0; } break; @@ -245,7 +254,7 @@ break; } - x25_transmit_link(skb, sk->protinfo.x25->neighbour); + x25_transmit_link(skb, x25->neighbour); } /* @@ -275,7 +284,7 @@ return frame[2]; } - if (sk->protinfo.x25->neighbour->extended) { + if (X25_SK(sk)->neighbour->extended) { if (frame[2] == X25_RR || frame[2] == X25_RNR || frame[2] == X25_REJ) { @@ -291,7 +300,7 @@ } } - if (sk->protinfo.x25->neighbour->extended) { + if (X25_SK(sk)->neighbour->extended) { if ((frame[2] & 0x01) == X25_DATA) { *q = (frame[0] & X25_Q_BIT) == X25_Q_BIT; *d = (frame[0] & X25_D_BIT) == X25_D_BIT; @@ -320,14 +329,16 @@ void x25_disconnect(struct sock *sk, int reason, unsigned char cause, unsigned char diagnostic) { + x25_cb *x25 = X25_SK(sk); + x25_clear_queues(sk); x25_stop_timer(sk); - sk->protinfo.x25->lci = 0; - sk->protinfo.x25->state = X25_STATE_0; + x25->lci = 0; + x25->state = X25_STATE_0; - sk->protinfo.x25->causediag.cause = cause; - sk->protinfo.x25->causediag.diagnostic = diagnostic; + x25->causediag.cause = cause; + x25->causediag.diagnostic = diagnostic; sk->state = TCP_CLOSE; sk->err = reason; @@ -345,11 +356,13 @@ */ void x25_check_rbuf(struct sock *sk) { + x25_cb *x25 = X25_SK(sk); + if (atomic_read(&sk->rmem_alloc) < (sk->rcvbuf / 2) && - (sk->protinfo.x25->condition & X25_COND_OWN_RX_BUSY)) { - sk->protinfo.x25->condition &= ~X25_COND_OWN_RX_BUSY; - sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING; - sk->protinfo.x25->vl = sk->protinfo.x25->vr; + (x25->condition & X25_COND_OWN_RX_BUSY)) { + x25->condition &= ~X25_COND_OWN_RX_BUSY; + x25->condition &= ~X25_COND_ACK_PENDING; + x25->vl = x25->vr; x25_write_internal(sk, X25_RR); x25_stop_timer(sk); } Index: kernel-acme/net/x25/x25_timer.c diff -u kernel-acme/net/x25/x25_timer.c:1.1.1.1 kernel-acme/net/x25/x25_timer.c:1.1.1.1.12.2 --- kernel-acme/net/x25/x25_timer.c:1.1.1.1 Tue Jun 26 17:28:55 2001 +++ kernel-acme/net/x25/x25_timer.c Mon Dec 17 15:04:53 2001 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -60,59 +61,67 @@ void x25_start_t2timer(struct sock *sk) { - del_timer(&sk->protinfo.x25->timer); + x25_cb *x25 = X25_SK(sk); - sk->protinfo.x25->timer.data = (unsigned long)sk; - sk->protinfo.x25->timer.function = &x25_timer_expiry; - sk->protinfo.x25->timer.expires = jiffies + sk->protinfo.x25->t2; + del_timer(&x25->timer); - add_timer(&sk->protinfo.x25->timer); + x25->timer.data = (unsigned long)sk; + x25->timer.function = &x25_timer_expiry; + x25->timer.expires = jiffies + x25->t2; + + add_timer(&x25->timer); } void x25_start_t21timer(struct sock *sk) { - del_timer(&sk->protinfo.x25->timer); + x25_cb *x25 = X25_SK(sk); + + del_timer(&x25->timer); - sk->protinfo.x25->timer.data = (unsigned long)sk; - sk->protinfo.x25->timer.function = &x25_timer_expiry; - sk->protinfo.x25->timer.expires = jiffies + sk->protinfo.x25->t21; + x25->timer.data = (unsigned long)sk; + x25->timer.function = &x25_timer_expiry; + x25->timer.expires = jiffies + x25->t21; - add_timer(&sk->protinfo.x25->timer); + add_timer(&x25->timer); } void x25_start_t22timer(struct sock *sk) { - del_timer(&sk->protinfo.x25->timer); + x25_cb *x25 = X25_SK(sk); + + del_timer(&x25->timer); - sk->protinfo.x25->timer.data = (unsigned long)sk; - sk->protinfo.x25->timer.function = &x25_timer_expiry; - sk->protinfo.x25->timer.expires = jiffies + sk->protinfo.x25->t22; + x25->timer.data = (unsigned long)sk; + x25->timer.function = &x25_timer_expiry; + x25->timer.expires = jiffies + x25->t22; - add_timer(&sk->protinfo.x25->timer); + add_timer(&x25->timer); } void x25_start_t23timer(struct sock *sk) { - del_timer(&sk->protinfo.x25->timer); + x25_cb *x25 = X25_SK(sk); - sk->protinfo.x25->timer.data = (unsigned long)sk; - sk->protinfo.x25->timer.function = &x25_timer_expiry; - sk->protinfo.x25->timer.expires = jiffies + sk->protinfo.x25->t23; + del_timer(&x25->timer); - add_timer(&sk->protinfo.x25->timer); + x25->timer.data = (unsigned long)sk; + x25->timer.function = &x25_timer_expiry; + x25->timer.expires = jiffies + x25->t23; + + add_timer(&x25->timer); } void x25_stop_timer(struct sock *sk) { - del_timer(&sk->protinfo.x25->timer); + del_timer(&X25_SK(sk)->timer); } unsigned long x25_display_timer(struct sock *sk) { - if (!timer_pending(&sk->protinfo.x25->timer)) + if (!timer_pending(&X25_SK(sk)->timer)) return 0; - return sk->protinfo.x25->timer.expires - jiffies; + return X25_SK(sk)->timer.expires - jiffies; } static void x25_heartbeat_expiry(unsigned long param) @@ -124,7 +133,7 @@ goto restart_heartbeat; } - switch (sk->protinfo.x25->state) { + switch (X25_SK(sk)->state) { case X25_STATE_0: /* Magic here: If we listen() and a new link dies before it @@ -154,11 +163,13 @@ */ static inline void x25_do_timer_expiry(struct sock * sk) { - switch (sk->protinfo.x25->state) { + x25_cb *x25 = X25_SK(sk); + + switch (x25->state) { case X25_STATE_3: /* T2 */ - if (sk->protinfo.x25->condition & X25_COND_ACK_PENDING) { - sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING; + if (x25->condition & X25_COND_ACK_PENDING) { + x25->condition &= ~X25_COND_ACK_PENDING; x25_enquiry_response(sk); } break; @@ -166,7 +177,7 @@ case X25_STATE_1: /* T21 */ case X25_STATE_4: /* T22 */ x25_write_internal(sk, X25_CLEAR_REQUEST); - sk->protinfo.x25->state = X25_STATE_2; + x25->state = X25_STATE_2; x25_start_t23timer(sk); break; @@ -182,7 +193,7 @@ bh_lock_sock(sk); if (sk->lock.users) { /* can currently only occur in state 3 */ - if (sk->protinfo.x25->state == X25_STATE_3) { + if (X25_SK(sk)->state == X25_STATE_3) { x25_start_t2timer(sk); } } else {