diff -ur --new-file old/atm/.kernel new/atm/.kernel --- old/atm/.kernel Thu Aug 20 16:27:21 1998 +++ new/atm/.kernel Sun Nov 1 19:39:09 1998 @@ -1,2 +1,2 @@ # this file is used to control automated generation of differences -2.1.117 +2.1.126 diff -ur --new-file old/atm/BUGS new/atm/BUGS --- old/atm/BUGS Tue Oct 6 13:18:26 1998 +++ new/atm/BUGS Sun Nov 1 17:40:25 1998 @@ -1,13 +1,10 @@ -Known bugs and restrictions in version 0.47 +Known bugs and restrictions in version 0.49 =========================================== - - 2.1.117 kernel may not compile properly with sound enabled - ANS: libresolve conflicts with libc on some systems - ENI driver loses synchronization on some systems, leading to panics or hung VCs (these may be two distinct problems) - few if any drivers build properly as modules - - MPOA may fail on RedHat 5.x with "mpcd: changed_fds = ...", due to what - seems to be a bug in RedHat's glibc - CLIP interfaces must not be reconfigured while "up" - swc show only displays manually configured VCs - invoking a queuing discipline that overwrites skb->cb from within sch_atm diff -ur --new-file old/atm/CHANGES new/atm/CHANGES --- old/atm/CHANGES Fri Oct 30 19:52:05 1998 +++ new/atm/CHANGES Sun Nov 1 19:30:35 1998 @@ -1,3 +1,27 @@ +Version 0.48 to 0.49 (1-NOV-1998) +==================== + +Bug fixes +--------- + + - q_atm.c passed TCA_ATM_EXCESS even if zero, while the kernel expected it + to be absent in this case (changed q_atm.c) + - q_atm: tc class show didn't separate fields properly with blanks + - removed double inclusion of atm/config from mkdist + +New features +------------ + + - upgraded to the 2.1.126 kernel + +Other changes +------------- + + - "new" atmsigd is now the default (atm/sigd got renamed to atm/sigd.old, + atm/sigd.new to atm/sigd) + - updated extra/tc/README + + Version 0.47 to 0.48 (30-OCT-1998) ==================== diff -ur --new-file old/atm/Makefile new/atm/Makefile --- old/atm/Makefile Mon Oct 5 17:09:30 1998 +++ new/atm/Makefile Sun Nov 1 16:04:04 1998 @@ -3,7 +3,7 @@ # "maint" must appear after "qgen" DIRS=lib test debug qgen saal sigd maint arpd ilmid aqd man led lane mpoad \ - switch sigd.new # extra + switch sigd.old # extra all: for n in $(DIRS); do $(MAKE) -C $$n || exit; done diff -ur --new-file old/atm/README new/atm/README --- old/atm/README Thu Oct 8 18:03:39 1998 +++ new/atm/README Sun Nov 1 17:37:26 1998 @@ -1,4 +1,4 @@ -ATM on Linux, release 0.48 (alpha) by Werner Almesberger, EPFL ICA +ATM on Linux, release 0.49 (alpha) by Werner Almesberger, EPFL ICA ============================================== Werner.Almesberger@epfl.ch This is experimental software. There are known major bugs and certainly @@ -9,7 +9,7 @@ device drivers, source for demons, management and test tools, and some documentation. -The kernel patch is relative to the "standard" 2.1.117 kernel. +The kernel patch is relative to the "standard" 2.1.126 kernel. Please see http://lrcwww.epfl.ch/linux-atm/info.html for a list of features supported by ATM on Linux. diff -ur --new-file old/atm/USAGE new/atm/USAGE --- old/atm/USAGE Thu Oct 8 18:10:58 1998 +++ new/atm/USAGE Sun Nov 1 19:27:42 1998 @@ -1,4 +1,4 @@ -Usage instructions - ATM on Linux, release 0.48 +Usage instructions - ATM on Linux, release 0.49 ------------------------------------------------- For updates of ATM on Linux, please check the Web page at @@ -17,9 +17,9 @@ In order to install this package, you need - the package itself - ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.48.tar.gz - - the Linux kernel, version 2.1.117, e.g. from - ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.117.tar.gz + ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.49.tar.gz + - the Linux kernel, version 2.1.126, e.g. from + ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.126.tar.gz - Perl, version 4 or 5 - if you want memory debugging: MPR version 1.6, e.g. from ftp://sunsite.unc.edu/pub/Linux/devel/lang/c/mpr-1.6.tar.gz @@ -33,11 +33,11 @@ all the files listed above there. Then extract the ATM on Linux distribution: -tar xfz atm-0.48.tar.gz +tar xfz atm-0.49.tar.gz and the kernel source: -tar xfz linux-2.1.117.tar.gz +tar xfz linux-2.1.126.tar.gz Finally, you can extract the ATM-related patches: diff -ur --new-file old/atm/VERSION new/atm/VERSION --- old/atm/VERSION Thu Oct 8 17:26:11 1998 +++ new/atm/VERSION Sun Nov 1 19:26:21 1998 @@ -1 +1 @@ -0.48 +0.49 diff -ur --new-file old/atm/atm.patch new/atm/atm.patch --- old/atm/atm.patch Fri Oct 30 20:03:50 1998 +++ new/atm/atm.patch Sun Nov 1 19:25:59 1998 @@ -1,6 +1,6 @@ ---- ref/Makefile Wed Aug 19 07:02:21 1998 -+++ work/Makefile Fri Aug 21 00:52:27 1998 -@@ -121,6 +121,10 @@ +--- ref/Makefile Sat Oct 17 05:33:22 1998 ++++ work/Makefile Sun Nov 1 15:31:52 1998 +@@ -128,6 +128,10 @@ DRIVERS := $(DRIVERS) drivers/net/net.a @@ -11,7 +11,7 @@ ifeq ($(CONFIG_SCSI),y) DRIVERS := $(DRIVERS) drivers/scsi/scsi.a endif -@@ -301,6 +305,7 @@ +@@ -312,6 +316,7 @@ if [ -f NET_MODULES ]; then inst_mod NET_MODULES net; fi; \ if [ -f IPV4_MODULES ]; then inst_mod IPV4_MODULES ipv4; fi; \ if [ -f IPV6_MODULES ]; then inst_mod IPV6_MODULES ipv6; fi; \ @@ -19,11 +19,11 @@ if [ -f SCSI_MODULES ]; then inst_mod SCSI_MODULES scsi; fi; \ if [ -f FS_MODULES ]; then inst_mod FS_MODULES fs; fi; \ if [ -f NLS_MODULES ]; then inst_mod NLS_MODULES fs; fi; \ ---- ref/Documentation/Configure.help Wed Aug 19 23:37:58 1998 -+++ work/Documentation/Configure.help Mon Oct 5 11:48:14 1998 -@@ -3166,6 +3166,164 @@ - This is a backward compatibility option, choose Y for now. - This option will be removed soon. +--- ref/Documentation/Configure.help Thu Oct 22 00:31:04 1998 ++++ work/Documentation/Configure.help Sun Nov 1 15:31:52 1998 +@@ -3235,6 +3235,164 @@ + remember to enable the driver for your HIPPI card below). Most + people will say N here. +Asynchronous Transfer Mode (ATM) +CONFIG_ATM @@ -187,15 +187,15 @@ CONFIG_SCSI If you want to use a SCSI hard disk, SCSI tape drive, SCSI CDROM or --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/Documentation/atm.txt Fri Aug 21 00:52:27 1998 ++++ work/Documentation/atm.txt Sun Nov 1 15:31:52 1998 @@ -0,0 +1,4 @@ +In order to use anything but the most primitive functions of ATM, +several user-mode programs are required to assist the kernel. These +programs and related material can be found via the ATM on Linux Web +page at http://lrcwww.epfl.ch/linux-atm/ ---- ref/arch/i386/config.in Thu Aug 6 11:29:45 1998 -+++ work/arch/i386/config.in Fri Aug 21 00:52:27 1998 -@@ -91,6 +91,9 @@ +--- ref/arch/i386/config.in Thu Oct 1 19:02:21 1998 ++++ work/arch/i386/config.in Sun Nov 1 15:31:52 1998 +@@ -101,6 +101,9 @@ bool 'Network device support' CONFIG_NETDEVICES if [ "$CONFIG_NETDEVICES" = "y" ]; then source drivers/net/Config.in @@ -205,9 +205,9 @@ fi endmenu fi ---- ref/arch/alpha/config.in Sun Aug 9 21:09:05 1998 -+++ work/arch/alpha/config.in Fri Aug 21 00:52:27 1998 -@@ -229,6 +229,9 @@ +--- ref/arch/alpha/config.in Mon Oct 12 20:40:12 1998 ++++ work/arch/alpha/config.in Sun Nov 1 15:31:52 1998 +@@ -227,6 +227,9 @@ bool 'Network device support' CONFIG_NETDEVICES if [ "$CONFIG_NETDEVICES" = "y" ]; then source drivers/net/Config.in @@ -217,8 +217,8 @@ fi endmenu fi ---- ref/drivers/Makefile Wed Aug 5 01:49:18 1998 -+++ work/drivers/Makefile Fri Aug 21 00:52:27 1998 +--- ref/drivers/Makefile Sat Oct 3 03:12:55 1998 ++++ work/drivers/Makefile Sun Nov 1 15:31:52 1998 @@ -10,7 +10,7 @@ SUB_DIRS := block char net misc sound MOD_SUB_DIRS := $(SUB_DIRS) sbus @@ -241,7 +241,7 @@ ifeq ($(CONFIG_AP1000),y) --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/Config.in Mon Oct 5 10:36:52 1998 ++++ work/drivers/atm/Config.in Sun Nov 1 15:31:53 1998 @@ -0,0 +1,34 @@ +# +# ATM device configuration @@ -278,7 +278,7 @@ + tristate 'IDT 77201 (NICStAR)' CONFIG_ATM_NICSTAR y +fi --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/Makefile Fri Aug 21 00:52:28 1998 ++++ work/drivers/atm/Makefile Sun Nov 1 15:31:53 1998 @@ -0,0 +1,57 @@ +# File: drivers/atm/Makefile +# @@ -338,7 +338,7 @@ + +include $(TOPDIR)/Rules.make --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/atmdev_init.c Fri Aug 21 00:52:28 1998 ++++ work/drivers/atm/atmdev_init.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,48 @@ +/* drivers/atm/atmdev_init.c - ATM device driver initialization */ + @@ -389,7 +389,7 @@ + return devs; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/atmtcp.c Fri Aug 21 00:52:28 1998 ++++ work/drivers/atm/atmtcp.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,339 @@ +/* drivers/atm/atmtcp.c - ATM over TCP "device" driver */ + @@ -731,7 +731,7 @@ +#endif + --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/eni.c Mon Oct 5 12:04:10 1998 ++++ work/drivers/atm/eni.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,2250 @@ +/* drivers/atm/eni.c - Efficient Networks ENI155P device driver */ + @@ -2984,7 +2984,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/eni.h Fri Oct 30 20:09:44 1998 ++++ work/drivers/atm/eni.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,115 @@ +/* drivers/atm/eni.h - Efficient Networks ENI155P device driver declarations */ + @@ -3102,7 +3102,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/midway.h Fri Aug 21 00:52:28 1998 ++++ work/drivers/atm/midway.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,265 @@ +/* drivers/atm/midway.h - Efficient Networks Midway (SAR) description */ + @@ -3370,7 +3370,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/nicstar.h Wed Oct 7 15:02:19 1998 ++++ work/drivers/atm/nicstar.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,753 @@ +/****************************************************************************** + * @@ -4126,7 +4126,7 @@ + +#endif /* _LINUX_NICSTAR_H_ */ --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/nicstar.c Thu Oct 1 16:26:36 1998 ++++ work/drivers/atm/nicstar.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,2884 @@ +/****************************************************************************** + * @@ -7013,7 +7013,7 @@ + PRINTK("nicstar: Leaving ns_poll().\n"); +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/nicstar.c.old_skb Thu Oct 1 13:23:28 1998 ++++ work/drivers/atm/nicstar.c.old_skb Sun Nov 1 15:31:53 1998 @@ -0,0 +1,2883 @@ +/****************************************************************************** + * @@ -9899,7 +9899,7 @@ + PRINTK("nicstar: Leaving ns_poll().\n"); +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/nicstarmac.h Fri Aug 21 02:32:42 1998 ++++ work/drivers/atm/nicstarmac.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,14 @@ +/****************************************************************************** + * @@ -9916,7 +9916,7 @@ +void nicstar_init_eprom( virt_addr_t base ); +void nicstar_read_eprom( virt_addr_t, u_int8_t, u_int8_t *, u_int32_t); --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/nicstarmac.c Fri Aug 21 02:32:42 1998 ++++ work/drivers/atm/nicstarmac.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,269 @@ +/* + * this file included by nicstar.c @@ -10188,7 +10188,7 @@ +*/ + --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/nicstarmac.copyright Fri Aug 21 02:32:07 1998 ++++ work/drivers/atm/nicstarmac.copyright Sun Nov 1 15:31:53 1998 @@ -0,0 +1,61 @@ +/* nicstar.c v0.22 Jawaid Bazyar (bazyar@hypermall.com) + * nicstar.c, M. Welsh (matt.welsh@cl.cam.ac.uk) @@ -10252,7 +10252,7 @@ + * + */ --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/suni.c Fri Aug 21 00:52:28 1998 ++++ work/drivers/atm/suni.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,303 @@ +/* drivers/atm/suni.c - PMC SUNI (PHY) driver */ + @@ -10558,7 +10558,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/suni.h Fri Oct 30 20:09:41 1998 ++++ work/drivers/atm/suni.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,210 @@ +/* drivers/atm/suni.h - PMC SUNI (PHY) declarations */ + @@ -10771,7 +10771,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/tonga.h Fri Aug 21 00:52:28 1998 ++++ work/drivers/atm/tonga.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,20 @@ +/* drivers/atm/tonga.h - Efficient Networks Tonga (PCI bridge) declarations */ + @@ -10794,7 +10794,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/uPD98401.h Fri Aug 21 00:52:28 1998 ++++ work/drivers/atm/uPD98401.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,292 @@ +/* drivers/atm/uPD98401.h - NEC uPD98401 (SAR) declarations */ + @@ -11089,7 +11089,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/uPD98402.c Fri Aug 21 00:52:28 1998 ++++ work/drivers/atm/uPD98402.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,224 @@ +/* drivers/atm/uPD98402.c - NEC uPD98402 (PHY) declarations */ + @@ -11316,7 +11316,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/uPD98402.h Fri Aug 21 00:52:28 1998 ++++ work/drivers/atm/uPD98402.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,106 @@ +/* drivers/atm/uPD98402.h - NEC uPD98402 (PHY) declarations */ + @@ -11425,7 +11425,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/zatm.c Mon Oct 5 11:53:41 1998 ++++ work/drivers/atm/zatm.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,1875 @@ +/* drivers/atm/zatm.c - ZeitNet ZN122x device driver */ + @@ -13303,7 +13303,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/zatm.h Fri Oct 30 20:09:47 1998 ++++ work/drivers/atm/zatm.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,137 @@ +/* drivers/atm/zatm.h - ZeitNet ZN122x device driver declarations */ + @@ -13443,7 +13443,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/zeprom.h Fri Aug 21 00:52:28 1998 ++++ work/drivers/atm/zeprom.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,34 @@ +/* drivers/atm/zeprom.h - ZeitNet ZN122x EEPROM (NM93C46) declarations */ + @@ -13479,9 +13479,9 @@ +/* No other commands are needed. */ + +#endif ---- ref/drivers/block/genhd.c Sun Aug 16 20:48:40 1998 -+++ work/drivers/block/genhd.c Fri Aug 21 00:52:28 1998 -@@ -58,6 +58,7 @@ +--- ref/drivers/block/genhd.c Tue Oct 20 22:52:01 1998 ++++ work/drivers/block/genhd.c Sun Nov 1 15:31:53 1998 +@@ -60,6 +60,7 @@ extern int blk_dev_init(void); extern int scsi_dev_init(void); extern int net_dev_init(void); @@ -13489,7 +13489,7 @@ /* * disk_name() is used by genhd.c and md.c. -@@ -1124,6 +1125,9 @@ +@@ -1207,6 +1208,9 @@ #endif #ifdef CONFIG_INET net_dev_init(); @@ -13500,7 +13500,7 @@ #ifdef CONFIG_VT console_map_init(); --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/arequipa.h Fri Oct 30 20:10:11 1998 ++++ work/include/linux/arequipa.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,63 @@ +/* arequipa.h - Arequipa interface definitions */ + @@ -13566,7 +13566,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atm.h Fri Oct 30 20:09:41 1998 ++++ work/include/linux/atm.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,239 @@ +/* atm.h - general ATM declarations */ + @@ -13808,7 +13808,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atm_eni.h Fri Aug 21 00:52:28 1998 ++++ work/include/linux/atm_eni.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,15 @@ +/* atm_eni.h - Driver-specific declarations of the ENI driver (for use by + driver-specific utilities) */ @@ -13826,7 +13826,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atm_nicstar.h Fri Aug 21 02:32:42 1998 ++++ work/include/linux/atm_nicstar.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,52 @@ +/****************************************************************************** + * @@ -13881,7 +13881,7 @@ + +#endif /* LINUX_ATM_NICSTAR_H */ --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atm_suni.h Fri Aug 21 00:52:28 1998 ++++ work/include/linux/atm_suni.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,19 @@ +/* atm_suni.h - Driver-specific declarations of the SUNI driver (for use by + driver-specific utilities) */ @@ -13903,7 +13903,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atm_tcp.h Fri Aug 21 00:52:28 1998 ++++ work/include/linux/atm_tcp.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,46 @@ +/* atm_tcp.h - Driver-specific declarations of the ATMTCP driver (for use by + driver-specific utilities) */ @@ -13952,7 +13952,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atm_zatm.h Fri Aug 21 00:52:28 1998 ++++ work/include/linux/atm_zatm.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,54 @@ +/* atm_zatm.h - Driver-specific declarations of the ZATM driver (for use by + driver-specific utilities) */ @@ -14009,7 +14009,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmarp.h Fri Aug 21 00:52:28 1998 ++++ work/include/linux/atmarp.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,42 @@ +/* atmarp.h - ATM ARP protocol and kernel-demon interface definitions */ + @@ -14054,7 +14054,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmclip.h Fri Aug 21 00:52:28 1998 ++++ work/include/linux/atmclip.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,25 @@ +/* atmclip.h - Classical IP over ATM */ + @@ -14082,7 +14082,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmdev.h Fri Oct 30 20:09:41 1998 ++++ work/include/linux/atmdev.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,324 @@ +/* atmdev.h - ATM device driver declarations */ + @@ -14409,7 +14409,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmioc.h Fri Aug 21 00:52:28 1998 ++++ work/include/linux/atmioc.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,39 @@ +/* atmioc.h - ranges for ATM-related ioctl numbers */ + @@ -14451,7 +14451,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmlec.h Fri Oct 30 20:10:11 1998 ++++ work/include/linux/atmlec.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,70 @@ +/* + * @@ -14524,7 +14524,7 @@ +}; +#endif /* _ATMLEC_H_ */ --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmmpc.h Fri Oct 30 20:10:11 1998 ++++ work/include/linux/atmmpc.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,99 @@ +#ifndef _ATMMPC_H_ +#define _ATMMPC_H_ @@ -14626,7 +14626,7 @@ +#endif /* _ATMMPC_H_ */ + --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmsap.h Fri Oct 30 18:49:44 1998 ++++ work/include/linux/atmsap.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,161 @@ +/* atmsap.h - ATM Service Access Point addressing definitions */ + @@ -14790,7 +14790,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmsvc.h Fri Oct 30 20:10:11 1998 ++++ work/include/linux/atmsvc.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,52 @@ +/* atmsvc.h - ATM signaling kernel-demon interface definitions */ + @@ -14844,9 +14844,9 @@ + (tp).max_pcr : (tp).min_pcr ? (tp).min_pcr : ATM_MAX_PCR) + +#endif ---- ref/include/linux/capability.h Thu Aug 20 01:38:43 1998 -+++ work/include/linux/capability.h Sun Oct 11 23:59:08 1998 -@@ -121,6 +121,7 @@ +--- ref/include/linux/capability.h Fri Oct 23 19:14:47 1998 ++++ work/include/linux/capability.h Sun Nov 1 15:34:05 1998 +@@ -131,6 +131,7 @@ #define CAP_LINUX_IMMUTABLE 9 /* Allows binding to TCP/UDP sockets below 1024 */ @@ -14854,7 +14854,7 @@ #define CAP_NET_BIND_SERVICE 10 -@@ -140,6 +141,7 @@ +@@ -150,6 +151,7 @@ /* Allow clearing driver statistics */ /* Allow multicasting */ /* Allow read/write of device-specific registers */ @@ -14862,8 +14862,8 @@ #define CAP_NET_ADMIN 12 ---- ref/include/linux/if_arp.h Thu Aug 20 01:38:57 1998 -+++ work/include/linux/if_arp.h Mon Oct 12 00:00:25 1998 +--- ref/include/linux/if_arp.h Fri Oct 23 19:16:30 1998 ++++ work/include/linux/if_arp.h Sun Nov 1 15:31:53 1998 @@ -35,6 +35,7 @@ #define ARPHRD_ARCNET 7 /* ARCnet */ #define ARPHRD_APPLETLK 8 /* APPLEtalk */ @@ -14883,7 +14883,7 @@ /* ARP ioctl request. */ --- ref/include/linux/pkt_sched.h Tue Apr 28 20:10:10 1998 -+++ work/include/linux/pkt_sched.h Wed Sep 16 15:56:51 1998 ++++ work/include/linux/pkt_sched.h Sun Nov 1 15:31:53 1998 @@ -274,4 +274,17 @@ #define TCA_CBQ_MAX TCA_CBQ_POLICE @@ -14902,11 +14902,11 @@ +#define TCA_ATM_MAX TCA_ATM_ADDR + #endif ---- ref/include/linux/skbuff.h Thu Aug 20 01:38:56 1998 -+++ work/include/linux/skbuff.h Sun Oct 11 23:59:14 1998 -@@ -106,6 +106,25 @@ - __u32 shapestamp; /* Stamp for shaper */ - __u16 shapepend; /* Pending */ +--- ref/include/linux/skbuff.h Fri Oct 23 19:15:48 1998 ++++ work/include/linux/skbuff.h Sun Nov 1 15:34:09 1998 +@@ -112,6 +112,25 @@ + __u32 ifield; + } private; #endif +#if defined(CONFIG_ATM) && !defined(CONFIG_ATM_SKB) + @@ -14931,7 +14931,7 @@ /* These are just the default values. This is run time configurable. --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/sonet.h Fri Aug 21 00:52:29 1998 ++++ work/include/linux/sonet.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,52 @@ +/* sonet.h - SONET/SHD physical layer control */ + @@ -14986,7 +14986,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/net/atmclip.h Fri Oct 30 20:10:05 1998 ++++ work/include/net/atmclip.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,62 @@ +/* net/atm/atmarp.h - RFC1577 ATM ARP */ + @@ -15050,9 +15050,9 @@ +int clip_encap(struct atm_vcc *vcc,int mode); + +#endif ---- ref/net/Config.in Mon Jun 8 19:02:34 1998 -+++ work/net/Config.in Thu Oct 1 16:52:42 1998 -@@ -23,6 +23,27 @@ +--- ref/net/Config.in Sun Sep 13 19:22:17 1998 ++++ work/net/Config.in Sun Nov 1 15:31:53 1998 +@@ -25,6 +25,27 @@ fi fi fi @@ -15081,7 +15081,7 @@ comment ' ' tristate 'The IPX protocol' CONFIG_IPX --- ref/net/Makefile Mon Jul 27 08:35:57 1998 -+++ work/net/Makefile Fri Aug 21 00:52:29 1998 ++++ work/net/Makefile Sun Nov 1 15:31:53 1998 @@ -10,7 +10,7 @@ MOD_SUB_DIRS := ipv4 ALL_SUB_DIRS := 802 ax25 bridge core ethernet ipv4 ipv6 ipx unix appletalk \ @@ -15110,7 +15110,7 @@ ifeq ($(CONFIG_DECNET),y) --- ref/net/protocols.c Fri Jul 10 22:51:41 1998 -+++ work/net/protocols.c Fri Aug 21 00:52:29 1998 ++++ work/net/protocols.c Sun Nov 1 15:31:53 1998 @@ -79,6 +79,10 @@ extern void rif_init(struct net_proto *); #endif @@ -15134,8 +15134,8 @@ #ifdef NEED_LLC { "802.2LLC", llc_init }, /* 802.2 LLC */ ---- ref/net/ipv4/arp.c Sun Aug 9 21:23:47 1998 -+++ work/net/ipv4/arp.c Fri Aug 21 00:52:29 1998 +--- ref/net/ipv4/arp.c Wed Oct 7 20:13:49 1998 ++++ work/net/ipv4/arp.c Sun Nov 1 15:31:53 1998 @@ -115,6 +115,9 @@ #include #endif @@ -15160,7 +15160,7 @@ } --- ref/net/sched/Config.in Thu May 14 19:26:23 1998 -+++ work/net/sched/Config.in Fri Aug 21 00:52:29 1998 ++++ work/net/sched/Config.in Sun Nov 1 15:31:53 1998 @@ -7,6 +7,9 @@ tristate 'CSZ packet scheduler' CONFIG_NET_SCH_CSZ #tristate 'H-PFQ packet scheduler' CONFIG_NET_SCH_HPFQ @@ -15172,7 +15172,7 @@ tristate 'RED queue' CONFIG_NET_SCH_RED tristate 'SFQ queue' CONFIG_NET_SCH_SFQ --- ref/net/sched/Makefile Tue Apr 28 20:10:11 1998 -+++ work/net/sched/Makefile Fri Aug 21 00:52:29 1998 ++++ work/net/sched/Makefile Sun Nov 1 15:31:53 1998 @@ -7,6 +7,8 @@ # # Note 2! The CFLAGS definition is now in the main makefile... @@ -15193,9 +15193,9 @@ endif ifeq ($(CONFIG_NET_CLS_U32), y) ---- ref/net/sched/sch_api.c Sat Jul 18 20:48:24 1998 -+++ work/net/sched/sch_api.c Fri Aug 21 00:52:29 1998 -@@ -983,6 +983,9 @@ +--- ref/net/sched/sch_api.c Fri Aug 28 04:33:09 1998 ++++ work/net/sched/sch_api.c Sun Nov 1 15:31:53 1998 +@@ -987,6 +987,9 @@ #ifdef CONFIG_NET_SCH_PRIO INIT_QDISC(prio); #endif @@ -15206,7 +15206,7 @@ tc_filter_init(); #endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/sched/sch_atm.c Thu Oct 29 16:29:26 1998 ++++ work/net/sched/sch_atm.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,611 @@ +/* net/sched/sch_atm.c - ATM VC selection "queueing discipline" */ + @@ -15820,7 +15820,7 @@ +} +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/Makefile Fri Aug 21 00:52:29 1998 ++++ work/net/atm/Makefile Sun Nov 1 15:31:53 1998 @@ -0,0 +1,64 @@ +# +# Makefile for the ATM Protocol Families. @@ -15887,7 +15887,7 @@ +mpoa.o: mpc.o mpoa_caches.o mpoa_proc.o + ld -r -o mpoa.o mpc.o mpoa_caches.o mpoa_proc.o --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/addr.c Fri Aug 21 00:52:29 1998 ++++ work/net/atm/addr.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,159 @@ +/* net/atm/addr.c - Local ATM address registry */ + @@ -16049,7 +16049,7 @@ + return total; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/addr.h Fri Oct 30 20:10:11 1998 ++++ work/net/atm/addr.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,18 @@ +/* net/atm/addr.h - Local ATM address registry */ + @@ -16070,7 +16070,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/clip.c Thu Oct 1 16:32:00 1998 ++++ work/net/atm/clip.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,652 @@ +/* net/atm/clip.c - RFC1577 Classical IP over ATM */ + @@ -16725,7 +16725,7 @@ + return 0; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/common.c Thu Oct 29 16:03:28 1998 ++++ work/net/atm/common.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,926 @@ +/* net/atm/common.c - ATM sockets (common part for PVC and SVC) */ + @@ -17654,7 +17654,7 @@ + return atm_do_getsockopt(sock,level,optname,optval,len); +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/common.h Mon Oct 12 00:09:43 1998 ++++ work/net/atm/common.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,46 @@ +/* net/atm/common.h - ATM sockets (common part for PVC and SVC) */ + @@ -17703,7 +17703,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/ipcommon.c Fri Aug 21 00:52:29 1998 ++++ work/net/atm/ipcommon.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,52 @@ +/* net/atm/ipcommon.c - Common items for all ways of doing IP over ATM */ + @@ -17758,7 +17758,7 @@ + skb_queue_head_init(from); +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/ipcommon.h Fri Oct 30 20:10:16 1998 ++++ work/net/atm/ipcommon.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,21 @@ +/* net/atm/ipcommon.h - Common items for all ways of doing IP over ATM */ + @@ -17782,7 +17782,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/misc.c Thu Sep 24 19:42:05 1998 ++++ work/net/atm/misc.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,184 @@ +/* net/atm/misc.c - Various functions for use by ATM drivers */ + @@ -17969,7 +17969,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/lec.c Mon Oct 5 13:19:34 1998 ++++ work/net/atm/lec.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,1992 @@ +/* + * lec.c: Lan Emulation driver @@ -19964,7 +19964,7 @@ +} + --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/lec.h Fri Oct 30 20:10:11 1998 ++++ work/net/atm/lec.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,143 @@ +/* + * @@ -20110,7 +20110,7 @@ +#endif _LEC_H_ + --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/lec_arpc.h Fri Oct 30 20:10:11 1998 ++++ work/net/atm/lec_arpc.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,112 @@ +/* + * Lec arp cache @@ -20225,7 +20225,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/mpc.c Fri Oct 30 19:58:28 1998 ++++ work/net/atm/mpc.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,1485 @@ +#include +#include @@ -21713,7 +21713,7 @@ + + --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/mpc.h Fri Oct 30 20:10:11 1998 ++++ work/net/atm/mpc.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,89 @@ +#ifndef _MPC_H_ +#define _MPC_H_ @@ -21805,7 +21805,7 @@ + +#endif /* _MPC_H_ */ --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/mpoa_caches.c Mon Oct 5 13:19:34 1998 ++++ work/net/atm/mpoa_caches.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,557 @@ +#include +#include @@ -22365,7 +22365,7 @@ + return; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/mpoa_caches.h Fri Oct 30 20:10:11 1998 ++++ work/net/atm/mpoa_caches.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,90 @@ +#ifndef MPOA_CACHES_H +#define MPOA_CACHES_H @@ -22458,7 +22458,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/mpoa_proc.c Fri Oct 30 19:58:49 1998 ++++ work/net/atm/mpoa_proc.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,388 @@ +#include + @@ -22849,7 +22849,7 @@ + + --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/lane_mpoa_init.c Fri Aug 21 00:52:30 1998 ++++ work/net/atm/lane_mpoa_init.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,48 @@ +#include +#include @@ -22900,7 +22900,7 @@ +} +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/proc.c Fri Aug 21 00:52:30 1998 ++++ work/net/atm/proc.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,610 @@ +/* net/atm/proc.c - ATM /proc interface */ + @@ -23513,7 +23513,7 @@ + return error; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/protocols.h Fri Aug 21 00:52:30 1998 ++++ work/net/atm/protocols.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,16 @@ +/* net/atm/protocols.h - ATM protocol handler entry points */ + @@ -23532,7 +23532,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/pvc.c Fri Aug 21 00:52:30 1998 ++++ work/net/atm/pvc.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,158 @@ +/* net/atm/pvc.c - ATM PVC sockets */ + @@ -23693,7 +23693,7 @@ +#endif +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/raw.c Thu Oct 1 16:48:19 1998 ++++ work/net/atm/raw.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,80 @@ +/* net/atm/raw.c - Raw AAL0 and AAL5 transports */ + @@ -23776,7 +23776,7 @@ + return 0; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/resources.c Fri Aug 21 00:52:30 1998 ++++ work/net/atm/resources.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,186 @@ +/* net/atm/resources.c - Staticly allocated resources */ + @@ -23965,7 +23965,7 @@ +EXPORT_SYMBOL(shutdown_atm_dev); +EXPORT_SYMBOL(bind_vcc); --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/resources.h Fri Oct 30 20:10:11 1998 ++++ work/net/atm/resources.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,32 @@ +/* net/atm/resources.h - ATM-related resources */ + @@ -24000,7 +24000,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/signaling.c Fri Aug 21 00:52:30 1998 ++++ work/net/atm/signaling.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,252 @@ +/* net/atm/signaling.c - ATM signaling */ + @@ -24255,7 +24255,7 @@ + return 0; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/signaling.h Fri Oct 30 20:10:11 1998 ++++ work/net/atm/signaling.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,25 @@ +/* net/atm/signaling.h - ATM signaling */ + @@ -24283,7 +24283,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/svc.c Fri Aug 21 00:52:30 1998 ++++ work/net/atm/svc.c Sun Nov 1 15:31:53 1998 @@ -0,0 +1,387 @@ +/* net/atm/svc.c - ATM SVC sockets */ + @@ -24673,7 +24673,7 @@ + } +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/tunable.h Fri Aug 21 00:52:30 1998 ++++ work/net/atm/tunable.h Sun Nov 1 15:31:53 1998 @@ -0,0 +1,26 @@ +/* net/atm/tunable.h - Tunable parameters of ATM support */ + @@ -24701,9 +24701,9 @@ + quota per PDU */ + +#endif ---- ref/net/core/skbuff.c Wed Aug 19 02:02:57 1998 -+++ work/net/core/skbuff.c Thu Oct 1 17:29:09 1998 -@@ -59,6 +59,10 @@ +--- ref/net/core/skbuff.c Tue Sep 15 07:52:10 1998 ++++ work/net/core/skbuff.c Sun Nov 1 15:31:53 1998 +@@ -61,6 +61,10 @@ #include #include @@ -24714,7 +24714,7 @@ /* * Skb list spinlock */ -@@ -159,6 +163,14 @@ +@@ -161,6 +165,14 @@ skb->len = 0; skb->is_clone = 0; skb->cloned = 0; diff -ur --new-file old/atm/doc/usage.tex new/atm/doc/usage.tex --- old/atm/doc/usage.tex Thu Oct 8 18:10:52 1998 +++ new/atm/doc/usage.tex Sun Nov 1 17:38:13 1998 @@ -1,7 +1,7 @@ %%def%:= %:\begin{verbatim} -%:Usage instructions - ATM on Linux, release 0.48 +%:Usage instructions - ATM on Linux, release 0.49 %:------------------------------------------------- %: %:\end{verbatim} @@ -38,14 +38,14 @@ \title{ATM on Linux \\ User's guide \\ - Release 0.48 (alpha)} + Release 0.49 (alpha)} \author{Werner Almesberger \\ {\tt Werner.Almesberger@epfl.ch} \\ \\ Institute for computer Communications and Applications (ICA) \\ EPFL, CH-1015 Lausanne, Switzerland} -\date{October 6, 1998} +\date{November 1, 1998} \begin{document} \maketitle @@ -82,9 +82,9 @@ In order to install this package, you need \begin{itemize} \item the package itself - \url{ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.48.tar.gz} - \item the Linux kernel, version 2.1.117, e.g. from - \url{ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.117.tar.gz} + \url{ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.49.tar.gz} + \item the Linux kernel, version 2.1.126, e.g. from + \url{ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.126.tar.gz} \item Perl, version 4 or 5 \item if you want memory debugging: MPR version 1.6, e.g. from \url{ftp://sunsite.unc.edu/pub/Linux/devel/lang/c/mpr-1.6.tar.gz} @@ -99,13 +99,13 @@ distribution: \begin{verbatim} -tar xfz atm-0.48.tar.gz +tar xfz atm-0.49.tar.gz \end{verbatim} and the kernel source: \begin{verbatim} -tar xfz linux-2.1.117.tar.gz +tar xfz linux-2.1.126.tar.gz \end{verbatim} Finally, you can extract the ATM-related patches: diff -ur --new-file old/atm/doc/usage.txt new/atm/doc/usage.txt --- old/atm/doc/usage.txt Thu Oct 8 18:10:58 1998 +++ new/atm/doc/usage.txt Sun Nov 1 19:27:42 1998 @@ -1,4 +1,4 @@ -Usage instructions - ATM on Linux, release 0.48 +Usage instructions - ATM on Linux, release 0.49 ------------------------------------------------- For updates of ATM on Linux, please check the Web page at @@ -17,9 +17,9 @@ In order to install this package, you need - the package itself - ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.48.tar.gz - - the Linux kernel, version 2.1.117, e.g. from - ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.117.tar.gz + ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.49.tar.gz + - the Linux kernel, version 2.1.126, e.g. from + ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.126.tar.gz - Perl, version 4 or 5 - if you want memory debugging: MPR version 1.6, e.g. from ftp://sunsite.unc.edu/pub/Linux/devel/lang/c/mpr-1.6.tar.gz @@ -33,11 +33,11 @@ all the files listed above there. Then extract the ATM on Linux distribution: -tar xfz atm-0.48.tar.gz +tar xfz atm-0.49.tar.gz and the kernel source: -tar xfz linux-2.1.117.tar.gz +tar xfz linux-2.1.126.tar.gz Finally, you can extract the ATM-related patches: diff -ur --new-file old/atm/extra/tc/README new/atm/extra/tc/README --- old/atm/extra/tc/README Wed Sep 16 15:49:51 1998 +++ new/atm/extra/tc/README Sun Nov 1 18:34:29 1998 @@ -13,19 +13,23 @@ 2. Build the kernel. -3. Download iproute2-2.1.99-now-ss980630.tar.gz either from +3. Download iproute2-2.1.99-now-ss981002.tar.gz either from ftp://ftp.inr.ac.ru/ip-routing/ or one of its mirrors, or from ftp://lrcftp.epfl.ch/pub/people/almesber/misc/ 4. Add the ATM queuing discipline to "tc" (assuming that we're in atm/extra/tc): - - tar xvfz iproute2-2.1.99-now-ss980630.tar.gz + - tar xvfz iproute2-2.1.99-now-ss981002.tar.gz - cd iproute2/tc - patch -s -p2 <../../Makefile.patch - cp ../../q_atm.c . 5. Build tc: - cd .. + - edit Makefile to adjust KERNEL_INCLUDE, and maybe also to change the + library definitions + - if using glibc 2, remove "ip" from SUBDIRS in Makefile, and delete both + references to IPPROTO_PIM in tc/f_rsvp.o - make - cd tc diff -ur --new-file old/atm/extra/tc/q_atm.c new/atm/extra/tc/q_atm.c --- old/atm/extra/tc/q_atm.c Wed Sep 16 15:50:24 1998 +++ new/atm/extra/tc/q_atm.c Sun Nov 1 19:08:21 1998 @@ -49,7 +49,7 @@ struct atm_qos qos; struct atm_sap sap; unsigned char hdr[MAX_HDR_LEN]; - __u32 excess; + __u32 excess = 0; struct rtattr *tail; int hdr_len = -1; int s; @@ -151,7 +151,7 @@ tail = (struct rtattr *) (((void *) n)+NLMSG_ALIGN(n->nlmsg_len)); addattr_l(n,1024,TCA_OPTIONS,NULL,0); addattr_l(n,1024,TCA_ATM_FD,&s,sizeof(s)); - addattr_l(n,1024,TCA_ATM_EXCESS,&excess,sizeof(excess)); + if (excess) addattr_l(n,1024,TCA_ATM_EXCESS,&excess,sizeof(excess)); if (hdr_len != -1) addattr_l(n,1024,TCA_ATM_HDR,hdr,hdr_len); tail->rta_len = (((void *) n)+NLMSG_ALIGN(n->nlmsg_len))-(void *) tail; return 0; @@ -175,7 +175,7 @@ if (atm2text(buffer,MAX_ATM_ADDR_LEN, RTA_DATA(tb[TCA_ATM_ADDR]),A2T_PRETTY | A2T_NAME) < 0) fprintf(stderr,"atm2text error\n"); - fprintf(f,"pvc %s",buffer); + fprintf(f,"pvc %s ",buffer); } if (tb[TCA_ATM_HDR]) { int i; @@ -185,6 +185,7 @@ fprintf(f,"%c%02x",i ? '.' : ' ', ((unsigned char *) RTA_DATA(tb[TCA_ATM_HDR]))[i]); if (!i) fprintf(f," ."); + fprintf(f," "); } if (tb[TCA_ATM_EXCESS]) { __u32 excess; diff -ur --new-file old/atm/mkdist new/atm/mkdist --- old/atm/mkdist Fri Oct 30 19:50:19 1998 +++ new/atm/mkdist Sun Nov 1 19:30:02 1998 @@ -20,20 +20,21 @@ atm/doc/README atm/doc/usage.tex atm/doc/usage.txt atm/doc/url.sty \ atm/doc/Makefile atm/doc/rlatex atm/doc/t2a.pl atm/doc/README.CLP \ atm/man/Makefile atm/man/qos.7 atm/man/sap.7 \ - atm/sigd/Makefile atm/sigd/atmsigd.c atm/sigd/cfg.l atm/sigd/cfg.y \ - atm/sigd/io.h atm/sigd/io.c atm/sigd/kernel.c atm/sigd/proto.h \ - atm/sigd/proto.c atm/sigd/uni.c atm/sigd/timeout.c atm/sigd/timeout.h \ - atm/sigd/sap.h atm/sigd/sap.c atm/sigd/trace.c atm/sigd/trace.h \ - atm/sigd/policy.h atm/sigd/policy.c \ + atm/sigd.old/Makefile atm/sigd.old/atmsigd.c atm/sigd.old/cfg.l \ + atm/sigd.old/cfg.y atm/sigd.old/io.h atm/sigd.old/io.c \ + atm/sigd.old/kernel.c atm/sigd.old/proto.h atm/sigd.old/proto.c \ + atm/sigd.old/uni.c atm/sigd.old/timeout.c atm/sigd.old/timeout.h \ + atm/sigd.old/sap.h atm/sigd.old/sap.c atm/sigd.old/trace.c \ + atm/sigd.old/trace.h atm/sigd.old/policy.h atm/sigd.old/policy.c \ + atm/sigd.old/mkmess.pl atm/sigd.old/atmsigd.8 atm/sigd.old/atmsigd.conf.4 \ + atm/sigd/README \ + atm/sigd/Makefile atm/sigd/atmsigd.c atm/sigd/cfg.l \ + atm/sigd/cfg.y atm/sigd/io.h atm/sigd/io.c \ + atm/sigd/kernel.c atm/sigd/proto.h atm/sigd/proto.c \ + atm/sigd/uni.c atm/sigd/timeout.c atm/sigd/timeout.h \ + atm/sigd/sap.h atm/sigd/sap.c atm/sigd/trace.c \ + atm/sigd/trace.h atm/sigd/policy.h atm/sigd/policy.c \ atm/sigd/mkmess.pl atm/sigd/atmsigd.8 atm/sigd/atmsigd.conf.4 \ - atm/sigd.new/README \ - atm/sigd.new/Makefile atm/sigd.new/atmsigd.c atm/sigd.new/cfg.l \ - atm/sigd.new/cfg.y atm/sigd.new/io.h atm/sigd.new/io.c \ - atm/sigd.new/kernel.c atm/sigd.new/proto.h atm/sigd.new/proto.c \ - atm/sigd.new/uni.c atm/sigd.new/timeout.c atm/sigd.new/timeout.h \ - atm/sigd.new/sap.h atm/sigd.new/sap.c atm/sigd.new/trace.c \ - atm/sigd.new/trace.h atm/sigd.new/policy.h atm/sigd.new/policy.c \ - atm/sigd.new/mkmess.pl atm/sigd.new/atmsigd.8 atm/sigd.new/atmsigd.conf.4 \ atm/saal/Makefile atm/saal/saal.h atm/saal/saal.c atm/saal/sscf.h \ atm/saal/sscf.c atm/saal/sscop.h atm/saal/sscop.c atm/saal/queue.h \ atm/saal/queue.c atm/saal/pdu.h atm/saal/pdu.c \ @@ -133,7 +134,7 @@ atm/extra/extra.html atm/extra/Makefile atm/extra/tcpdump-3.0.4-1.patch \ atm/extra/bind-4.9.5-REL.patch atm/extra/hosts2ans.pl \ atm/extra/tc/README atm/extra/tc/Makefile.patch atm/extra/tc/q_atm.c \ - atm/config/README atm/config/Makefile atm/config\ + atm/config/README atm/config/Makefile \ atm/config/common/README atm/config/common/Makefile \ atm/config/common/hosts.atm atm/config/common/e164_cc \ atm/config/redhat-4.0/README atm/config/redhat-4.0/Makefile \ diff -ur --new-file old/atm/sigd/README new/atm/sigd/README --- old/atm/sigd/README Thu Jan 1 01:00:00 1970 +++ new/atm/sigd/README Fri Aug 21 00:47:03 1998 @@ -0,0 +1,25 @@ +This is a very early version of atmsigd that supports multiple signaling +entities in the same process. Everything's still a bit buggy and ugly. + +To play with it, ... + +1) Generate ATM interfaces 1 and 2: + # atmtcp -b -i 1 -l + # atmtcp -b -i 2 -c localhost +2) Create the following configuration file (name "config"): + entity 1.0.5 { mode user route +1 } + entity 2.0.5 { mode network default } +3) Launch atmsigd: + # ./atmsigd.new -c config +4) Add local addresses: + # atmaddr -a 1 +1 + # atmaddr -a 2 +2 +5) Test it: + % ttcp_atm -r -a + % ttcp_atm -t -a +1 + +Known bugs: + - wildcard bind removes wildcard + - selection of local address isn't consistent with signaling interface + selection + - everything else that's marked with @@@ diff -ur --new-file old/atm/sigd/atmsigd.c new/atm/sigd/atmsigd.c --- old/atm/sigd/atmsigd.c Mon Oct 5 17:52:08 1998 +++ new/atm/sigd/atmsigd.c Sun Nov 1 19:41:18 1998 @@ -31,68 +31,82 @@ int debug = 0; int pretty = A2T_PRETTY | A2T_NAME | A2T_LOCAL; -int sig_pcr = -1; /* obsolete */ -const char *sig_qos = NULL; const char *dump_dir = NULL; -SIGNALING_MODE mode = sm_user; -int net = 0; -int allocate_ci = 1; +/* A little hack until we have full support for multiple signaling entities */ -/* ------------------------------ SAAL relays ------------------------------ */ +SIG_ENTITY _entity = { + 0, /* fd */ + 0, /* unspecified UNI version */ + sm_user, /* mode */ + -1, /* sig_pcr; obsolete @@@ */ + NULL /* sig_qos */ +}; -static SAAL_DSC saal; +/* ------------------------------ SAAL relays ------------------------------ */ static void q_estab_conf(void *user_data,void *uu_data,int uu_length) { - saal_okay(); + SIG_ENTITY *sig = user_data; + + saal_okay(sig); } static void q_rel_ind(void *user_data,void *uu_data,int uu_length) { - saal_failure(); - saal_estab_req(&saal,NULL,0); + SIG_ENTITY *sig = user_data; + + saal_failure(sig); + saal_estab_req(&sig->saal,NULL,0); } static void q_restart(void *user_data,void *uu_data,int uu_length,int ind) { - saal_failure(); - if (!ind) saal_okay(); /* actually, ind should probably never be zero */ + SIG_ENTITY *sig = user_data; + + saal_failure(sig); + if (!ind) saal_okay(sig); + /* actually, ind should probably never be zero */ } -void from_net(void *buffer,int size) +void from_net(SIG_ENTITY *sig,void *buffer,int size) { - saal_pdu(&saal,buffer,size); + saal_pdu(&sig->saal,buffer,size); } -void to_signaling(void *msg,int size) +void to_signaling(SIG_ENTITY *sig,void *msg,int size) { - trace_uni("TO NETWORK",msg,size); - diag(COMPONENT,DIAG_DEBUG,"TO SAAL: %s (0x%02x) CR 0x%06x (%d bytes)", + trace_uni("TO NETWORK",sig,msg,size); + diag(COMPONENT,DIAG_DEBUG,"TO SAAL (%d.%d.%d): %s (0x%02x) CR 0x%06x " + "(%d bytes)",S_PVC(sig), mid2name(((unsigned char *) msg)[5]),((unsigned char *) msg)[5], (((unsigned char *) msg)[2] << 16) | (((unsigned char *) msg)[3] << 8) | ((unsigned char *) msg)[4],size); - saal_send(&saal,msg,size); + saal_send(&sig->saal,msg,size); } static void q_data_ind(void *user_data,void *data,int length) { - trace_uni("FROM NETWORK",data,length); - to_uni(data,length); + SIG_ENTITY *sig = user_data; + + trace_uni("FROM NETWORK",sig,data,length); + to_uni(sig,data,length); } static void q_cpcs_send(void *user_data,void *data,int length) { - to_net(data,length); + SIG_ENTITY *sig = user_data; + + to_net(sig,data,length); } @@ -151,16 +165,20 @@ static void dump_status(FILE *file,const char *banner) { + SIG_ENTITY *sig; SOCKET *walk; - if (sockets) fprintf(file,"%s\n\n",banner); - for (walk = sockets; walk; walk = walk->next) { - fprintf(file,"0x%lx: %s, CR 0x%06lX, PVC %d.%d.%d\n",walk->id, - state_name[walk->state],walk->call_ref,walk->pvc.sap_addr.itf, - walk->pvc.sap_addr.vpi,walk->pvc.sap_addr.vci); - dump_addr(file,"local ",&walk->local); - dump_addr(file,"remote",&walk->remote); - dump_sap(file,"sap",&walk->sap); + if (entities) fprintf(file,"%s\n\n",banner); + for (sig = entities; sig; sig = sig->next) { + fprintf(file,"--- Entity %d.%d.%d ---\n",S_PVC(sig)); + for (walk = sockets; walk; walk = walk->next) { + fprintf(file,"0x%lx: %s, CR 0x%06lX, PVC %d.%d.%d\n",walk->id, + state_name[walk->state],walk->call_ref,walk->pvc.sap_addr.itf, + walk->pvc.sap_addr.vpi,walk->pvc.sap_addr.vci); + dump_addr(file,"local ",&walk->local); + dump_addr(file,"remote",&walk->remote); + dump_sap(file,"sap",&walk->sap); + } } } @@ -280,6 +298,16 @@ } +static void manual_override(void) +{ + /* + * Gross hack to avoid changing the command-line parameters ... @@@ + */ + entities = &_entity; + _entity.next = NULL; +} + + static void usage(const char *name) { fprintf(stderr,"usage: %s [ -b ] [ -c config_file ] [ -d ] " @@ -292,16 +320,17 @@ int main(int argc,char **argv) { + SIG_ENTITY *sig; const char *config_file; char *end; int c,background; + int net = 0,allocate_ci = 1; set_application("atmsigd"); config_file = CONFIG_FILE; dump_dir = NULL; background = 0; - memset(&signaling_pvc,0,sizeof(signaling_pvc)); - signaling_pvc.sap_addr.vci = 5; + memset(&_entity.signaling_pvc,0,sizeof(_entity.signaling_pvc)); /* 1st pass to get the -c option */ while ((c = getopt(argc,argv,"Abc:dD:l:m:nNP:q:t:")) != EOF) if (c == 'c') config_file = optarg; @@ -309,11 +338,15 @@ diag(COMPONENT,DIAG_WARN,"%s not found. - Using defaults.",config_file); else if (yyparse()) diag(COMPONENT,DIAG_FATAL,"Error in config file. - Aborting."); + if (!atmpvc_addr_in_use(_entity.signaling_pvc)) + _entity.signaling_pvc.sap_addr.vci = 5; + if (!_entity.uni) _entity.uni = S_UNI30; /* process all other options but -c */ optind = 0; while ((c = getopt(argc,argv,"Abc:dD:l:m:nNP:q:t:")) != EOF) switch (c) { case 'A': + manual_override(); allocate_ci = 0; break; case 'b': @@ -337,25 +370,31 @@ set_logfile(optarg); break; case 'm': - if (!strcmp(optarg,"user")) mode = sm_user; - else if (!strcmp(optarg,"network")) mode = sm_net; - else if (!strcmp(optarg,"switch")) mode = sm_switch; + manual_override(); + if (!strcmp(optarg,"user")) _entity.mode = sm_user; + else if (!strcmp(optarg,"network")) _entity.mode = sm_net; + else if (!strcmp(optarg,"switch")) _entity.mode = sm_switch; else usage(argv[0]); break; case 'n': pretty = A2T_PRETTY; break; case 'N': + manual_override(); net = 1; break; case 'q': - if (sig_pcr != -1) usage(argv[0]); - sig_qos = optarg; + manual_override(); + if (_entity.sig_pcr != -1) usage(argv[0]); + _entity.sig_qos = optarg; break; case 'P': /* obsolete */ - if (sig_qos) usage(argv[0]); - sig_pcr = strtol(optarg,&end,0); + manual_override(); + if (_entity.sig_qos) usage(argv[0]); + _entity.sig_pcr = strtol(optarg,&end,0); if (*end) usage(argv[0]); + diag(COMPONENT,DIAG_WARN,"option -P is obsolete, " + "please use -q qos instead"); break; case 't': trace_size = strtol(optarg,&end,0); @@ -364,41 +403,25 @@ default: usage(argv[0]); } - switch (mode) { - case sm_unknown: - if (net) { - if (allocate_ci) { - mode = sm_net; - diag(COMPONENT,DIAG_WARN,"option -N is obsolete, " - "please use -m network instead"); - } - else { - mode = sm_switch; - diag(COMPONENT,DIAG_WARN,"options -N -A are obsolete, " - "please use -m switch instead"); - } + if (_entity.mode == sm_unknown) + if (net) { + if (allocate_ci) { + _entity.mode = sm_net; + diag(COMPONENT,DIAG_WARN,"option -N is obsolete, " + "please use -m network instead"); } - else if (allocate_ci) mode = sm_user; - else usage(argv[0]); - break; - case sm_user: - allocate_ci = 1; /* should be ignored anyway */ - net = 0; - break; - case sm_net: - allocate_ci = 1; - net = 1; - break; - case sm_switch: - allocate_ci = 0; - net = 1; - break; - default: - abort(); - } + else { + _entity.mode = sm_switch; + diag(COMPONENT,DIAG_WARN,"options -N -A are obsolete, " + "please use -m switch instead"); + } + } + else if (allocate_ci) _entity.mode = sm_user; + else usage(argv[0]); if (optind < argc) { - if (text2atm(argv[optind],(struct sockaddr *) &signaling_pvc, - sizeof(signaling_pvc),T2A_PVC) < 0) + manual_override(); + if (text2atm(argv[optind],(struct sockaddr *) &_entity.signaling_pvc, + sizeof(_entity.signaling_pvc),T2A_PVC) < 0) diag(COMPONENT,DIAG_FATAL,"text2atm \"%s\": failed",argv[optind]); optind++; if (optind == argc-1) { @@ -407,41 +430,33 @@ } } if (optind != argc) usage(argv[0]); - diag(COMPONENT,DIAG_INFO,"Linux ATM signaling " -#ifdef UNI30 - "UNI 3.0" -#endif -#ifdef UNI31 - "UNI 3.1" -#ifdef ALLOW_UNI30 - "+3.0compat" -#endif -#endif -#ifdef UNI40 - "UNI 4.0" -#ifdef Q2963_1 - "+Q.2963.1" -#endif -#endif - "/AAL5, version " VERSION); if (dump_dir) if (chdir(dump_dir) < 0) diag(COMPONENT,DIAG_ERROR,"chdir %s: %s",dump_dir,strerror(errno)); - diag(COMPONENT,DIAG_INFO,"Acting as %s", - mode == sm_user ? "USER side" : - mode == sm_net ? "NETWORK side" : "SWITCH"); + for (sig = entities; sig; sig = sig->next) { + diag(COMPONENT,DIAG_INFO,"Linux ATM signaling %s" +#ifdef DYNAMIC_UNI + " (dynamic)" +#endif + ", version " VERSION " on %d.%d.%d", + sig->uni & S_UNI30 ? + sig->uni & S_UNI31 ? "UNI 3.1+3.0compat" : "UNI 3.0" : + sig->uni & S_UNI31 ? "UNI 3.1" : + sig->uni & S_Q2963_1 ? "UNI 4.0+Q.2963.1" : "UNI 4.0", + S_PVC(sig)); + diag(COMPONENT,DIAG_INFO,"Acting as %s", + sig->mode == sm_user ? "USER side" : + sig->mode == sm_net ? "NETWORK side" : "SWITCH"); + } if (open_all()) return 1; init_current_time(); - if (mode != sm_switch) init_addr(); q_start(); - start_saal(&saal,&ops,NULL, -#ifdef UNI30 - sscop_qsaal1 -#else - sscop_q2110 -#endif - ); - saal_estab_req(&saal,NULL,0); + for (sig = entities; sig; sig = sig->next) { + if (sig->mode != sm_switch) init_addr(sig); + start_saal(&sig->saal,&ops,sig, + sig->uni == S_UNI30 ? sscop_qsaal1 : sscop_q2110); + saal_estab_req(&sig->saal,NULL,0); + } setup_signals(); if (background) { pid_t pid; @@ -457,6 +472,6 @@ (void) on_exit(trace_on_exit,NULL); poll_loop(); close_all(); - stop_saal(&saal); + for (sig = entities; sig; sig = sig->next) stop_saal(&sig->saal); return 0; } diff -ur --new-file old/atm/sigd/atmsigd.conf.4 new/atm/sigd/atmsigd.conf.4 --- old/atm/sigd/atmsigd.conf.4 Thu Aug 20 18:04:24 1998 +++ new/atm/sigd/atmsigd.conf.4 Sun Nov 1 17:32:18 1998 @@ -1,4 +1,4 @@ -.TH ATMSIGD.CONF 4 "June 25, 1998" "Linux" "File Formats" +.TH ATMSIGD.CONF 4 "November 1, 1998" "Linux" "File Formats" .SH NAME atmsigd.conf \- configuration file for the ATM signaling demon .SH SYNOPSIS @@ -58,11 +58,17 @@ the user side, \fBnetwork\fP for the network side, and \fBswitch\fP for operation in a switch. The default behaviour is \fBuser\fP. .IP \fBsig\ uni30\fP -Use UNI 3.0 signaling. This option is not implemented. The signaling mode -must be configured at compile time. +Use UNI 3.0 signaling. If specified together with \fBsig uni31\fP, this +option sets UNI 3.1 signaling with a few backwards-compatibility extensions. .IP \fBsig\ uni31\fP -Use UNI 3.1 signaling. This option is not implemented. The signaling mode -must be configured at compile time. +Use UNI 3.1 signaling. This option can be combined with \fBsig uni30\fP (see +above). +.IP \fBsig\ uni40\fP +Use UNI 4.0 signaling. This option can be combined with \fBsig q2963_1\fP +(see below). +.IP \fBsig\ q2963_1\fP +Enable peak cell rate renegotiation. This option is only available with +UNI 4.0 signaling. .IP \fBsig\ vpci\ \fIvpci\fB\ itf\ \fIitf\fP Sets up a very simplistic type of routing. All calls with VPCI values equal to or greater than \fIvpci\fP will be routed to \fIitf\fP, and their @@ -81,6 +87,18 @@ prepending a slash and the number of significant bits (NSAP) or digits (E.164). The rules are searched in the order in which they appear in \fBatmsigd.conf\fP until the first match. If no rule matches, the call is allowed. +.IP \fBentity\ \fP[\fIitf\fB.\fP]\fIvpi\fB.\fIvci\fP\ {\ \fIoptions\ ...\fP\ } +Activates a signaling entity on that specific VC. Multiple \fBentity\fP +clauses can appear in the same configuration. When using \fBentity\fP, +the option \fBio vc\fP is not available. +\fBentity\fP is optionally followed by the following options, enclosed in +curly braces: \fBvpci\fP (corresponds to \fBsig vpci\fP), +\fBmode\fP (corresponds to \fBsig mode\fP), \fBqos\fP (corresponds to \fBvc +qos\fP), \fBroute\fP, and \fBdefault\fP. The last two options determine how +outbound call are routed. The \fBroute\fP option is followed by an address +in the format used for addresses in \fBpolicy\fP. If no route entry matches +the called party number of an outbound call, the entry marked with +\fBdefault\fP is selected. .P When setting multiple parameters in the same group, the group name doesn't have to be repeated if it is followed by the parameters in curly braces. @@ -103,9 +121,10 @@ If an option is specified in \fBatmsigd.conf\fP and on the command line, the command line has priority. .COMPATIBILITY -For historical reasons, synonyms (e.g. abbreviated or long forms) exist for -most keywords. Future versions of \fBatmsigd\fP will only recognize the -syntax described on this man page. +Certain options used by past versions of \fBatmsigd\fP but no longer documented +on the man page are still recognized and supported, but they also yield a +warning message. Future versions of \fBatmsigd\fP will not recognize those +options. .SH AUTHOR Werner Almesberger, EPFL ICA .SH "SEE ALSO" diff -ur --new-file old/atm/sigd/cfg.l new/atm/sigd/cfg.l --- old/atm/sigd/cfg.l Thu Aug 20 18:04:24 1998 +++ new/atm/sigd/cfg.l Thu Aug 20 23:02:30 1998 @@ -53,6 +53,8 @@ policy return TOK_POLICY; allow return TOK_ALLOW; reject return TOK_REJECT; +entity return TOK_ENTITY; +default return TOK_DEFAULT; dump { BEGIN(P); token = TOK_DUMP_DIR; } log { BEGIN(P); @@ -63,6 +65,8 @@ token = TOK_FROM; } to { BEGIN(P); /* syntacticly close to a path */ token = TOK_TO; } +route { BEGIN(P); /* syntacticly close to a path */ + token = TOK_ROUTE; } trace return TOK_TRACE; [0-9]+ { char *end; yylval.num = strtoul(yytext,&end,10); diff -ur --new-file old/atm/sigd/cfg.y new/atm/sigd/cfg.y --- old/atm/sigd/cfg.y Thu Aug 20 18:04:24 1998 +++ new/atm/sigd/cfg.y Mon Oct 5 18:43:29 1998 @@ -6,6 +6,7 @@ #include #include +#include #include "atm.h" #include "atmd.h" @@ -17,6 +18,7 @@ static RULE *rule; +static SIG_ENTITY *curr_sig = &_entity; static int hex2num(char digit) @@ -56,8 +58,9 @@ %token TOK_SIG TOK_UNI30 TOK_UNI31 TOK_UNI40 TOK_Q2963_1 TOK_SAAL %token TOK_VC TOK_IO TOK_MODE TOK_USER TOK_NET TOK_SWITCH TOK_VPCI %token TOK_ITF TOK_PCR TOK_TRACE TOK_POLICY TOK_ALLOW TOK_REJECT +%token TOK_ENTITY TOK_DEFAULT %token TOK_NUMBER -%token TOK_DUMP_DIR TOK_LOGFILE TOK_QOS TOK_FROM TOK_TO +%token TOK_DUMP_DIR TOK_LOGFILE TOK_QOS TOK_FROM TOK_TO TOK_ROUTE %token TOK_PVC %type level opt_trace_size action @@ -65,7 +68,35 @@ %% all: - | item all + global local + ; + +global: + | item global + ; + +local: + | entity local + { + if (!curr_sig->uni) + curr_sig->uni = +#if defined(UNI30) || defined(DYNAMIC_UNI) + S_UNI30 +#endif +#ifdef UNI31 + S_UNI31 +#endif +#ifdef ALLOW_UNI30 + S_UNI30 | S_UNI31 +#endif +#ifdef UNI40 + S_UNI40 +#ifdef Q2963_1 + | S_Q2963_1 +#endif +#endif + ; + } ; item: @@ -80,6 +111,67 @@ | TOK_POLICY policy ; +entity: + TOK_ENTITY TOK_PVC + { + SIG_ENTITY *sig,**walk; + + if (atmpvc_addr_in_use(_entity.signaling_pvc)) + yyerror("can't use io vc and entity ... in the same " + "configuration"); + if (entities == &_entity) entities = NULL; + for (sig = entities; sig; sig = sig->next) + if (atm_equal((struct sockaddr *) &sig->signaling_pvc, + (struct sockaddr *) &$2,0,0)) + yyerror("duplicate PVC address %d.%d.%d",S_PVC(sig)); + curr_sig = alloc_t(SIG_ENTITY); + *curr_sig = _entity; + curr_sig->signaling_pvc = $2; + curr_sig->next = NULL; + for (walk = &entities; *walk; walk = &(*walk)->next); + *walk = curr_sig; + } + opt_options + ; + +opt_options: + | '{' options '}' + ; + +options: + | option options + ; + +option: + TOK_VPCI TOK_NUMBER TOK_ITF TOK_NUMBER + { + enter_vpci(curr_sig,$2,$4); + } + | TOK_MODE mode + | TOK_QOS + { + curr_sig->sig_qos = $1; + } + | TOK_ROUTE + { + struct sockaddr_atmsvc addr; + char *mask; + + mask = strchr($1,'/'); + if (mask) *mask++ = 0; + if (text2atm($1,(struct sockaddr *) &addr,sizeof(addr), + T2A_SVC | T2A_WILDCARD | T2A_NAME | T2A_LOCAL) < 0) { + yyerror("invalid address"); + return; + } + add_route(curr_sig,&addr,mask ? strtol(mask,NULL,10) : INT_MAX); + } + | TOK_DEFAULT + { + add_route(curr_sig,NULL,0); + } + ; + sig: sig_item | '{' sig_items '}' @@ -134,36 +226,48 @@ } | TOK_VPCI TOK_NUMBER TOK_ITF TOK_NUMBER { - enter_vpci($2,$4); + enter_vpci(curr_sig,$2,$4); } | TOK_UNI30 { -#ifndef UNI30 +#if defined(UNI30) || defined(ALLOW_UNI30) || defined(DYNAMIC_UNI) + if (curr_sig->uni & ~S_UNI31) yyerror("UNI mode is already set"); + curr_sig->uni |= S_UNI30; +#else yyerror("Sorry, not supported yet"); #endif } | TOK_UNI31 { -#ifndef UNI31 +#if defined(UNI31) || defined(ALLOW_UNI30) || defined(DYNAMIC_UNI) + if (curr_sig->uni & ~S_UNI30) yyerror("UNI mode is already set"); + curr_sig->uni |= S_UNI31; +#else yyerror("Sorry, not supported yet"); #endif } | TOK_UNI40 { -#ifndef UNI40 +#if defined(UNI40) || defined(DYNAMIC_UNI) + if (curr_sig->uni) yyerror("UNI mode is already set"); + curr_sig->uni = S_UNI40; +#else yyerror("Sorry, not supported yet"); #endif } | TOK_Q2963_1 { -#ifndef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) + if (!(curr_sig->uni & S_UNI40)) yyerror("Incompatible UNI mode"); + curr_sig->uni |= S_Q2963_1; +#else yyerror("Sorry, not supported yet"); #endif } | TOK_NET { yywarn("sig net is obsolete, please use sig mode net instead"); - net = 1; + curr_sig->mode = sm_net; } | TOK_MODE mode ; @@ -183,15 +287,16 @@ } | TOK_VC TOK_PVC { - signaling_pvc = $2; + curr_sig->signaling_pvc = $2; } | TOK_PCR TOK_NUMBER { - sig_pcr = $2; + yywarn("io pcr is obsolete, please use io qos instead"); + curr_sig->sig_pcr = $2; } | TOK_QOS { - sig_qos = $1; + curr_sig->sig_qos = $1; } ; @@ -251,15 +356,15 @@ mode: TOK_USER { - mode = sm_user; + curr_sig->mode = sm_user; } | TOK_NET { - mode = sm_net; + curr_sig->mode = sm_net; } | TOK_SWITCH { - mode = sm_switch; + curr_sig->mode = sm_switch; } ; diff -ur --new-file old/atm/sigd/io.c new/atm/sigd/io.c --- old/atm/sigd/io.c Wed Sep 23 20:02:07 1998 +++ new/atm/sigd/io.c Wed Sep 23 19:45:35 1998 @@ -31,11 +31,10 @@ struct timeval now; -struct sockaddr_atmpvc signaling_pvc; int stop = 0; -static int kernel = -1,signaling; +static int kernel = -1; static int need_connect = 0; /* non-zero if connection to kernel isn't bi-directional yet */ @@ -118,7 +117,7 @@ /* ----- signaling interface ----------------------------------------------- */ -static int open_signaling(void) +static int open_signaling(SIG_ENTITY *sig) { struct atm_qos qos; int s; @@ -130,26 +129,27 @@ memset(&qos,0,sizeof(qos)); qos.aal = ATM_AAL5; qos.rxtp.max_sdu = qos.txtp.max_sdu = MAX_Q_MSG; - if (sig_qos) { - if (text2qos(sig_qos,&qos,T2Q_DEFAULTS) < 0) { - fprintf(stderr,"invalid qos: %s\n",sig_qos); + if (sig->sig_qos) { + if (text2qos(sig->sig_qos,&qos,T2Q_DEFAULTS) < 0) { + fprintf(stderr,"invalid qos: %s\n",sig->sig_qos); return -1; } } else { - if (sig_pcr == -1) + if (sig->sig_pcr == -1) qos.rxtp.traffic_class = qos.txtp.traffic_class = ATM_UBR; else { qos.rxtp.traffic_class = qos.txtp.traffic_class = ATM_CBR; - qos.rxtp.min_pcr = qos.txtp.min_pcr = sig_pcr; + qos.rxtp.min_pcr = qos.txtp.min_pcr = sig->sig_pcr; } } if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { perror("setsockopt SO_ATMQOS"); return -1; } - signaling_pvc.sap_family = AF_ATMPVC; - if (bind(s,(struct sockaddr *) &signaling_pvc,sizeof(signaling_pvc)) < 0) { + sig->signaling_pvc.sap_family = AF_ATMPVC; + if (bind(s,(struct sockaddr *) &sig->signaling_pvc, + sizeof(sig->signaling_pvc)) < 0) { perror("bind"); return -1; } @@ -157,32 +157,33 @@ } -static void recv_signaling(void) +static void recv_signaling(SIG_ENTITY *sig) { static unsigned char buffer[MAX_Q_MSG]; int size; - size = read(signaling,buffer,MAX_Q_MSG); + size = read(sig->signaling,buffer,MAX_Q_MSG); if (size < 1) { perror("read signaling"); return; } - diag(COMPONENT,DIAG_DEBUG,"FROM NET: %s PDU (%d bytes)", - pdu_name[size > 3 && !(size & 3) ? buffer[size-4] & 0xf : 0],size); + diag(COMPONENT,DIAG_DEBUG,"FROM NET (%d.%d.%d): %s PDU (%d bytes)", + S_PVC(sig),pdu_name[size > 3 && !(size & 3) ? buffer[size-4] & 0xf : 0], + size); if (debug) diag_dump(COMPONENT,DIAG_DEBUG,NULL,buffer,size); - from_net(buffer,size); + from_net(sig,buffer,size); } -void to_net(void *msg,int size) +void to_net(SIG_ENTITY *sig,void *msg,int size) { int wrote; - diag(COMPONENT,DIAG_DEBUG,"TO NET: %s PDU (%d bytes)", + diag(COMPONENT,DIAG_DEBUG,"TO NET (%d.%d.%d): %s PDU (%d bytes)",S_PVC(sig), pdu_name[size > 3 && !(size & 3) ? ((unsigned char *) msg)[size-4] & 0xf : 0],size); if (debug) diag_dump(COMPONENT,DIAG_DEBUG,NULL,msg,size); - wrote = write(signaling,msg,size); + wrote = write(sig->signaling,msg,size); if (wrote == size) return; if (wrote < 0) { perror("signaling write"); @@ -193,22 +194,33 @@ } -static void close_signaling(void) +static void close_signaling(SIG_ENTITY *sig) { - (void) close(signaling); + (void) close(sig->signaling); } /* ----- addresses --------------------------------------------------------- */ -LOCAL_ADDR local_addr[MAX_ADDRS+1]; +LOCAL_ADDR local_addr[MAX_LOCAL_ADDRS+1]; + + +struct sockaddr_atmsvc *get_local(int itf) +{ + LOCAL_ADDR *local; + + for (local = local_addr; local->state != ls_unused; local++) + if (local->state == ls_same && atmsvc_addr_in_use(local->addr) && + (local->itf == itf || itf == ATM_ITF_ANY)) return &local->addr; + return NULL; +} int get_addr(int itf) { struct atmif_sioc req; - struct sockaddr_atmsvc buffer[MAX_ADDRS]; + struct sockaddr_atmsvc buffer[MAX_LOCAL_ADDRS]; LOCAL_ADDR *from,*to; int addrs,i; @@ -220,7 +232,7 @@ req.number = itf; req.arg = buffer; req.length = sizeof(buffer); - if (ioctl(signaling,ATM_GETADDR,&req) < 0) + if (ioctl(entities->signaling,ATM_GETADDR,&req) < 0) diag(COMPONENT,DIAG_FATAL,"ioctl ATM_GETADDR yields \"%s\"", strerror(errno)); addrs = req.length/sizeof(struct sockaddr_atmsvc); @@ -229,7 +241,7 @@ if (from->itf == itf && atm_equal((struct sockaddr *) (buffer+i), (struct sockaddr *) &from->addr,0,0)) break; if (from->state != ls_unused) from->state = ls_same; - else if (to == local_addr+MAX_ADDRS-1) + else if (to == local_addr+MAX_LOCAL_ADDRS-1) diag(COMPONENT,DIAG_WARN,"local address table overflow"); else { to->state = ls_added; @@ -248,12 +260,18 @@ int open_all(void) { + SIG_ENTITY *sig,*purge; + if (kernel == -1) kernel = open_kernel(); if (kernel < 0) return -1; - signaling = open_signaling(); - if (signaling < 0) { - close_kernel(); - return -1; + for (sig = entities; sig; sig = sig->next) { + sig->signaling = open_signaling(sig); + if (sig->signaling < 0) { + for (purge = entities; purge != sig; purge = purge->next) + close_signaling(purge); + close_kernel(); + return -1; + } } local_addr[0].state = ls_unused; return 0; @@ -262,8 +280,10 @@ void close_all(void) { + SIG_ENTITY *sig; + close_kernel(); - close_signaling(); + for (sig = entities;sig; sig = sig->next) close_signaling(sig); } @@ -275,13 +295,17 @@ void poll_loop(void) { + SIG_ENTITY *sig; fd_set perm,set; int fds,ret; FD_ZERO(&perm); FD_SET(kernel,&perm); - FD_SET(signaling,&perm); - fds = kernel > signaling ? kernel+1 : signaling+1; + fds = kernel+1; + for (sig = entities; sig; sig = sig->next) { + FD_SET(sig->signaling,&perm); + if (fds <= sig->signaling) fds = sig->signaling+1; + } gettimeofday(&now,NULL); while (!stop) { set = perm; @@ -301,7 +325,8 @@ diag(COMPONENT,DIAG_DEBUG,"----------"); gettimeofday(&now,NULL); if (FD_ISSET(kernel,&set)) recv_kernel(); - if (FD_ISSET(signaling,&set)) recv_signaling(); + for (sig = entities; sig; sig = sig->next) + if (FD_ISSET(sig->signaling,&set)) recv_signaling(sig); expire_timers(); /* expire timers after handling messges to make sure we don't time out unnecessarily because of scheduling delays */ diff -ur --new-file old/atm/sigd/io.h new/atm/sigd/io.h --- old/atm/sigd/io.h Thu Aug 20 18:04:24 1998 +++ new/atm/sigd/io.h Thu Aug 20 19:50:44 1998 @@ -10,8 +10,10 @@ #include #include +#include "proto.h" -#define MAX_ADDRS 128 + +#define MAX_LOCAL_ADDRS 128 typedef struct { @@ -22,7 +24,6 @@ extern LOCAL_ADDR local_addr[]; -extern struct sockaddr_atmpvc signaling_pvc; int open_all(void); @@ -32,8 +33,9 @@ void close_all(void); void to_kernel(struct atmsvc_msg *msg); -void to_net(void *msg,int size); +void to_net(SIG_ENTITY *sig,void *msg,int size); +struct sockaddr_atmsvc *get_local(int itf); int get_addr(int itf); int get_pvc(int itf,int *vci); diff -ur --new-file old/atm/sigd/kernel.c new/atm/sigd/kernel.c --- old/atm/sigd/kernel.c Mon Sep 7 15:37:16 1998 +++ new/atm/sigd/kernel.c Sun Nov 1 16:55:55 1998 @@ -43,35 +43,24 @@ while (walk); sock->call_ref = call_ref; q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_call_ref,call_ref); - q_assign(&dsc,QF_msg_type,ATM_MSG_SETUP); - q_assign(&dsc,QF_aal_type,5); /* AAL 5 */ -#ifdef UNI30 - q_assign(&dsc,QF_aal_mode,1); /* Message mode - LANE seems to really want - this */ -#endif - q_assign(&dsc,QF_sscs_type,0); /* unspecified - LANE wants this */ - error = sap_encode(&dsc,&sock->remote,&sock->sap,&sock->qos); - q_assign(&dsc,QF_bearer_class,16); /* BCOB-X */ -#if defined(UNI30) || defined(ALLOW_UNI30) - q_assign(&dsc,QF_trans_cap,ATM_TC_VBR_NRT_R00); - /* force presence - UNI 3.0 wants this */ -#endif - q_assign(&dsc,QF_upcc,0); /* p2p */ -#ifndef UNI30 - q_assign(&dsc,QF_qos_cs,Q2931_CS_ITU); -#endif - q_assign(&dsc,QF_qos_fw,0); /* QOS 0 */ - q_assign(&dsc,QF_qos_bw,0); local = NULL; + error = 0; if (atmsvc_addr_in_use(sock->local)) local = &sock->local; - else if (local_addr[0].state == ls_same && - atmsvc_addr_in_use(local_addr[0].addr)) - local = &local_addr[0].addr; - if (!local) { - if (!error) error = -EADDRNOTAVAIL; + else { + sock->sig = route_call(&sock->remote); + if (!sock->sig) error = -EHOSTUNREACH; + else { + local = get_local(sock->sig->signaling_pvc.sap_addr.itf); + if (!local) local = get_local(ATM_ITF_ANY); + if (local) sock->local = *local; + else { + error = -EADDRNOTAVAIL; + diag(COMPONENT,DIAG_ERROR,"no local address"); + } + } } - else if (*local->sas_addr.pub) { + if (local) + if (*local->sas_addr.pub) { q_assign(&dsc,QF_cgpn_plan,ATM_NP_E164); q_assign(&dsc,QF_cgpn_type,ATM_TON_INTRNTNL); q_write(&dsc,QF_cgpn,(void *) local->sas_addr.pub, @@ -82,26 +71,52 @@ q_assign(&dsc,QF_cgpn_type,ATM_TON_UNKNOWN); q_write(&dsc,QF_cgpn,(void *) local->sas_addr.prv,ATM_ESA_LEN); } - if (net) { + q_assign(&dsc,QF_call_ref,call_ref); + q_assign(&dsc,QF_msg_type,ATM_MSG_SETUP); + q_assign(&dsc,QF_aal_type,5); /* AAL 5 */ +#if defined(UNI30) || defined(DYNAMIC_UNI) + if (sock->sig->uni == S_UNI30) + q_assign(&dsc,QF_aal_mode,1); /* Message mode - LANE seems to really + want this */ +#endif + q_assign(&dsc,QF_sscs_type,0); /* unspecified - LANE wants this */ + if (!error) + error = sap_encode(&dsc,&sock->remote,&sock->sap,&sock->qos, + sock->sig->uni); + q_assign(&dsc,QF_bearer_class,16); /* BCOB-X */ +#if defined(UNI30) || defined(ALLOW_UNI30) || defined(DYNAMIC_UNI) + if (sock->sig->uni & S_UNI30) + q_assign(&dsc,QF_trans_cap,ATM_TC_VBR_NRT_R00); + /* force presence - UNI 3.0 wants this */ +#endif + q_assign(&dsc,QF_upcc,0); /* p2p */ +#if !defined(UNI30) || defined(DYNAMIC_UNI) + if (sock->sig->uni != S_UNI30) + q_assign(&dsc,QF_qos_cs,Q2931_CS_ITU); +#endif + q_assign(&dsc,QF_qos_fw,0); /* QOS 0 */ + q_assign(&dsc,QF_qos_bw,0); + if (sock->sig->mode != sm_user) { if (!atmpvc_addr_in_use(sock->pvc)) { - int vci; + int vpci,vci; - if (!allocate_ci) + if (sock->sig->mode == sm_switch) diag(COMPONENT,DIAG_FATAL,"No CI allocator (use -A)"); - vci = get_vci(0); + vpci = 0; + sock->pvc.sap_addr.itf = get_itf(sock->sig,&vpci); + sock->pvc.sap_addr.vpi = vpci; + vci = get_vci(sock->pvc.sap_addr.itf); if (vci < 0) { (void) q_close(&dsc); return vci; } - sock->pvc.sap_addr.itf = get_itf(0); - sock->pvc.sap_addr.vpi = 0; sock->pvc.sap_addr.vci = vci; } q_assign(&dsc,QF_vpi,sock->pvc.sap_addr.vpi); q_assign(&dsc,QF_vci,sock->pvc.sap_addr.vci); } if ((size = q_close(&dsc)) < 0) error = -EINVAL; - else if (!error) to_signaling(q_buffer,size); + else if (!error) to_signaling(sock->sig,q_buffer,size); return error; } @@ -117,20 +132,21 @@ if (sock->ep_ref >= 0) q_assign(&dsc,QF_ep_ref,sock->ep_ref); if (sock->ep_ref <= 0) { /* no AAL parameters if ep_ref present and != 0 */ q_assign(&dsc,QF_aal_type,5); -#ifdef UNI30 - q_assign(&dsc,QF_aal_mode,1); /* Message mode - LANE seems to really - want this */ +#if defined(UNI30) || defined(DYNAMIC_UNI) + if (sock->sig->uni == S_UNI30) + q_assign(&dsc,QF_aal_mode,1); /* Message mode - LANE seems to + really want this */ #endif q_assign(&dsc,QF_sscs_type,0); /* unspecified - LANE wants this */ q_assign(&dsc,QF_fw_max_sdu,sock->qos.rxtp.max_sdu); q_assign(&dsc,QF_bw_max_sdu,sock->qos.txtp.max_sdu); } - if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); return 0; } -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) static void send_modify_request(SOCKET *sock) { @@ -144,7 +160,7 @@ q_assign(&dsc,QF_fw_pcr_01,SELECT_TOP_PCR(sock->new_qos.txtp)); if (sock->new_qos.rxtp.traffic_class) q_assign(&dsc,QF_bw_pcr_01,SELECT_TOP_PCR(sock->new_qos.rxtp)); - if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); } @@ -161,30 +177,12 @@ q_assign(&dsc,QF_type_of_report,ATM_TOR_MOD_CONF); START_TIMER(sock,T361); } - if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); } #endif -static int bind_check(SOCKET *sock,struct sockaddr_atmsvc *local) -{ - struct sockaddr_atmsvc *use; - - if (atmsvc_addr_in_use(sock->local)) return 0; - if (atmsvc_addr_in_use(*local)) use = local; - else { - if (local_addr[0].state != ls_same) { - diag(COMPONENT,DIAG_ERROR,"no local address"); - return -EADDRNOTAVAIL; - } - use = &local_addr[0].addr; - } - sock->local = *use; - return 0; -} - - static void dispatch(SOCKET *sock,struct atmsvc_msg *msg) { int error; @@ -215,9 +213,17 @@ if(*msg->svc.sas_addr.pub) diag(COMPONENT,DIAG_DEBUG,"binding to E.164 address " "%s\n",msg->svc.sas_addr.pub); - if (walk->state == ls_unused) + if (walk->state == ls_unused) { SEND_ERROR(msg->vcc,-EADDRNOTAVAIL); - else send_kernel(msg->vcc,0,as_okay,0,NULL,NULL,NULL,NULL,NULL); + return; + } + sock->sig = get_sig_entity(walk->itf); + if (!sock->sig) { + diag(COMPONENT,DIAG_ERROR,"signaling entity lookup failed"); + SEND_ERROR(msg->vcc,-EADDRNOTAVAIL); + return; + } + send_kernel(msg->vcc,0,as_okay,0,NULL,NULL,NULL,NULL,NULL); } return; case as_connect: /* NULL state only */ @@ -227,12 +233,6 @@ return; } sock = new_sock(msg->vcc); - error = bind_check(sock,&msg->local); - if (error) { - free_sock(sock); - SEND_ERROR(msg->vcc,error); - return; - } sock->remote = msg->svc; sock->qos = msg->qos; sock->sap = msg->sap; @@ -255,7 +255,7 @@ } if (sock->state != ss_indicated && sock->state != ss_proceeding) break; - if (sock->state == ss_indicated && net) + if (sock->state == ss_indicated && sock->sig->mode != sm_user) diag(COMPONENT,DIAG_FATAL,"No CI allocator (use -A)"); error = send_connect(sock); if (!error) { @@ -271,7 +271,8 @@ case as_reject: /* ZOMBIE, INDICATED, or PROCEEDING */ switch (sock->state) { case ss_indicated: - send_release_complete(sock->call_ref,ATM_CV_CALL_REJ); + send_release_complete(sock->sig,sock->call_ref, + ATM_CV_CALL_REJ); /* fall through */ case ss_zombie: free_sock(sock); @@ -328,12 +329,12 @@ return; case ss_connecting: case ss_accepting: -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) case ss_mod_req: #endif STOP_TIMER(sock); /* fall through */ -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) case ss_mod_lcl: case ss_mod_rcv: case ss_mod_fin_ok: @@ -341,7 +342,7 @@ case ss_mod_fin_ack: #endif case ss_connected: -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) if (timer_handler(sock->conn_timer) == on_T361) STOP_TIMER(sock); #endif @@ -349,17 +350,22 @@ diag(COMPONENT,DIAG_INFO,"Active close (CR 0x%06X)", sock->call_ref); send_release(sock, +#ifdef DYNAMIC_UNI + sock->sig->uni != S_UNI30 ? ATM_CV_NORMAL_CLEAR : + ATM_CV_NORMAL_UNSPEC +#else #if defined(UNI31) || defined(UNI40) ATM_CV_NORMAL_CLEAR #else ATM_CV_NORMAL_UNSPEC #endif +#endif ); START_TIMER(sock,T308_1); new_state(sock,ss_rel_req); return; case ss_rel_ind: - send_release_complete(sock->call_ref,0); /* @@@ */ + send_release_complete(sock->sig,sock->call_ref,0); /* @@@ */ free_sock(sock); return; default: @@ -370,19 +376,24 @@ if (sock->state != ss_indicated && sock->state != ss_proceeding) break; if (!atmpvc_addr_in_use(msg->pvc)) { - if (net && !allocate_ci) + if (sock->sig->mode == sm_switch) diag(COMPONENT,DIAG_FATAL,"No CI allocator (use -A)"); return; } - if (net && allocate_ci) + if (sock->sig->mode == sm_net) diag(COMPONENT,DIAG_FATAL,"CI allocation role conflict"); sock->pvc = msg->pvc; if (send_call_proceeding(sock)) diag(COMPONENT,DIAG_FATAL,"s_c_p failed"); new_state(sock,ss_proceeding); return; -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) case as_modify: + if (sock && !(sock->sig->uni & S_Q2963_1)) { + send_kernel(sock->id,0,as_okay,-ENOPROTOOPT,NULL,NULL,NULL, + NULL,NULL); + return; + } if (sock && (sock->state == ss_mod_lcl || sock->state == ss_mod_req || sock->state == ss_mod_rcv || sock->state == ss_mod_fin_ok || sock->state == ss_mod_fin_fail || @@ -522,6 +533,10 @@ diag(COMPONENT,DIAG_INFO,"Removed local ATM address %s at " "itf %d",buf,itf); walk->state = ls_unused; +/* + * This is probably wrong. What if we delete an entry from the middle of + * the list ? @@@ + */ /* @@@ delete SVCs using that address ? */ break; default: @@ -541,14 +556,19 @@ return; } if (msg->type == as_terminate) { +#if 0 /* need to pass some ID ... @@@ */ if (mode != sm_switch) { diag(COMPONENT,DIAG_ERROR,"Ignoring as_terminate received in %s " "mode",mode == sm_user ? "USER" : "NETWORK"); return; } - clear_all_calls(); + clear_all_calls(sig); +#endif stop = 1; diag(COMPONENT,DIAG_INFO,"Going down on as_terminate"); + /* + * Fix this - we need to shut it down more gracefully. + */ return; } if (msg->listen_vcc && (msg->type == as_accept || msg->type == as_reject || diff -ur --new-file old/atm/sigd/proto.c new/atm/sigd/proto.c --- old/atm/sigd/proto.c Thu Aug 20 18:04:25 1998 +++ new/atm/sigd/proto.c Sun Nov 1 16:57:13 1998 @@ -58,6 +58,8 @@ ps_active, ps_add_recv, ps_active, ps_active, /* 8 */ ps_active }; /*12 */ + +SIG_ENTITY *entities = &_entity; SOCKET *sockets = NULL; unsigned char q_buffer[MAX_Q_MSG]; @@ -67,6 +69,7 @@ SOCKET *sock; sock = alloc_t(SOCKET); + sock->sig = NULL; sock->state = ss_invalid; memset(&sock->pvc,0,sizeof(sock->pvc)); sock->qos.txtp.traffic_class = sock->qos.rxtp.traffic_class = ATM_UBR; @@ -250,20 +253,37 @@ default: } va_end(ap); - if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); } -void send_release_complete(unsigned long call_ref,unsigned char cause) +void send_release_complete(SIG_ENTITY *sig,unsigned long call_ref, + unsigned char cause,...) { + va_list ap; Q_DSC dsc; int size; q_create(&dsc,q_buffer,MAX_Q_MSG); q_assign(&dsc,QF_msg_type,ATM_MSG_REL_COMP); q_assign(&dsc,QF_call_ref,call_ref); - if (cause) q_assign(&dsc,QF_cause,cause); /* @@@ more data */ - if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + if (cause) { + q_assign(&dsc,QF_cause,cause); + va_start(ap,cause); + switch (cause) { + case ATM_CV_INVALID_IE: + { + unsigned char ie; + + ie = va_arg(ap,int); + q_write(&dsc,QF_ie_id6,&ie,1); + } + break; + default: + } + va_end(ap); + } + if ((size = q_close(&dsc)) >= 0) to_signaling(sig,q_buffer,size); } @@ -276,7 +296,7 @@ q_assign(&dsc,QF_msg_type,ATM_MSG_MODIFY_REJ); q_assign(&dsc,QF_call_ref,sock->call_ref); q_assign(&dsc,QF_cause,reason); - if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); } @@ -312,7 +332,7 @@ s = get_pvc(itf,&vci); if (s < 0) return s; for (walk = sockets; walk; walk = walk->next) - if (walk->pvc.sap_addr.vci == vci) { + if (walk->pvc.sap_addr.itf == itf && walk->pvc.sap_addr.vci == vci) { vci = get_vci(itf); /* this recursion will keep all the busy ones open until we return */ break; @@ -322,21 +342,11 @@ } -typedef struct _vpci { - int vpci; - int itf; - struct _vpci *next; -} VPCI; - - -static VPCI *vpcis = NULL; - - -void enter_vpci(int vpci,int itf) +void enter_vpci(SIG_ENTITY *sig,int vpci,int itf) { VPCI *entry; - for (entry = vpcis; entry; entry = entry->next) + for (entry = sig->vpcis; entry; entry = entry->next) if (entry->vpci == vpci) { diag(COMPONENT,DIAG_ERROR,"ignoring duplicate VPCI %d (itf %d)", vpci,itf); @@ -345,29 +355,99 @@ entry = alloc_t(VPCI); entry->vpci = vpci; entry->itf = itf; - entry->next = vpcis; - vpcis = entry; + entry->next = sig->vpcis; + sig->vpcis = entry; } -int get_itf(int *vpci) +int get_itf(SIG_ENTITY *sig,int *vpci) { VPCI *best,*walk; best = NULL; - for (walk = vpcis; walk; walk = walk->next) + for (walk = sig->vpcis; walk; walk = walk->next) if (walk->vpci <= *vpci && (!best || best->vpci < walk->vpci)) best = walk; - if (!best) return signaling_pvc.sap_addr.itf; + if (!best) return sig->signaling_pvc.sap_addr.itf; *vpci -= best->vpci; return best->itf; } -void init_addr(void) +void init_addr(SIG_ENTITY *sig) { VPCI *walk; - itf_load(signaling_pvc.sap_addr.itf); - for (walk = vpcis; walk; walk = walk->next) itf_load(walk->itf); + itf_load(sig->signaling_pvc.sap_addr.itf); + for (walk = sig->vpcis; walk; walk = walk->next) itf_load(walk->itf); +} + + +/* + * The following code is stolen from switch/route.c. Eventually, all this + * should move into a library. + */ + + +#include + + +typedef struct _route { + struct sockaddr_atmsvc addr; + int len; + SIG_ENTITY *sig; + struct _route *next; +} ROUTE; + + +static ROUTE *routes = NULL; + + +void add_route(SIG_ENTITY *sig,struct sockaddr_atmsvc *addr,int len) +{ + ROUTE *route; + + for (route = routes; route; route = route->next) + if (route->len == len && (!len || atm_equal((struct sockaddr *) addr, + (struct sockaddr *) &route->addr,len, + AXE_PRVOPT | (len == INT_MAX ? 0 : AXE_WILDCARD)))) + diag(COMPONENT,DIAG_FATAL,"duplicate route"); + route = alloc_t(ROUTE); + if (addr) route->addr = *addr; + route->len = len; + route->sig = sig; + route->next = routes; + routes = route; +} + + +SIG_ENTITY *route_call(struct sockaddr_atmsvc *addr) +{ + ROUTE *best,*route; + int best_len; + + if (!routes) return entities; + best = NULL; + best_len = -1; + for (route = routes; route; route = route->next) + if (route->len > best_len && (!route->len || + atm_equal((struct sockaddr *) addr,(struct sockaddr *) &route->addr, + route->len, + AXE_PRVOPT | (route->len == INT_MAX ? 0 : AXE_WILDCARD)))) { + if (route->len == INT_MAX) return route->sig; + best_len = route->len; + best = route; + } + return best ? best->sig : NULL; +} + + +SIG_ENTITY *get_sig_entity(int itf) +{ + SIG_ENTITY *sig; + + for (sig = entities; sig; sig = sig->next) + if (sig->signaling_pvc.sap_addr.itf == itf) return sig; + /* should also check for vpcis @@@ */ + return NULL; } diff -ur --new-file old/atm/sigd/proto.h new/atm/sigd/proto.h --- old/atm/sigd/proto.h Thu Aug 20 18:04:25 1998 +++ new/atm/sigd/proto.h Sun Nov 1 16:56:36 1998 @@ -11,6 +11,7 @@ #include "atmsap.h" #include "atmd.h" +#include "saal.h" typedef enum { /* formatting aligned with state_map and others */ @@ -18,7 +19,7 @@ ss_connected, ss_indicated, ss_accepting, ss_zombie, ss_wait_rel, ss_wait_close, ss_rel_req, ss_rel_ind, ss_proceeding, ss_listen_zombie, -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) ss_mod_lcl, ss_mod_req, ss_mod_rcv, ss_mod_fin_ack, ss_mod_fin_ok, ss_mod_fin_fail #endif @@ -26,7 +27,7 @@ typedef enum { cs_null,cs_call_init,cs_out_proc = 3,cs_conn_req = 8, cs_in_proc,cs_active,cs_rel_req,cs_rel_ind, -#ifdef Q2963_1 +#if defined(Q2963_1) || defined (DYNAMIC_UNI) cs_mod_req,cs_mod_rcv #endif } CALL_STATE; @@ -34,8 +35,34 @@ typedef enum { ps_null,ps_add_init,ps_add_recv = 6,ps_drop_init = 11, ps_drop_recv,ps_active = 10 } PARTY_STATE; +#define S_UNI30 1 /* UNI 3.0 or ALLOW_UNI30 */ +#define S_UNI31 2 /* UNI 3.1 or ALLOW_UNI30 */ +#define S_UNI40 4 /* UNI 4.0 */ +#define S_Q2963_1 8 /* UNI 4.0 plus Q.2963.1 */ + +typedef enum { sm_unknown,sm_user,sm_net,sm_switch } SIGNALING_MODE; + +typedef struct _vpci { + int vpci; + int itf; + struct _vpci *next; +} VPCI; + +typedef struct _sig_entity { + int signaling; /* fd */ + int uni; + SIGNALING_MODE mode; + int sig_pcr; /* @@@ remove soon */ + const char *sig_qos; + struct sockaddr_atmpvc signaling_pvc; + SAAL_DSC saal; + VPCI *vpcis; + struct _sig_entity *next; +} SIG_ENTITY; + typedef struct _socket { STATE state; + SIG_ENTITY *sig; struct sockaddr_atmpvc pvc; /* --- socket layer information ---------------------------------------- */ unsigned long id; @@ -43,7 +70,7 @@ struct sockaddr_atmsvc remote; /* remote address */ struct atm_sap sap; /* SAP (BHLI and BLLI) */ struct atm_qos qos; /* QOS parameters */ -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) struct atm_qos new_qos; /* during modification */ int owner; /* non-zero if connection owner */ #endif @@ -58,6 +85,8 @@ struct _socket *next; /* next socket */ } SOCKET; +extern SOCKET *sockets; + /* * SOCKET uses a horrible linked list structure. Lists should be at least * doubly-linked and there should be a few hashes (by id and by call_ref) for @@ -65,23 +94,23 @@ * stable enough to be useful to test the "real" thing against it. */ -typedef enum { sm_unknown,sm_user,sm_net,sm_switch } SIGNALING_MODE; +#define S_PVC(e) \ + (e)->signaling_pvc.sap_addr.itf, \ + (e)->signaling_pvc.sap_addr.vpi, \ + (e)->signaling_pvc.sap_addr.vci + +extern SIG_ENTITY *entities; +extern SIG_ENTITY _entity; extern const CALL_STATE state_map[]; extern const PARTY_STATE eps_map[]; extern const char *state_name[],*cs_name[],*as_name[]; -extern SOCKET *sockets; extern unsigned char q_buffer[]; #define DEFAULT_TRACE_SIZE 20 -extern SIGNALING_MODE mode; -extern int net; /* @@@ remove soon */ -extern int allocate_ci; /* @@@ remove soon */ extern int pretty; -extern int sig_pcr; -extern const char *sig_qos; extern const char *dump_dir; extern int stop; @@ -96,17 +125,17 @@ void from_kernel(struct atmsvc_msg *msg,int size); void itf_load(int itf); -void to_uni(void *msg,int size); +void to_uni(SIG_ENTITY *sig,void *msg,int size); void send_kernel(unsigned long vcc,unsigned long listen_vcc, enum atmsvc_msg_type type,int reply,const struct sockaddr_atmpvc *pvc, const struct sockaddr_atmsvc *svc,const struct sockaddr_atmsvc *local, const struct atm_sap *sap,const struct atm_qos *qos); -void from_net(void *msg,int size); -void to_signaling(void *msg,int size); -void saal_failure(void); -void saal_okay(void); -void clear_all_calls(void); -void clear_all_calls_on_T309(void); +void from_net(SIG_ENTITY *sig,void *msg,int size); +void to_signaling(SIG_ENTITY *sig,void *msg,int size); +void saal_failure(SIG_ENTITY *sig); +void saal_okay(SIG_ENTITY *sig); +void clear_all_calls(SIG_ENTITY *sig); +void clear_all_calls_on_T309(SIG_ENTITY *sig); SOCKET *new_sock(unsigned long id); void free_sock(SOCKET *sock); @@ -117,7 +146,8 @@ struct atm_qos *res_qos,int exact_match); void send_release(SOCKET *sock,unsigned char reason,...); -void send_release_complete(unsigned long call_ref,unsigned char cause); +void send_release_complete(SIG_ENTITY *sig,unsigned long call_ref, + unsigned char cause,...); int send_call_proceeding(SOCKET *sock); void send_modify_reject(SOCKET *sock,unsigned char reason); @@ -128,8 +158,13 @@ int get_vci(int itf); -void enter_vpci(int vpci,int itf); -int get_itf(int *vpci); -void init_addr(void); +void enter_vpci(SIG_ENTITY *sig,int vpci,int itf); +int get_itf(SIG_ENTITY *sig,int *vpci); +void init_addr(SIG_ENTITY *sig); + +void add_route(SIG_ENTITY *sig,struct sockaddr_atmsvc *addr,int len); +SIG_ENTITY *route_call(struct sockaddr_atmsvc *addr); + +SIG_ENTITY *get_sig_entity(int itf); #endif diff -ur --new-file old/atm/sigd/sap.c new/atm/sigd/sap.c --- old/atm/sigd/sap.c Thu Aug 20 18:04:25 1998 +++ new/atm/sigd/sap.c Sun Nov 1 17:00:37 1998 @@ -17,6 +17,7 @@ #include #include "common.h" +#include "proto.h" #include "sap.h" @@ -129,7 +130,7 @@ int sap_encode(Q_DSC *dsc,const struct sockaddr_atmsvc *addr, - const struct atm_sap *sap,const struct atm_qos *qos) + const struct atm_sap *sap,const struct atm_qos *qos,int uni) { int error,pcr; @@ -141,9 +142,12 @@ else return -EDESTADDRREQ; if (qos->txtp.traffic_class == ATM_UBR || qos->rxtp.traffic_class == ATM_UBR) q_assign(dsc,QF_best_effort,0); -#ifdef UNI40 +#if defined(UNI40) || defined(DYNAMIC_UNI) if (qos->txtp.traffic_class == ATM_CBR || qos->rxtp.traffic_class == - ATM_CBR) q_assign(dsc,QF_trans_cap,ATM_TC_CBR); + ATM_CBR) { + if (!(uni & S_UNI40)) return -EINVAL; + q_assign(dsc,QF_trans_cap,ATM_TC_CBR); + } #endif switch (qos->txtp.traffic_class) { case ATM_NONE: @@ -195,8 +199,9 @@ case ATM_HL_USER: q_write(dsc,QF_user_hli,sap->bhli.hl_info,sap->bhli.hl_length); break; -#ifdef UNI30 +#if defined(UNI30) || defined(DYNAMIC_UNI) case ATM_HL_HLP: + if (!(uni & S_UNI30)) return -EINVAL; q_write(dsc,QF_hlp,sap->bhli.hl_info,4); break; #endif @@ -256,8 +261,8 @@ } -void sap_decode(Q_DSC *dsc,struct sockaddr_atmsvc *addr,struct atm_sap *sap, - struct atm_qos *qos) +unsigned int sap_decode(Q_DSC *dsc,struct sockaddr_atmsvc *addr, + struct atm_sap *sap,struct atm_qos *qos,int uni) { memset(addr,0,sizeof(*addr)); memset(sap,0,sizeof(*sap)); @@ -269,10 +274,22 @@ else if (q_present(dsc,QF_cdpn_esa)) (void) q_read(dsc,QF_cdpn_esa,(void *) &addr->sas_addr.prv, ATM_ESA_LEN); + qos->aal = ATM_AAL5; /* default and only choice */ if (q_present(dsc,QF_aal_type)) - if (q_fetch(dsc,QF_aal_type) != 5) + if (q_fetch(dsc,QF_aal_type) != 5) { diag(COMPONENT,DIAG_ERROR,"AAL type %d requested", q_fetch(dsc,QF_aal_type)); +#ifdef DYNAMIC_UNI + return IE_PROBLEM( + uni & S_UNI30 ? ATM_CV_AAL_UNSUPP_OLD : ATM_CV_AAL_UNSUPP_NEW,0); +#else +#ifdef UNI30 + return IE_PROBLEM(ATM_CV_AAL_UNSUPP_OLD,0); +#else + return IE_PROBLEM(ATM_CV_AAL_UNSUPP_NEW,0); +#endif /* UNI30 */ +#endif /* DYNAMIC_UNI */ + } if (q_present(dsc,QF_best_effort)) { qos->txtp.traffic_class = qos->rxtp.traffic_class = ATM_UBR; diag(COMPONENT,DIAG_DEBUG,"UBR"); @@ -312,28 +329,34 @@ sap->bhli.hl_length = q_length(dsc,QF_user_hli); q_read(dsc,QF_user_hli,sap->bhli.hl_info,sap->bhli.hl_length); break; -#ifdef UNI30 - case ATM_HL_HLP: - sap->bhli.hl_length = 4; - q_read(dsc,QF_hlp,sap->bhli.hl_info,4); - break; -#endif case ATM_HL_VENDOR: sap->bhli.hl_length = 7; q_read(dsc,QF_hli_oui,sap->bhli.hl_info,3); q_read(dsc,QF_app_id,sap->bhli.hl_info+3,4); break; +#if defined(UNI30) || defined(DYNAMIC_UNI) + case ATM_HL_HLP: + if (!(uni & S_UNI30)) { + sap->bhli.hl_length = 4; + q_read(dsc,QF_hlp,sap->bhli.hl_info,4); + break; + } + /* fall through */ +#endif default: - diag(COMPONENT,DIAG_FATAL,"unrecognized hl_type"); + diag(COMPONENT,DIAG_ERROR,"unrecognized hl_type %d", + sap->bhli.hl_type); + return IE_PROBLEM(ATM_CV_INVALID_IE,ATM_IE_BHLI); } } - if (!q_present(dsc,QG_blli1)) return; + if (!q_present(dsc,QG_blli1)) return 0; q_instance(dsc,QG_blli1); decode_blli(dsc,sap->blli); - if (!q_present(dsc,QG_blli2)) return; + if (!q_present(dsc,QG_blli2)) return 0; q_instance(dsc,QG_blli2); decode_blli(dsc,sap->blli+1); - if (!q_present(dsc,QG_blli3)) return; + if (!q_present(dsc,QG_blli3)) return 0; q_instance(dsc,QG_blli3); decode_blli(dsc,sap->blli+2); + return 0; } diff -ur --new-file old/atm/sigd/sap.h new/atm/sigd/sap.h --- old/atm/sigd/sap.h Thu Aug 20 18:04:25 1998 +++ new/atm/sigd/sap.h Sun Nov 1 16:40:00 1998 @@ -1,6 +1,6 @@ /* sap.h - SAP manipulations */ -/* Written 1996,1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1996-1998 by Werner Almesberger, EPFL-LRC/ICA */ #ifndef SAP_H @@ -11,14 +11,29 @@ #include "atmsap.h" +#define IE_PROBLEM(cause,ie) (((cause) << 8) | (ie)) +#define IE_PB_CAUSE(problem) ((problem) >> 8) +#define IE_PB_IE(problem) ((problem) & 0xff) + + int sap_compat(const struct sockaddr_atmsvc *old_addr, const struct sockaddr_atmsvc *new_addr,struct sockaddr_atmsvc *res_addr, const struct atm_sap *old_sap,const struct atm_sap *new_sap, struct atm_sap *res_sap,const struct atm_qos *old_qos, const struct atm_qos *new_qos,struct atm_qos *res_qos); int sap_encode(Q_DSC *dsc,const struct sockaddr_atmsvc *addr, - const struct atm_sap *sap,const struct atm_qos *qos); -void sap_decode(Q_DSC *dsc,struct sockaddr_atmsvc *addr,struct atm_sap *sap, - struct atm_qos *qos); + const struct atm_sap *sap,const struct atm_qos *qos,int uni); + +/* + * sap_encode returns zero on success, -errno on error. + */ + +unsigned int sap_decode(Q_DSC *dsc,struct sockaddr_atmsvc *addr, + struct atm_sap *sap,struct atm_qos *qos,int uni); + +/* + * sap_decode returns zero on success, the problem report (encoded with + * IE_PROBLEM) on error. + */ #endif diff -ur --new-file old/atm/sigd/timeout.c new/atm/sigd/timeout.c --- old/atm/sigd/timeout.c Thu Aug 20 18:04:25 1998 +++ new/atm/sigd/timeout.c Mon Oct 5 19:00:15 1998 @@ -6,6 +6,7 @@ #include #include #include +#include #include "atmd.h" @@ -65,7 +66,7 @@ void on_T309(void *user) { diag(COMPONENT,DIAG_DEBUG,"T309 has expired"); - clear_all_calls_on_T309(); + clear_all_calls_on_T309(user); } @@ -89,7 +90,7 @@ } -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) void on_T360(void *user) { diff -ur --new-file old/atm/sigd/trace.c new/atm/sigd/trace.c --- old/atm/sigd/trace.c Thu Aug 20 18:04:26 1998 +++ new/atm/sigd/trace.c Mon Oct 5 09:59:36 1998 @@ -16,6 +16,7 @@ #include "atmd.h" #include "atmsap.h" #include "trace.h" +#include "proto.h" #define DUMP_MODE @@ -27,6 +28,7 @@ struct timeval time; void (*print)(void *msg,int size); const char *comment; + struct sockaddr_atmpvc pvc; /* unused if !sap_family */ void *msg; int size; struct _entry *next; @@ -35,6 +37,7 @@ int trace_size = 0; +static struct sockaddr_atmpvc null_pvc; static int current_size = 0; static int sequence = 0; static ENTRY *first = NULL,*last = NULL; @@ -206,7 +209,7 @@ static void store(void (*print)(void *msg,int size),const char *comment, - void *msg,int size) + const struct sockaddr_atmpvc *pvc,void *msg,int size) { ENTRY *entry; @@ -215,6 +218,7 @@ entry->number = sequence++; entry->print = print; entry->comment = comment; + entry->pvc = *pvc; entry->msg = msg; entry->size = size; entry->next = NULL; @@ -241,18 +245,19 @@ if (!trace_size) return; buf = alloc(strlen(msg)+1); strcpy(buf,msg); - store(&print_text,"MESSAGE",buf,strlen(msg)); + store(&print_text,"MESSAGE",&null_pvc,buf,strlen(msg)); } -void trace_uni(const char *comment,const void *msg,int size) +void trace_uni(const char *comment,const SIG_ENTITY *sig,const void *msg, + int size) { - void *buf; + char *buf; if (!trace_size) return; buf = alloc(size); memcpy(buf,msg,size); - store(&print_uni,comment,buf,size); + store(&print_uni,comment,&sig->signaling_pvc,buf,size); } @@ -263,7 +268,7 @@ if (!trace_size) return; buf = alloc_t(struct atmsvc_msg); *buf = *msg; - store(&print_kernel,comment,buf,sizeof(*msg)); + store(&print_kernel,comment,&null_pvc,buf,sizeof(*msg)); } @@ -276,8 +281,11 @@ string = NULL; } for (walk = first; walk; walk = walk->next) { - append("%6d (%d.%06d) %s:\n",walk->number,walk->time.tv_sec, + append("%6d (%d.%06d) %s",walk->number,walk->time.tv_sec, walk->time.tv_usec,walk->comment); + if (!walk->pvc.sap_family) append(":\n"); + else append(" (%d.%d.%d):\n",walk->pvc.sap_addr.itf, + walk->pvc.sap_addr.vpi,walk->pvc.sap_addr.vci); new_line = 1; walk->print(walk->msg,walk->size); } diff -ur --new-file old/atm/sigd/trace.h new/atm/sigd/trace.h --- old/atm/sigd/trace.h Thu Aug 20 18:04:26 1998 +++ new/atm/sigd/trace.h Thu Aug 20 18:06:41 1998 @@ -1,6 +1,6 @@ /* trace.h - Support functions for message tracing */ -/* Written 1996 by Werner Almesberger, EPFL-LRC */ +/* Written 1996,1998 by Werner Almesberger, EPFL-LRC */ #ifndef TRACE_H @@ -8,10 +8,14 @@ #include +#include "proto.h" + + extern int trace_size; void trace_msg(const char *msg); -void trace_uni(const char *comment,const void *msg,int size); +void trace_uni(const char *comment,const SIG_ENTITY *sig,const void *msg, + int size); void trace_kernel(const char *comment,const struct atmsvc_msg *msg); char *get_trace(void); diff -ur --new-file old/atm/sigd/uni.c new/atm/sigd/uni.c --- old/atm/sigd/uni.c Mon Oct 5 18:56:01 1998 +++ new/atm/sigd/uni.c Sun Nov 1 16:57:28 1998 @@ -43,56 +43,63 @@ q_create(&dsc,q_buffer,MAX_Q_MSG); q_assign(&dsc,QF_msg_type,ATM_MSG_CALL_PROC); q_assign(&dsc,QF_call_ref,sock->call_ref); - if (net && allocate_ci) { - int vci; + if (sock->sig->mode == sm_net) { + int vpci,vci; - vci = get_vci(0); + sock->pvc.sap_family = AF_ATMPVC; + vpci = sock->sig->signaling_pvc.sap_addr.itf; + sock->pvc.sap_addr.itf = get_itf(sock->sig,&vpci); + sock->pvc.sap_addr.vpi = vpci; + vci = get_vci(sock->pvc.sap_addr.itf); if (vci < 0) { (void) q_close(&dsc); return vci; } - sock->pvc.sap_family = AF_ATMPVC; - sock->pvc.sap_addr.itf = signaling_pvc.sap_addr.itf; - sock->pvc.sap_addr.vpi = 0; sock->pvc.sap_addr.vci = vci; } - if (net) { + if (sock->sig->mode != sm_user) { q_assign(&dsc,QF_vpi,sock->pvc.sap_addr.vpi); q_assign(&dsc,QF_vci,sock->pvc.sap_addr.vci); } if (sock->ep_ref >= 0) q_assign(&dsc,QF_ep_ref,sock->ep_ref); - if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); return 0; } -static void setup_call(unsigned long call_ref) +static void setup_call(SIG_ENTITY *sig,unsigned long call_ref) { SOCKET *sock,*this,**walk; struct sockaddr_atmsvc in_addr; struct atm_sap in_sap; struct atm_qos in_qos; + unsigned int problem; int i; - sap_decode(&in_dsc,&in_addr,&in_sap,&in_qos); + problem = sap_decode(&in_dsc,&in_addr,&in_sap,&in_qos,sig->uni); + if (problem) { + send_release_complete(sig,call_ref,IE_PB_CAUSE(problem), + IE_PB_IE(problem)); + return; + } if (!atmsvc_addr_in_use(in_addr)) { - send_release_complete(call_ref,ATM_CV_UNALLOC); + send_release_complete(sig,call_ref,ATM_CV_UNALLOC); return; } if (!allow(&in_addr,ACL_IN)) { - send_release_complete(call_ref,ATM_CV_REJ_CLIR); + send_release_complete(sig,call_ref,ATM_CV_REJ_CLIR); return; } this = new_sock(0); + this->sig = sig; sock = lookup_sap(&in_addr,&in_sap,&in_qos,&this->local,&this->sap, &this->qos,0); if (!sock) { free_sock(this); - send_release_complete(call_ref,ATM_CV_INCOMP_DEST); + send_release_complete(sig,call_ref,ATM_CV_INCOMP_DEST); return; } - this->qos.aal = ATM_AAL5; /* hack @@@ */ - this->state = net && allocate_ci ? ss_proceeding : ss_indicated; + this->state = sig->mode == sm_net ? ss_proceeding : ss_indicated; this->call_state = cs_in_proc; this->call_ref = call_ref; if (q_present(&in_dsc,QF_ep_ref)) @@ -100,24 +107,24 @@ #ifdef CISCO else #endif - if (net && allocate_ci) { + if (sig->mode == sm_net) { int error; error = send_call_proceeding(this); if (error) { free_sock(this); - send_release_complete(call_ref,ATM_CV_NO_CI); + send_release_complete(sig,call_ref,ATM_CV_NO_CI); return; } } /* if (sock->local) *this->local->sas_addr = sock->local->sas_addr; ??? */ diag(COMPONENT,DIAG_DEBUG,"AAL type %ld",q_fetch(&in_dsc,QF_aal_type)); - if (!net) { /* already set by send_call_proceeding */ + if (sig->mode == sm_user) { /* already set by send_call_proceeding */ int vpci; vpci = q_fetch(&in_dsc,QF_vpi); this->pvc.sap_family = AF_ATMPVC; - this->pvc.sap_addr.itf = get_itf(&vpci); + this->pvc.sap_addr.itf = get_itf(sig,&vpci); this->pvc.sap_addr.vpi = vpci; this->pvc.sap_addr.vci = q_fetch(&in_dsc,QF_vci); } @@ -159,7 +166,7 @@ } -static void send_status(SOCKET *sock,unsigned long call_ref, +static void send_status(SIG_ENTITY *sig,SOCKET *sock,unsigned long call_ref, unsigned char cause,...) { va_list ap; @@ -200,7 +207,7 @@ ; } va_end(ap); - if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + if ((size = q_close(&dsc)) >= 0) to_signaling(sig,q_buffer,size); } @@ -213,7 +220,7 @@ q_assign(&dsc,QF_msg_type,ATM_MSG_STATUS_ENQ); q_assign(&dsc,QF_call_ref,sock->call_ref); if (sock->ep_ref >= 0) q_assign(&dsc,QF_ep_ref,sock->ep_ref); - if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); /* @@@ should start T322 */ } @@ -226,11 +233,11 @@ q_create(&dsc,q_buffer,MAX_Q_MSG); q_assign(&dsc,QF_msg_type,ATM_MSG_CONN_ACK); q_assign(&dsc,QF_call_ref,sock->call_ref); - if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); } -static void send_restart_ack(int vpi,int vci) +static void send_restart_ack(SIG_ENTITY *sig,int vpi,int vci) { Q_DSC dsc; int size; @@ -244,12 +251,12 @@ q_assign(&dsc,QF_vpi,vpi); q_assign(&dsc,QF_vci,vci); } - if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + if ((size = q_close(&dsc)) >= 0) to_signaling(sig,q_buffer,size); } -static void send_drop_party_ack(unsigned long call_ref,short ep_ref, - unsigned char cause) +static void send_drop_party_ack(SIG_ENTITY *sig,unsigned long call_ref, + short ep_ref,unsigned char cause) { Q_DSC dsc; int size; @@ -259,11 +266,11 @@ q_assign(&dsc,QF_call_ref,call_ref); q_assign(&dsc,QF_ep_ref,ep_ref); q_assign(&dsc,QF_cause,cause); - if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + if ((size = q_close(&dsc)) >= 0) to_signaling(sig,q_buffer,size); } -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) static void send_conn_avail(SOCKET *sock) { @@ -273,7 +280,7 @@ q_create(&dsc,q_buffer,MAX_Q_MSG); q_assign(&dsc,QF_msg_type,ATM_MSG_CONN_AVAIL); q_assign(&dsc,QF_call_ref,sock->call_ref); - if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); } #endif @@ -310,7 +317,8 @@ switch (mid) { case ATM_MSG_CALL_PROC: /* CONNECTING, WAIT_REL, REL_REQ */ if (sock->state == ss_wait_rel || sock->state == ss_rel_req) { - send_status(sock,0,ATM_CV_INCOMP_MSG,ATM_MSG_CALL_PROC); + send_status(sock->sig,sock,0,ATM_CV_INCOMP_MSG, + ATM_MSG_CALL_PROC); return; } if (sock->state != ss_connecting) break; @@ -321,7 +329,7 @@ vpci = q_fetch(&in_dsc,QF_vpi); sock->pvc.sap_family = AF_ATMPVC; - sock->pvc.sap_addr.itf = get_itf(&vpci); + sock->pvc.sap_addr.itf = get_itf(sock->sig,&vpci); sock->pvc.sap_addr.vpi = vpci; sock->pvc.sap_addr.vci = q_fetch(&in_dsc,QF_vci); diag(COMPONENT,DIAG_DEBUG,"ITF.VPI.VCI: %d.%d.%d", @@ -333,7 +341,7 @@ return; case ATM_MSG_CONNECT: /* CONNECTING, REL_REQ */ if (sock->state == ss_rel_req) { - send_status(sock,0,ATM_CV_INCOMP_MSG,ATM_MSG_CONNECT); + send_status(sock->sig,sock,0,ATM_CV_INCOMP_MSG,ATM_MSG_CONNECT); return; } if (sock->state != ss_connecting) break; @@ -343,7 +351,7 @@ vpci = q_fetch(&in_dsc,QF_vpi); sock->pvc.sap_family = AF_ATMPVC; - sock->pvc.sap_addr.itf = get_itf(&vpci); + sock->pvc.sap_addr.itf = get_itf(sock->sig,&vpci); sock->pvc.sap_addr.vpi = vpci; sock->pvc.sap_addr.vci = q_fetch(&in_dsc,QF_vci); diag(COMPONENT,DIAG_DEBUG,"ITF.VPI.VCI: %d/%d.%d", @@ -367,19 +375,20 @@ send_kernel(sock->id,0,as_okay,0,&sock->pvc,NULL,&sock->local, &sock->sap,&sock->qos); new_state(sock,ss_connected); -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) sock->owner = 1; #endif if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) - &sock->local,0) < 0) strcpy(buffer,""); + &sock->remote,0) < 0) strcpy(buffer,""); diag(COMPONENT,DIAG_INFO,"Active open succeeded (CR 0x%06X, " - "ID 0x%08x, addr %s)",sock->call_ref,sock->id,buffer); + "ID 0x%08x, to %s)",sock->call_ref,sock->id,buffer); return; case ATM_MSG_CONN_ACK: /* ACCEPTING, WAIT_REL, REL_REQ */ diag(COMPONENT,DIAG_DEBUG,"CA vpi.vci=%d.%d", sock->pvc.sap_addr.vpi,sock->pvc.sap_addr.vci); if (sock->state == ss_wait_rel || sock->state == ss_rel_req) { - send_status(sock,0,ATM_CV_INCOMP_MSG,ATM_MSG_CONN_ACK); + send_status(sock->sig,sock,0,ATM_CV_INCOMP_MSG, + ATM_MSG_CONN_ACK); return; } if (sock->state != ss_accepting) break; @@ -387,13 +396,13 @@ send_kernel(sock->id,0,as_okay,0,NULL,NULL,&sock->local,&sock->sap, NULL); new_state(sock,ss_connected); -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) sock->owner = 0; #endif if (atm2text(buffer,MAX_ATM_ADDR_LEN+1, (struct sockaddr *) - &sock->local,0) < 0) strcpy(buffer,""); + &sock->remote,0) < 0) strcpy(buffer,""); diag(COMPONENT,DIAG_INFO,"Passive open succeeded (CR 0x%06X, " - "ID 0x%08x, addr %s)",sock->call_ref,sock->id,buffer); + "ID 0x%08x, from %s)",sock->call_ref,sock->id,buffer); return; case ATM_MSG_RELEASE: /* all states */ { @@ -409,7 +418,7 @@ /* fall through */ case ss_accepting: set_error(sock,-ECONNRESET); /* ERESTARTSYS ? */ - send_release_complete(sock->call_ref,0); + send_release_complete(sock->sig,sock->call_ref,0); SEND_ERROR(sock->id,sock->error); STOP_TIMER(sock); free_sock(sock); @@ -421,12 +430,12 @@ STOP_TIMER(sock); free_sock(sock); return; -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) case ss_mod_req: #endif STOP_TIMER(sock); /* fall through */ -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) case ss_mod_lcl: case ss_mod_rcv: case ss_mod_fin_ok: @@ -436,7 +445,7 @@ case ss_connected: diag(COMPONENT,DIAG_INFO,"Passive close (CR 0x%06X)", sock->call_ref); -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) if (timer_handler(sock->conn_timer) == on_T361) STOP_TIMER(sock); #endif @@ -446,14 +455,14 @@ case ss_indicated: /* fall through */ case ss_proceeding: - send_release_complete(sock->call_ref,0); + send_release_complete(sock->sig,sock->call_ref,0); new_state(sock,ss_zombie); /* fall through */ case ss_rel_ind: return; default: - send_release_complete(sock->call_ref,0); /* @@@ should - be ATM_CV_INCOMP_MSG */ + send_release_complete(sock->sig,sock->call_ref,0); + /* @@@ should be ATM_CV_INCOMP_MSG */ break; } break; @@ -477,7 +486,7 @@ case ss_connecting: set_error(sock,cause == ATM_CV_UNALLOC ? -EADDRNOTAVAIL : cause == ATM_CV_RES_UNAVAIL || -#if defined(UNI31) || defined(UNI40) +#if defined(UNI31) || defined(UNI40) || defined(DYNAMIC_UNI) cause == ATM_CV_UCR_UNAVAIL_NEW || #endif cause == ATM_CV_NO_ROUTE_DEST ? -EHOSTUNREACH : @@ -498,12 +507,12 @@ STOP_TIMER(sock); free_sock(sock); return; -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) case ss_mod_req: #endif STOP_TIMER(sock); /* fall through */ -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) case ss_mod_lcl: case ss_mod_rcv: case ss_mod_fin_ok: @@ -513,7 +522,7 @@ case ss_connected: diag(COMPONENT,DIAG_INFO,"Passive close (CR 0x%06X)", sock->call_ref); -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) if (timer_handler(sock->conn_timer) == on_T361) STOP_TIMER(sock); #endif @@ -542,7 +551,7 @@ vpci = q_fetch(&in_dsc,QF_vpi); sock->pvc.sap_family = AF_ATMPVC; - sock->pvc.sap_addr.itf = get_itf(&vpci); + sock->pvc.sap_addr.itf = get_itf(sock->sig,&vpci); sock->pvc.sap_addr.vpi = vpci; sock->pvc.sap_addr.vci = q_fetch(&in_dsc,QF_vci); diag(COMPONENT,DIAG_DEBUG,"ITF.VPI.VCI: %d.%d.%d", @@ -553,11 +562,12 @@ case ATM_MSG_NOTIFY: /* silently ignore this junk */ return; -#ifdef Q2963_1 +#if defined(Q2963_1) || defined(DYNAMIC_UNI) /* * Buglet ahead: should actually test "call_state" */ case ATM_MSG_MODIFY_REQ: + if (!(sock->sig->uni & S_Q2963_1)) goto _default; if (sock->state != ss_connected || sock->owner) break; sock->new_qos = sock->qos; if (q_present(&in_dsc,QF_fw_pcr_01)) @@ -569,6 +579,7 @@ new_state(sock,ss_mod_rcv); return; case ATM_MSG_MODIFY_ACK: + if (!(sock->sig->uni & S_Q2963_1)) goto _default; if (sock->state != ss_mod_req) break; STOP_TIMER(sock); sock->qos = sock->new_qos; @@ -578,6 +589,7 @@ new_state(sock,ss_mod_fin_ok); return; case ATM_MSG_MODIFY_REJ: + if (!(sock->sig->uni & S_Q2963_1)) goto _default; if (sock->state != ss_mod_req) break; STOP_TIMER(sock); sock->error = -EAGAIN; @@ -586,60 +598,63 @@ new_state(sock,ss_mod_fin_fail); return; case ATM_MSG_CONN_AVAIL: + if (!(sock->sig->uni & S_Q2963_1)) goto _default; if (sock->state != ss_connected || !sock->owner) break; STOP_TIMER(sock); send_kernel(sock->id,0,as_modify,ATM_MF_SET,NULL,NULL,NULL,NULL, &sock->qos); new_state(sock,ss_mod_fin_ack); return; + _default: /* jump here if we don't want to understand a message */ #endif default: diag(COMPONENT,DIAG_WARN,"Bad signaling message %d",mid); - send_status(sock,0,ATM_CV_UNKNOWN_MSG_TYPE,mid); + send_status(sock->sig,sock,0,ATM_CV_UNKNOWN_MSG_TYPE,mid); return; } diag(COMPONENT,DIAG_WARN, "Signaling message %s is incompatible with state %s/%s (%d?%d)", mid2name(mid),state_name[sock->state],cs_name[sock->call_state], (int) sock->state,(int) sock->call_state); - send_status(sock,0,ATM_CV_INCOMP_MSG,mid); + send_status(sock->sig,sock,0,ATM_CV_INCOMP_MSG,mid); } -void clear_all_calls(void) +void clear_all_calls(SIG_ENTITY *sig) { SOCKET *curr,*next; for (curr = sockets; curr; curr = next) { next = curr->next; - if (curr->call_state != cs_null) uni_call(curr,ATM_MSG_RESTART); + if (curr->sig == sig && curr->call_state != cs_null) + uni_call(curr,ATM_MSG_RESTART); } } -void clear_all_calls_on_T309(void) +void clear_all_calls_on_T309(SIG_ENTITY *sig) { - clear_all_calls(); + clear_all_calls(sig); t309 = NULL; } -void saal_failure(void) +void saal_failure(SIG_ENTITY *sig) { SOCKET *curr,*next; trace_msg("SAAL went down"); for (curr = sockets; curr; curr = next) { next = curr->next; - if (curr->call_state != cs_null) + if (curr->sig == sig && curr->call_state != cs_null) if (curr->call_state != cs_active) uni_call(curr,ATM_MSG_RESTART); - else if (!t309) t309 = start_timer(T309_TIME,on_T309,NULL); + else if (!t309) t309 = start_timer(T309_TIME,on_T309,sig); } } -void saal_okay(void) +void saal_okay(SIG_ENTITY *sig) { SOCKET *curr; @@ -657,23 +672,24 @@ Q_DSC dsc; int size; - clear_all_calls(); + clear_all_calls(sig); q_create(&dsc,q_buffer,MAX_Q_MSG); q_assign(&dsc,QF_msg_type,QMSG_RESTART); q_assign(&dsc,QF_call_ref,0); q_assign(&dsc,QF_rst_class,ATM_RST_ALL_VC); - if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + if ((size = q_close(&dsc)) >= 0) to_signaling(sig,q_buffer,size); } #endif if (!t309) return; stop_timer(t309); t309 = NULL; for (curr = sockets; curr; curr = curr->next) - if (curr->call_state != cs_null) send_status_enq(curr); + if (curr->sig == sig && curr->call_state != cs_null) + send_status_enq(curr); } -static void process_uni(void *msg) +static void process_uni(SIG_ENTITY *sig,void *msg) { SOCKET *curr; unsigned long call_ref; @@ -692,69 +708,70 @@ int vpi,vci; if (!q_present(&in_dsc,QG_conn_id)) { - send_status(NULL,0L,ATM_CV_MAND_IE_MISSING, + send_status(sig,NULL,0L,ATM_CV_MAND_IE_MISSING, ATM_IE_CONN_ID); return; } vpi = q_fetch(&in_dsc,QF_vpi); vci = q_fetch(&in_dsc,QF_vci); for (curr = sockets; curr; curr = curr->next) - if (curr->pvc.sap_addr.vpi == vpi && + if (curr->sig == sig && curr->pvc.sap_addr.vpi == vpi && curr->pvc.sap_addr.vci == vci) break; if (!curr) { - send_status(NULL,0L,ATM_CV_INVALID_IE, + send_status(sig,NULL,0L,ATM_CV_INVALID_IE, ATM_IE_CONN_ID); return; } uni_call(curr,mid); - send_restart_ack(vpi,vci); + send_restart_ack(sig,vpi,vci); } break; case ATM_RST_ALL_VC: - clear_all_calls(); - send_restart_ack(0,0); + clear_all_calls(sig); + send_restart_ack(sig,0,0); break; default: - send_status(NULL,0L,ATM_CV_INVALID_IE,ATM_IE_RESTART); + send_status(sig,NULL,0L,ATM_CV_INVALID_IE,ATM_IE_RESTART); } return; } if (!(call_ref & 0x7fffff)) { - return; /* bad things happen ... @@@ */ + diag(COMPONENT,DIAG_ERROR,"unrecognized global call ref"); + return; } for (curr = sockets; curr; curr = curr->next) - if (curr->call_ref == call_ref) break; - diag(COMPONENT,DIAG_DEBUG,"FROM SAAL: %s (0x%02X) CR 0x%06lx for 0x%lx", - mid2name(((unsigned char *) msg)[5]),((unsigned char *)msg)[5],call_ref, - curr ? curr->id : 0); + if (curr->sig == sig && curr->call_ref == call_ref) break; + diag(COMPONENT,DIAG_DEBUG,"FROM SAAL %d.%d.%d: %s (0x%02X) CR 0x%06lx for " + "0x%lx",S_PVC(sig),mid2name(((unsigned char *) msg)[5]), + ((unsigned char *)msg)[5],call_ref,curr ? curr->id : 0); if (mid == ATM_MSG_SETUP) { - if (!curr) setup_call(call_ref); + if (!curr) setup_call(sig,call_ref); return; } if (mid == ATM_MSG_STATUS_ENQ) { - send_status(curr,call_ref,ATM_CV_RESP_STAT_ENQ); + send_status(curr->sig,curr,call_ref,ATM_CV_RESP_STAT_ENQ); return; } if (curr && q_present(&in_dsc,QF_ep_ref) && mid != ATM_MSG_ADD_PARTY && mid != ATM_MSG_DROP_PARTY_ACK) if (curr->ep_ref != q_fetch(&in_dsc,QF_ep_ref)) { - send_drop_party_ack(call_ref,q_fetch(&in_dsc,QF_ep_ref), + send_drop_party_ack(sig,call_ref,q_fetch(&in_dsc,QF_ep_ref), ATM_CV_INV_EPR); return; } if (!curr || curr->call_state == cs_null) { if (mid != ATM_MSG_REL_COMP) if (mid != ATM_MSG_STATUS) - send_release_complete(call_ref,ATM_CV_INV_CR); + send_release_complete(sig,call_ref,ATM_CV_INV_CR); else if (q_fetch(&in_dsc,QF_call_state) != (int) cs_null) - send_release_complete(call_ref,ATM_CV_INCOMP_MSG); + send_release_complete(sig,call_ref,ATM_CV_INCOMP_MSG); return; } uni_call(curr,mid); } -static void abort_call(unsigned char *msg,int size) +static void abort_call(SIG_ENTITY *sig,unsigned char *msg,int size) { SOCKET *curr; unsigned long call_ref; @@ -768,21 +785,21 @@ diag(COMPONENT,DIAG_ERROR,"can't parse message - aborting the call " "(CR 0x%06lx)",call_ref); for (curr = sockets; curr; curr = curr->next) - if (curr->call_ref == call_ref) { + if (curr->sig == sig && curr->call_ref == call_ref) { uni_call(curr,ATM_MSG_RESTART); break; } - send_release_complete(call_ref,ATM_CV_PROTOCOL_ERROR); + send_release_complete(sig,call_ref,ATM_CV_PROTOCOL_ERROR); } -void to_uni(void *msg,int size) +void to_uni(SIG_ENTITY *sig,void *msg,int size) { if (q_open(&in_dsc,msg,size) < 0) { - abort_call(msg,size); + abort_call(sig,msg,size); return; } - process_uni(msg); + process_uni(sig,msg); if (q_close(&in_dsc) < 0) diag(COMPONENT,DIAG_ERROR,"q_close returned <0 in to_uni"); } diff -ur --new-file old/atm/sigd.new/Makefile new/atm/sigd.new/Makefile --- old/atm/sigd.new/Makefile Fri Aug 21 00:28:34 1998 +++ new/atm/sigd.new/Makefile Thu Jan 1 01:00:00 1970 @@ -1,39 +0,0 @@ -LIBS=-L../saal -lsaal -latmd -lfl # lex may want -ll here -LIBDEPS=../saal/libsaal.a ../lib/libatmd.a -INCLUDES=-I../qgen -I../saal -I. -OBJS=atmsigd.o io.o kernel.o mess.o proto.o uni.o sap.o timeout.o trace.o \ - policy.o lex.yy.o y.tab.o -EXTOBJS=../qgen/q.out.o ../qgen/qd.dump.o -#BOOTPGMS=atmsigd # don't install yet -PGMS=atmsigd.new -TRASH=mess.c -#MAN4=atmsigd.conf.4 # don't install yet -#MAN8=atmsigd.8 # don't install yet - -include ../Rules.make -CFLAGS_NOWARN += $(STANDARDS) - -atmsigd.new: $(OBJS) $(EXTOBJS) - $(CC) $(LDFLAGS) -o atmsigd.new $(OBJS) $(EXTOBJS) \ - $(LDLIBS) $(LIBS) - -lex.yy.c: cfg.l y.tab.h ../lib/atm.h - $(LEX) cfg.l - -y.tab.c y.tab.h: cfg.y ../lib/atmd.h proto.h io.h - $(YACC) -d cfg.y - -mess.c: ../qgen/uni.h mkmess.pl - perl ./mkmess.pl <../qgen/uni.h >mess.c - -# -# The following hack makes sure that "make depend" finds q.out.h and is -# happy with it. Once qgen has been built, there will be ../qgen/q.out.h, -# which is first in the include file search path and therefore gets -# included. An second "make depend" will also use the right file. -# - -depend: fake_q.out.h - -fake_q.out.h: - echo "! This must not compile" >q.out.h diff -ur --new-file old/atm/sigd.new/README new/atm/sigd.new/README --- old/atm/sigd.new/README Fri Aug 21 00:47:03 1998 +++ new/atm/sigd.new/README Thu Jan 1 01:00:00 1970 @@ -1,25 +0,0 @@ -This is a very early version of atmsigd that supports multiple signaling -entities in the same process. Everything's still a bit buggy and ugly. - -To play with it, ... - -1) Generate ATM interfaces 1 and 2: - # atmtcp -b -i 1 -l - # atmtcp -b -i 2 -c localhost -2) Create the following configuration file (name "config"): - entity 1.0.5 { mode user route +1 } - entity 2.0.5 { mode network default } -3) Launch atmsigd: - # ./atmsigd.new -c config -4) Add local addresses: - # atmaddr -a 1 +1 - # atmaddr -a 2 +2 -5) Test it: - % ttcp_atm -r -a - % ttcp_atm -t -a +1 - -Known bugs: - - wildcard bind removes wildcard - - selection of local address isn't consistent with signaling interface - selection - - everything else that's marked with @@@ diff -ur --new-file old/atm/sigd.new/atmsigd.8 new/atm/sigd.new/atmsigd.8 --- old/atm/sigd.new/atmsigd.8 Thu Jun 25 13:08:40 1998 +++ new/atm/sigd.new/atmsigd.8 Thu Jan 1 01:00:00 1970 @@ -1,105 +0,0 @@ -.TH ATMSIGD 8 "June 25, 1998" "Linux" "Maintenance Commands" -.SH NAME -atmsigd \- ATM signaling demon -.SH SYNOPSIS -.B atmsigd -.RB [ \-b ] -.RB [ \-c\ \fIconfig_file\fP ] -.RB [ \-d ] -.RB [ \-D\ \fIdump_dir\fP ] -.RB [ \-l\ \fIlogfile\fP ] -.RB [ \-m\ \fImode\fP ] -.RB [ \-n ] -.RB [ \-q\ \fIqos\fP ] -.RB [ \-t\ \fItrace_length\fP ] -.RB [ [\fIitf\fP.]\fIvpi\fP.\fIvci\fP -.RB [ \fIinput\ output\fP ] ] -.SH DESCRIPTION -\fBatmsigd\fP implements the ATM UNI signaling protocol. Requests to -establish, accept, or close ATM SVCs are sent from the kernel (using a -comparably simple protocol) to the signaling demon, which then performs -the dialog with the network. -.P -Note that \fBatmsigd\fP is not able to accept or establish connections -until the local ATM address of the interface is configured by \fBilmid\fP -or manually using \fBatmaddr\fP. -.P -The default signaling VC (interface 0, VPI 0, VCI 5) can be overridden on -the command line by specifying a different PVC address. -.P -When overriding the default VC, optionally a pair of named pipes to use for -communicating with the user of signaling can be specified. Normally, the -kernel is the user of signaling and \fBatmsigd\fP opens a special socket for -communication with it. -.P -If \fBatmsigd\fP is killed, all system calls requiring interaction with it -will return with an error and set \fBerrno\fP to \fBEUNATCH\fP. -.SH OPTIONS -.IP \fB\-b\fP -Run in background (i.e. in a forked child process) after initializing. -.IP \fB\-c\ \fIconfig_file\fP -Use the specified configuration file instead of \fB/etc/atmsigd.conf\fP -If an option is specified in the configuration file and on the command -line, the command line has priority. -.IP \fB\-d\fP -Enables (lots of) debugging output. By default, \fBatmsigd\fP is comparably -quiet. -.IP \fB\-D\ \fIdump_dir\fP -Specifies the directory to which \fBatmsigd\fP will write status and trace -dumps. If tracing is not yet enabled, the trace size is automatically -set to a (small) default value. -.IP \fB\-l\ \fIlogfile\fP -Write diagnostic messages to the specified file. The special name -\fBsyslog\fP is used to send diagnostics to the system logger, \fBstderr\fP -is used to send diagnostics to standard error. If \fB\-l\fP is absent, the -setting in \fBatmsigd.conf\fP is used. If \fBatmsigd\fP doesn't specify a -destination either, messages are written to standard error. -.IP \fB\-m\ \fImode\fP -Set the mode of operation. The following modes are available: \fBuser\fP for -the user side (the default), \fBnetwork\fP for the network side (useful if you -have two PCs but no switch), and \fBswitch\fP for operation with a signaling -relay in a switch. -.IP \fB\-n\fP -Prints addresses in numeric format only, i.e. no address to name translation -is attempted. -.IP \fB\-q\ \fIqos\fP -Configures the signaling VC to use the specified quality of service (see -qos(7) for the syntax). -By default, UBR at link speed is used on the signaling VC. -.IP \fB\-t\ \fItrace_length\fP -Enables tracing and sets the number -of entries that should be kept in the trace buffer. -.SH FILES -.PD 0 -.TP 25 -.B /etc/atmsigd.conf -default configuration file -.TP 25 -.B /var/tmp/atmsigd.\fIpid\fB.status.\fIversion\fP -default location of status dumps -.TP 25 -.B /var/tmp/atmsigd.\fIpid\fB.trace.\fIversion\fP -default location of signaling trace dumps -.PD -.SH DEBUGGING -When receiving a \fBSIGUSR1\fP signals, \fBatmsigd\fP dumps the list of all -internal socket descriptors. With \fBSIGUSR2\fP, it dumps the contents of -the trace buffer. If a dump directory was set, dumps are written to files -called \fBatmsigd.\fP\fIpid\fP\fB.status.\fP\fInumber\fP and -\fBatmsigd.\fP\fIpid\fP\fB.trace.\fP\fInumber\fP, respectively, with -\fInumber\fP -starting at zero and being incremented for every dump. If no dump directory -is set, dumps are written to standard error. -.P -Dumps are also generated whenever \fBatmsigd\fP detects a fatal error and -terminates. No attempt is made to catch signals like \fBSIGSEGV\fP. -.SH BUGS -The generation of traces is a comparably slow -process which may already take several seconds for only 100 trace entries. -To generate a trace dump, \fBatmsigd\fP therefore forks a child process that -runs in parallel to the signaling demon. -.SH AUTHOR -Werner Almesberger, EPFL ICA -.SH "SEE ALSO" -atmaddr(8), atmsigd.conf(4), ilmid(8), qos(7) -.\"{{{}}} diff -ur --new-file old/atm/sigd.new/atmsigd.c new/atm/sigd.new/atmsigd.c --- old/atm/sigd.new/atmsigd.c Mon Oct 5 19:12:57 1998 +++ new/atm/sigd.new/atmsigd.c Thu Jan 1 01:00:00 1970 @@ -1,477 +0,0 @@ -/* atmsigd.c - ATM signaling demon */ - -/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "atm.h" -#include "atmd.h" -#include "qlib.h" - -#include "io.h" -#include "proto.h" -#include "saal.h" -#include "trace.h" - - -#define COMPONENT "SIGD" -#define CONFIG_FILE "/etc/atmsigd.conf" - - -extern int yyparse(void); -extern FILE *yyin; - -int debug = 0; -int pretty = A2T_PRETTY | A2T_NAME | A2T_LOCAL; -const char *dump_dir = NULL; - - -/* A little hack until we have full support for multiple signaling entities */ - -SIG_ENTITY _entity = { - 0, /* fd */ - 0, /* unspecified UNI version */ - sm_user, /* mode */ - -1, /* sig_pcr; obsolete @@@ */ - NULL /* sig_qos */ -}; - - -/* ------------------------------ SAAL relays ------------------------------ */ - - -static void q_estab_conf(void *user_data,void *uu_data,int uu_length) -{ - SIG_ENTITY *sig = user_data; - - saal_okay(sig); -} - - -static void q_rel_ind(void *user_data,void *uu_data,int uu_length) -{ - SIG_ENTITY *sig = user_data; - - saal_failure(sig); - saal_estab_req(&sig->saal,NULL,0); -} - - -static void q_restart(void *user_data,void *uu_data,int uu_length,int ind) -{ - SIG_ENTITY *sig = user_data; - - saal_failure(sig); - if (!ind) saal_okay(sig); - /* actually, ind should probably never be zero */ -} - - -void from_net(SIG_ENTITY *sig,void *buffer,int size) -{ - saal_pdu(&sig->saal,buffer,size); -} - - -void to_signaling(SIG_ENTITY *sig,void *msg,int size) -{ - trace_uni("TO NETWORK",sig,msg,size); - diag(COMPONENT,DIAG_DEBUG,"TO SAAL (%d.%d.%d): %s (0x%02x) CR 0x%06x " - "(%d bytes)",S_PVC(sig), - mid2name(((unsigned char *) msg)[5]),((unsigned char *) msg)[5], - (((unsigned char *) msg)[2] << 16) | (((unsigned char *) msg)[3] << 8) | - ((unsigned char *) msg)[4],size); - saal_send(&sig->saal,msg,size); -} - - -static void q_data_ind(void *user_data,void *data,int length) -{ - SIG_ENTITY *sig = user_data; - - trace_uni("FROM NETWORK",sig,data,length); - to_uni(sig,data,length); -} - - -static void q_cpcs_send(void *user_data,void *data,int length) -{ - SIG_ENTITY *sig = user_data; - - to_net(sig,data,length); -} - - -static SAAL_USER_OPS ops = { - NULL, /* no q_estab_ind - 5.5.6.9 says 5.5.6.11 and 5.5.6.11 says "may" */ - q_estab_conf, - q_rel_ind, - NULL, /* no q_rel_conf - what to do ? */ - q_restart, - q_data_ind, - NULL, /* no q_unitdata */ - q_cpcs_send -}; - - -/* -------------------------------- signals -------------------------------- */ - - -static volatile int got_usr1 = 0,got_usr2 = 0; - - -static void dump_addr(FILE *file,const char *label,struct sockaddr_atmsvc *addr) -{ - char buffer[MAX_ATM_ADDR_LEN+1]; - int i; - - if (!atmsvc_addr_in_use(*addr)) return; - fprintf(file," %s ",label); - if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) addr,A2T_NAME | - A2T_PRETTY | A2T_LOCAL) >= 0) fprintf(file,"%s\n",buffer); - else { - fprintf(file,"\n"); - } -} - - -static void dump_sap(FILE *file,const char *label,struct atm_sap *sap) -{ - char buffer[MAX_ATM_SAP_LEN+1]; - int i; - - fprintf(file," %s ",label); - if (sap2text(buffer,MAX_ATM_SAP_LEN+1,sap,S2T_NAME | S2T_LOCAL) >= 0) - fprintf(file,"%s\n",buffer); - else { - fprintf(file,"\n"); - } -} - - -static void dump_status(FILE *file,const char *banner) -{ - SIG_ENTITY *sig; - SOCKET *walk; - - if (entities) fprintf(file,"%s\n\n",banner); - for (sig = entities; sig; sig = sig->next) { - fprintf(file,"--- Entity %d.%d.%d ---\n",S_PVC(sig)); - for (walk = sockets; walk; walk = walk->next) { - fprintf(file,"0x%lx: %s, CR 0x%06lX, PVC %d.%d.%d\n",walk->id, - state_name[walk->state],walk->call_ref,walk->pvc.sap_addr.itf, - walk->pvc.sap_addr.vpi,walk->pvc.sap_addr.vci); - dump_addr(file,"local ",&walk->local); - dump_addr(file,"remote",&walk->remote); - dump_sap(file,"sap",&walk->sap); - } - } -} - - -static void dump_trace(FILE *file,const char *banner) -{ - static int busy = 0; - char *trace; - - if (busy++) abort(); - trace = get_trace(); - if (trace) { - fprintf(file,"%s\n\n",banner); - fprintf(file,"%s",trace); - } - busy--; -} - - -void poll_signals(void) -{ - static status_num = 0,trace_num = 0; - char path[PATH_MAX+1]; - FILE *file; - - if (got_usr1) { - got_usr1 = 0; - if (!dump_dir) file = stderr; - else { - sprintf(path,"atmsigd.%d.status.%d",getpid(),status_num++); - if ((file = fopen(path,"w"))) - diag(COMPONENT,DIAG_INFO,"Dumping to %s",path); - else { - perror(path); - file = stderr; - } - } - dump_status(file,"Status dump (on SIGUSR1)"); - if (file != stderr) (void) fclose(file); - } - if (got_usr2) { - pid_t pid; - - got_usr2 = 0; - if (!dump_dir) file = stderr; - else { - sprintf(path,"atmsigd.%d.trace.%d",getpid(),trace_num++); - if ((file = fopen(path,"w"))) - diag(COMPONENT,DIAG_INFO,"Dumping to %s",path); - else { - perror(path); - file = stderr; - } - } - if (!(pid = fork())) - dump_trace(file,"Message trace (on SIGUSR2)"); - else if (pid < 0) perror("fork"); - if (file != stderr) (void) fclose(file); - if (!pid) exit(0); - } -} - - -static void handle_signal(int sig) -{ - switch (sig) { - case SIGUSR1: - got_usr1 = 1; - break; - case SIGUSR2: - got_usr2 = 1; - break; - default: - break; - } -} - - -static void setup_signals(void) -{ - struct sigaction act; - - (void) signal(SIGCHLD,SIG_IGN); /* reap children automatially */ - act.sa_handler = handle_signal; - sigemptyset(&act.sa_mask); - act.sa_flags = 0; - if (sigaction(SIGUSR1,&act,NULL) < 0) { - perror("sigaction"); - exit(1); - } - if (sigaction(SIGUSR2,&act,NULL) < 0) { - perror("sigaction"); - exit(1); - } -} - - -/* ------------------------------- main ... ------------------------------- */ - - -static void trace_on_exit(int status,void *dummy) -{ - char path[PATH_MAX+1]; - FILE *file; - - if (!status) return; - if (!dump_dir) file = stderr; - else { - sprintf(path,"atmsigd.%d.trace.exit",getpid()); - if (!(file = fopen(path,"w"))) { - perror(path); - file = stderr; - } - } - dump_trace(file,"Message trace (after error exit)"); - if (file != stderr) (void) fclose(file); -} - - -static void manual_override(void) -{ - /* - * Gross hack to avoid changing the command-line parameters ... @@@ - */ - entities = &_entity; - _entity.next = NULL; -} - - -static void usage(const char *name) -{ - fprintf(stderr,"usage: %s [ -b ] [ -c config_file ] [ -d ] " - "[ -D dump_dir ]\n" - " [ -l logfile ] [ -n ] [ -m user|network|switch ] [ -q qos ]\n" - " [ -t trace_length ] [ [itf.]vpi.vci [ socket_path ] ]\n",name); - exit(1); -} - - -int main(int argc,char **argv) -{ - SIG_ENTITY *sig; - const char *config_file; - char *end; - int c,background; - int net = 0,allocate_ci = 1; - - set_application("atmsigd"); - config_file = CONFIG_FILE; - dump_dir = NULL; - background = 0; - memset(&_entity.signaling_pvc,0,sizeof(_entity.signaling_pvc)); - /* 1st pass to get the -c option */ - while ((c = getopt(argc,argv,"Abc:dD:l:m:nNP:q:t:")) != EOF) - if (c == 'c') config_file = optarg; - if (!(yyin = fopen(config_file,"r"))) - diag(COMPONENT,DIAG_WARN,"%s not found. - Using defaults.",config_file); - else if (yyparse()) - diag(COMPONENT,DIAG_FATAL,"Error in config file. - Aborting."); - if (!atmpvc_addr_in_use(_entity.signaling_pvc)) - _entity.signaling_pvc.sap_addr.vci = 5; - if (!_entity.uni) _entity.uni = S_UNI30; - /* process all other options but -c */ - optind = 0; - while ((c = getopt(argc,argv,"Abc:dD:l:m:nNP:q:t:")) != EOF) - switch (c) { - case 'A': - manual_override(); - allocate_ci = 0; - break; - case 'b': - background = 1; - break; - case 'c': - /* already handled */ - break; - case 'd': - set_verbosity(NULL,DIAG_DEBUG); - set_verbosity("QMSG",DIAG_INFO); - set_verbosity("SSCOP",DIAG_INFO); - debug = 1; - /*q_dump = 1;*/ - break; - case 'D': - dump_dir = optarg; - if (!trace_size) trace_size = DEFAULT_TRACE_SIZE; - break; - case 'l': - set_logfile(optarg); - break; - case 'm': - manual_override(); - if (!strcmp(optarg,"user")) _entity.mode = sm_user; - else if (!strcmp(optarg,"network")) _entity.mode = sm_net; - else if (!strcmp(optarg,"switch")) _entity.mode = sm_switch; - else usage(argv[0]); - break; - case 'n': - pretty = A2T_PRETTY; - break; - case 'N': - manual_override(); - net = 1; - break; - case 'q': - manual_override(); - if (_entity.sig_pcr != -1) usage(argv[0]); - _entity.sig_qos = optarg; - break; - case 'P': /* obsolete */ - manual_override(); - if (_entity.sig_qos) usage(argv[0]); - _entity.sig_pcr = strtol(optarg,&end,0); - if (*end) usage(argv[0]); - diag(COMPONENT,DIAG_WARN,"option -P is obsolete, " - "please use -q qos instead"); - break; - case 't': - trace_size = strtol(optarg,&end,0); - if (*end) usage(argv[0]); - break; - default: - usage(argv[0]); - } - if (_entity.mode == sm_unknown) - if (net) { - if (allocate_ci) { - _entity.mode = sm_net; - diag(COMPONENT,DIAG_WARN,"option -N is obsolete, " - "please use -m network instead"); - } - else { - _entity.mode = sm_switch; - diag(COMPONENT,DIAG_WARN,"options -N -A are obsolete, " - "please use -m switch instead"); - } - } - else if (allocate_ci) _entity.mode = sm_user; - else usage(argv[0]); - if (optind < argc) { - manual_override(); - if (text2atm(argv[optind],(struct sockaddr *) &_entity.signaling_pvc, - sizeof(_entity.signaling_pvc),T2A_PVC) < 0) - diag(COMPONENT,DIAG_FATAL,"text2atm \"%s\": failed",argv[optind]); - optind++; - if (optind == argc-1) { - open_unix(argv[optind]); - optind++; - } - } - if (optind != argc) usage(argv[0]); - if (dump_dir) - if (chdir(dump_dir) < 0) - diag(COMPONENT,DIAG_ERROR,"chdir %s: %s",dump_dir,strerror(errno)); - for (sig = entities; sig; sig = sig->next) { - diag(COMPONENT,DIAG_INFO,"Linux ATM signaling %s " -#ifdef DYNAMIC_UNI - "(dynamic)" -#endif - ", version " VERSION " on %d.%d.%d", - sig->uni & S_UNI30 ? - sig->uni & S_UNI31 ? "UNI 3.1+3.0compat" : "UNI 3.0" : - sig->uni & S_UNI31 ? "UNI 3.1" : - sig->uni & S_Q2963_1 ? "UNI 4.0+Q.2963.1" : "UNI 4.0", - S_PVC(sig)); - diag(COMPONENT,DIAG_INFO,"Acting as %s", - sig->mode == sm_user ? "USER side" : - sig->mode == sm_net ? "NETWORK side" : "SWITCH"); - } - if (open_all()) return 1; - init_current_time(); - q_start(); - for (sig = entities; sig; sig = sig->next) { - if (sig->mode != sm_switch) init_addr(sig); - start_saal(&sig->saal,&ops,sig, - sig->uni == S_UNI30 ? sscop_qsaal1 : sscop_q2110); - saal_estab_req(&sig->saal,NULL,0); - } - setup_signals(); - if (background) { - pid_t pid; - - pid = fork(); - if (pid < 0) - diag(COMPONENT,DIAG_FATAL,"fork: %s",strerror(errno)); - if (pid) { - diag(COMPONENT,DIAG_DEBUG,"Backgrounding (PID %d)",pid); - exit(0); - } - } - (void) on_exit(trace_on_exit,NULL); - poll_loop(); - close_all(); - for (sig = entities; sig; sig = sig->next) stop_saal(&sig->saal); - return 0; -} diff -ur --new-file old/atm/sigd.new/atmsigd.conf.4 new/atm/sigd.new/atmsigd.conf.4 --- old/atm/sigd.new/atmsigd.conf.4 Mon Oct 5 19:07:05 1998 +++ new/atm/sigd.new/atmsigd.conf.4 Thu Jan 1 01:00:00 1970 @@ -1,119 +0,0 @@ -.TH ATMSIGD.CONF 4 "June 25, 1998" "Linux" "File Formats" -.SH NAME -atmsigd.conf \- configuration file for the ATM signaling demon -.SH SYNOPSIS -.B /etc/atmsigd.conf -.SH DESCRIPTION -\fBatmsigd.conf\fP contains configuration data for \fBatmsigd\fP. -\fBatmsigd\fP reads \fBatmsigd.conf\fP after parsing the command -line options, before connecting to the ATM network. -.P -Configuration parameters are arranged in functional groups. In order to -set a parameter, the name of the group, the name of the parameter, and -the parameter value(s) have to be specified, e.g. -.nf -.sp - sig level debug -.sp -.fi -decreases the logging threshold for messages related to signaling to the -\fBdebug\fP level. The following options are recognized: -.IP \fBdebug\ dump\ \fIpath\fP -Specifies the directory to which \fBatmsigd\fP will write status and trace -dumps. If tracing is not yet enabled, the trace size is automatically -set to a (small) default value. -.IP \fBdebug\ level\ \fIlevel\fP -Sets the default debug level to \fIlevel\fP. \fIlevel\fP can be any of -\fBdebug\fP, \fBinfo\fP, \fBwarn\fP, \fBerror\fP, and \fBfatal\fP. Only -messages with the same or a higher priority than the debug level are printed. -Note that -the command-line option \fB\-d\fP generates even more output (e.g. hexdumps -of all packets passing between \fBatmsigd\fP and the network) than -\fBdebug level debug\fP. -.IP \fBdebug\ log\ \fIpath\fP -Specifies the file to which \fBatmsigd\fP writes logging messages. When -using the special file name \fBsyslog\fP, messages are send to the -system logger instead. Log messages are written to standard output if no log -file is specified. Writing to standard output can also be explicitly requested -by using the special file name \fBstderr\fP. -.IP \fBdebug\ trace\ \fP[\fInumber\fP] -Enables tracing and optionally sets the number of entries that should be -kept in the trace buffer. A (small) default is used if the number is -omitted. -.IP \fBio\ level\ \fIlevel\fP -Sets the debug level for IO-related messages to \fIlevel\fP. -.IP \fBio\ qos\ \fIqos\fP -Configures the signaling VC to use the specified QOS (see qos(7) for the -syntax). By default, UBR at link speed is used on the signaling VC. -.IP \fBio\ vc\ \fP[\fIitf\fB.\fP]\fIvpi\fB.\fIvci\fP -Uses the specified VC for signaling messages instead of the usual 0.0.5. -.IP \fBsaal\ level\ \fIlevel\fP -Sets the debug level for messages related to SAAL (i.e. SSCF and SSCOP) to -\fIlevel\fP. -.IP \fBsig\ level\ \fIlevel\fP -Sets the debug level for messages related to signaling (Q.2931 or ISP) to -\fIlevel\fP. -.IP \fBsig\ mode\ \fImode\fP -Set the mode of operation. The following modes are available: \fBuser\fP for -the user side, \fBnetwork\fP for the network side, and \fBswitch\fP for -operation in a switch. The default behaviour is \fBuser\fP. -.IP \fBsig\ uni30\fP -Use UNI 3.0 signaling. If specified together with \fBsig uni31\fP, this -option sets UNI 3.1 signaling with a few backwards-compatibility extensions. -.IP \fBsig\ uni31\fP -Use UNI 3.1 signaling. This option can be combined with \fBsig uni30\fP (see -above). -.IP \fBsig\ uni40\fP -Use UNI 4.0 signaling. This option can be combined with \fBsig q2963_1\fP -(see below). -.IP \fBsig\ q2963_1\fP -Enable peak cell rate renegotiation. This option is only available with -UNI 4.0 signaling. -.IP \fBsig\ vpci\ \fIvpci\fB\ itf\ \fIitf\fP -Sets up a very simplistic type of routing. All calls with VPCI values -equal to or greater than \fIvpci\fP will be routed to \fIitf\fP, and their -VPI values will be set to the signaled VPCI minus \fIvpci\fP. Multiple -\fBsig vpci\fP entries can be used to support an arbitrary number of -interfaces. -Example: with \fBsig vpci 4 itf 1\fP, a call signaled for -VPCI/VCI 0.x is routed to 0.0.x, a call signaled for 6.y is routed to -1.2.y, etc. -.IP \fBpolicy\ level\ \fIlevel\fP -Sets the debug level for messages related to policy decisions to \fIlevel\fP. -.IP \fBpolicy\ \fIdecision\ direction\ address\fP -Takes the specified \fIdecision\fP for calls from or to \fIaddress\fP. -\fIdecision\fP can be either \fBallow\fP or \fBreject\fP. \fIdirection\fP is -either \fBfrom\fP or \fBto\fP. The \fIaddress\fP may be wildcarded by -prepending a slash and the number of significant bits (NSAP) or digits (E.164). -The rules are searched in the order in which they appear in \fBatmsigd.conf\fP -until the first match. If no rule matches, the call is allowed. -.P -When setting multiple parameters in the same group, the group name doesn't -have to be repeated if it is followed by the parameters in curly braces. -Example: -.nf -.sp - debug { - level warn - dump /var/tmp - log syslog - trace 100 - } -.sp -.fi -.P -Line breaks can be inserted in \fBatmsigd.conf\fP wherever spaces or tabs -are allowed. Everything between a `#' and the end of the line is considered -a comment. The `#' character cannot be escaped. -.P -If an option is specified in \fBatmsigd.conf\fP and on the command -line, the command line has priority. -.COMPATIBILITY -For historical reasons, synonyms (e.g. abbreviated or long forms) exist for -most keywords. Future versions of \fBatmsigd\fP will only recognize the -syntax described on this man page. -.SH AUTHOR -Werner Almesberger, EPFL ICA -.SH "SEE ALSO" -atmsigd(8), qos(7), syslogd(8) -.\"{{{}}} diff -ur --new-file old/atm/sigd.new/cfg.l new/atm/sigd.new/cfg.l --- old/atm/sigd.new/cfg.l Thu Aug 20 23:02:30 1998 +++ new/atm/sigd.new/cfg.l Thu Jan 1 01:00:00 1970 @@ -1,104 +0,0 @@ -%{ -/* cfg.l - configuration language */ - -/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ - - -#include -#include -#include -#include - -#include "atm.h" - -#include "y.tab.h" - - -static int lineno = 1; -static int token; /* f@#%ing flex doesn't grok return after BEGIN */ - - -void yyerror(const char *s); -void yywarn(const char *s); - -%} - -%s N -%s P - -%% - BEGIN(N); - -level return TOK_LEVEL; -debug return TOK_DEBUG; -info return TOK_INFO; -warn return TOK_WARN; -error return TOK_ERROR; -fatal return TOK_FATAL; -sig return TOK_SIG; -uni30 return TOK_UNI30; -uni31 return TOK_UNI31; -uni40 return TOK_UNI40; -[qQ].2963.1 return TOK_Q2963_1; -mode return TOK_MODE; -user return TOK_USER; -network return TOK_NET; -switch return TOK_SWITCH; -saal return TOK_SAAL; -vc return TOK_VC; -io return TOK_IO; -itf return TOK_ITF; -vpci return TOK_VPCI; -pcr return TOK_PCR; -policy return TOK_POLICY; -allow return TOK_ALLOW; -reject return TOK_REJECT; -entity return TOK_ENTITY; -default return TOK_DEFAULT; -dump { BEGIN(P); - token = TOK_DUMP_DIR; } -log { BEGIN(P); - token = TOK_LOGFILE; } -qos { BEGIN(P); /* syntacticly close to a path */ - token = TOK_QOS; } -from { BEGIN(P); /* syntacticly close to a path */ - token = TOK_FROM; } -to { BEGIN(P); /* syntacticly close to a path */ - token = TOK_TO; } -route { BEGIN(P); /* syntacticly close to a path */ - token = TOK_ROUTE; } -trace return TOK_TRACE; -[0-9]+ { char *end; - yylval.num = strtoul(yytext,&end,10); - if (*end) yyerror("invalid number"); - return TOK_NUMBER; } -[0-9]+\.[0-9]+(\.[0-9]+)? { - if (text2atm(yytext,(struct sockaddr *) &yylval.pvc, - sizeof(yylval.pvc),T2A_PVC) < 0) - yyerror("invalid signaling channel"); - return TOK_PVC; - } -

[^\t\n ]+ { BEGIN(N); - yylval.str = strdup(yytext); /* tiny leak ... */ - if (!yylval.str) { - perror("strdup"); - exit(1); - } - return token; } -\n?[\t ]* lineno += *yytext == '\n'; -#[^\n]*\n lineno++; -. return *yytext; - -%% - -void yywarn(const char *s) -{ - fprintf(stderr,"line %d: %s near \"%s\"\n",lineno,s,yytext); -} - - -void yyerror(const char *s) -{ - yywarn(s); - exit(1); -} diff -ur --new-file old/atm/sigd.new/cfg.y new/atm/sigd.new/cfg.y --- old/atm/sigd.new/cfg.y Mon Oct 5 18:43:29 1998 +++ new/atm/sigd.new/cfg.y Thu Jan 1 01:00:00 1970 @@ -1,406 +0,0 @@ -%{ -/* cfg.y - configuration language */ - -/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ - - -#include -#include -#include - -#include "atm.h" -#include "atmd.h" - -#include "proto.h" -#include "io.h" -#include "trace.h" -#include "policy.h" - - -static RULE *rule; -static SIG_ENTITY *curr_sig = &_entity; - - -static int hex2num(char digit) -{ - if (isdigit(digit)) return digit-'0'; - if (islower(digit)) return toupper(digit)-'A'+10; - return digit-'A'+10; -} - - -static void put_address(char *address) -{ - char *mask; - - mask = strchr(address,'/'); - if (mask) *mask++ = 0; - if (text2atm(address,(struct sockaddr *) &rule->addr,sizeof(rule->addr), - T2A_SVC | T2A_WILDCARD | T2A_NAME | T2A_LOCAL) < 0) { - yyerror("invalid address"); - return; - } - if (!mask) rule->mask = -1; - else rule->mask = strtol(mask,NULL,10); - add_rule(rule); -} - -%} - -%union { - int num; - char *str; - struct sockaddr_atmpvc pvc; -}; - - -%token TOK_LEVEL TOK_DEBUG TOK_INFO TOK_WARN TOK_ERROR TOK_FATAL -%token TOK_SIG TOK_UNI30 TOK_UNI31 TOK_UNI40 TOK_Q2963_1 TOK_SAAL -%token TOK_VC TOK_IO TOK_MODE TOK_USER TOK_NET TOK_SWITCH TOK_VPCI -%token TOK_ITF TOK_PCR TOK_TRACE TOK_POLICY TOK_ALLOW TOK_REJECT -%token TOK_ENTITY TOK_DEFAULT -%token TOK_NUMBER -%token TOK_DUMP_DIR TOK_LOGFILE TOK_QOS TOK_FROM TOK_TO TOK_ROUTE -%token TOK_PVC - -%type level opt_trace_size action - -%% - -all: - global local - ; - -global: - | item global - ; - -local: - | entity local - { - if (!curr_sig->uni) - curr_sig->uni = -#if defined(UNI30) || defined(DYNAMIC_UNI) - S_UNI30 -#endif -#ifdef UNI31 - S_UNI31 -#endif -#ifdef ALLOW_UNI30 - S_UNI30 | S_UNI31 -#endif -#ifdef UNI40 - S_UNI40 -#ifdef Q2963_1 - | S_Q2963_1 -#endif -#endif - ; - } - ; - -item: - TOK_LEVEL level - { - set_verbosity(NULL,$2); - } - | TOK_SIG sig - | TOK_SAAL saal - | TOK_IO io - | TOK_DEBUG debug - | TOK_POLICY policy - ; - -entity: - TOK_ENTITY TOK_PVC - { - SIG_ENTITY *sig,**walk; - - if (atmpvc_addr_in_use(_entity.signaling_pvc)) - yyerror("can't use io vc and entity ... in the same " - "configuration"); - if (entities == &_entity) entities = NULL; - for (sig = entities; sig; sig = sig->next) - if (atm_equal((struct sockaddr *) &sig->signaling_pvc, - (struct sockaddr *) &$2,0,0)) - yyerror("duplicate PVC address %d.%d.%d",S_PVC(sig)); - curr_sig = alloc_t(SIG_ENTITY); - *curr_sig = _entity; - curr_sig->signaling_pvc = $2; - curr_sig->next = NULL; - for (walk = &entities; *walk; walk = &(*walk)->next); - *walk = curr_sig; - } - opt_options - ; - -opt_options: - | '{' options '}' - ; - -options: - | option options - ; - -option: - TOK_VPCI TOK_NUMBER TOK_ITF TOK_NUMBER - { - enter_vpci(curr_sig,$2,$4); - } - | TOK_MODE mode - | TOK_QOS - { - curr_sig->sig_qos = $1; - } - | TOK_ROUTE - { - struct sockaddr_atmsvc addr; - char *mask; - - mask = strchr($1,'/'); - if (mask) *mask++ = 0; - if (text2atm($1,(struct sockaddr *) &addr,sizeof(addr), - T2A_SVC | T2A_WILDCARD | T2A_NAME | T2A_LOCAL) < 0) { - yyerror("invalid address"); - return; - } - add_route(curr_sig,&addr,mask ? strtol(mask,NULL,10) : INT_MAX); - } - | TOK_DEFAULT - { - add_route(curr_sig,NULL,0); - } - ; - -sig: - sig_item - | '{' sig_items '}' - ; - -sig_items: - | sig_item sig_items - ; - -saal: - saal_item - | '{' saal_items '}' - ; - -saal_items: - | saal_item saal_items - ; - -io: - io_item - | '{' io_items '}' - ; - -io_items: - | io_item io_items - ; - -debug: - debug_item - | '{' debug_items '}' - ; - -debug_items: - | debug_item debug_items - ; - -policy: - policy_item - | '{' policy_items '}' - ; - -policy_items: - | policy_item policy_items - ; - -sig_item: - TOK_LEVEL level - { - set_verbosity("UNI",$2); - set_verbosity("KERNEL",$2); - set_verbosity("SAP",$2); - } - | TOK_VPCI TOK_NUMBER TOK_ITF TOK_NUMBER - { - enter_vpci(curr_sig,$2,$4); - } - | TOK_UNI30 - { -#if defined(UNI30) || defined(ALLOW_UNI30) || defined(DYNAMIC_UNI) - if (curr_sig->uni & ~S_UNI31) yyerror("UNI mode is already set"); - curr_sig->uni |= S_UNI30; -#else - yyerror("Sorry, not supported yet"); -#endif - } - | TOK_UNI31 - { -#if defined(UNI31) || defined(ALLOW_UNI30) || defined(DYNAMIC_UNI) - if (curr_sig->uni & ~S_UNI30) yyerror("UNI mode is already set"); - curr_sig->uni |= S_UNI31; -#else - yyerror("Sorry, not supported yet"); -#endif - } - | TOK_UNI40 - { -#if defined(UNI40) || defined(DYNAMIC_UNI) - if (curr_sig->uni) yyerror("UNI mode is already set"); - curr_sig->uni = S_UNI40; -#else - yyerror("Sorry, not supported yet"); -#endif - } - | TOK_Q2963_1 - { -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - if (!(curr_sig->uni & S_UNI40)) yyerror("Incompatible UNI mode"); - curr_sig->uni |= S_Q2963_1; -#else - yyerror("Sorry, not supported yet"); -#endif - } - | TOK_NET - { - yywarn("sig net is obsolete, please use sig mode net instead"); - curr_sig->mode = sm_net; - } - | TOK_MODE mode - ; - -saal_item: - TOK_LEVEL level - { - set_verbosity("SSCF",$2); - set_verbosity("SSCOP",$2); - } - ; - -io_item: - TOK_LEVEL level - { - set_verbosity("IO",$2); - } - | TOK_VC TOK_PVC - { - curr_sig->signaling_pvc = $2; - } - | TOK_PCR TOK_NUMBER - { - yywarn("io pcr is obsolete, please use io qos instead"); - curr_sig->sig_pcr = $2; - } - | TOK_QOS - { - curr_sig->sig_qos = $1; - } - ; - -debug_item: - TOK_LEVEL level - { - set_verbosity(NULL,$2); - } - | TOK_DUMP_DIR - { - dump_dir = $1; - if (!trace_size) trace_size = DEFAULT_TRACE_SIZE; - } - | TOK_LOGFILE - { - set_logfile($1); - } - | TOK_TRACE opt_trace_size - { - trace_size = $2; - } - ; - -opt_trace_size: - { - $$ = DEFAULT_TRACE_SIZE; - } - | TOK_NUMBER - { - $$ = $1; - } - ; - -level: - TOK_DEBUG - { - $$ = DIAG_DEBUG; - } - | TOK_INFO - { - $$ = DIAG_INFO; - } - | TOK_WARN - { - $$ = DIAG_WARN; - } - | TOK_ERROR - { - $$ = DIAG_ERROR; - } - | TOK_FATAL - { - $$ = DIAG_FATAL; - } - ; - -mode: - TOK_USER - { - curr_sig->mode = sm_user; - } - | TOK_NET - { - curr_sig->mode = sm_net; - } - | TOK_SWITCH - { - curr_sig->mode = sm_switch; - } - ; - -policy_item: - TOK_LEVEL level - { - set_verbosity("POLICY",$2); - } - | action - { - rule = alloc_t(RULE); - rule->type = $1; - } - direction - ; - -action: - TOK_ALLOW - { - $$ = ACL_ALLOW; - } - | TOK_REJECT - { - $$ = ACL_REJECT; - } - ; - -direction: - TOK_FROM - { - rule->type |= ACL_IN; - put_address($1); - } - | TOK_TO - { - rule->type |= ACL_OUT; - put_address($1); - } - ; diff -ur --new-file old/atm/sigd.new/io.c new/atm/sigd.new/io.c --- old/atm/sigd.new/io.c Wed Sep 23 19:45:35 1998 +++ new/atm/sigd.new/io.c Thu Jan 1 01:00:00 1970 @@ -1,379 +0,0 @@ -/* io.c - I/O operations */ - -/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* linux/atmsvc.h includes linux/atm.h */ -#include - -#include "atm.h" -#include "atmd.h" -#include "uni.h" -#include "pdu.h" - -#include "proto.h" -#include "io.h" -#include "trace.h" - - -#define COMPONENT "IO" - - -struct timeval now; - -int stop = 0; - -static int kernel = -1; -static int need_connect = 0; /* non-zero if connection to kernel isn't - bi-directional yet */ - - -/* ----- kernel interface -------------------------------------------------- */ - - -static int open_kernel(void) -{ - int s; - - if ((s = socket(PF_ATMSVC,SOCK_DGRAM,0)) < 0) { - perror("socket"); - return -1; - } - if (ioctl(s,ATMSIGD_CTRL,0) < 0) { - perror("ioctl ATMSIGD_CTRL"); - return -1; - } - return s; -} - - -void open_unix(const char *path) -{ - kernel = un_create(path,0600); - if (kernel < 0) - diag(COMPONENT,DIAG_FATAL,"un_create %s: %s",path,strerror(errno)); - need_connect = 1; -} - - -static void recv_kernel(void) -{ - static unsigned char buffer[sizeof(struct atmsvc_msg)+1]; - int size; - - if (!need_connect) size = read(kernel,buffer,sizeof(buffer)); - else { - size = un_recv_connect(kernel,buffer,sizeof(buffer)); - need_connect = 0; - } - if (size < 0) { - diag(COMPONENT,DIAG_ERROR,"read kernel: %s",strerror(errno)); - return; - } - if (size != sizeof(struct atmsvc_msg)) - diag(COMPONENT,DIAG_FATAL,"kernel message size %d != %d",size, - sizeof(struct atmsvc_msg)); - trace_kernel("FROM KERNEL",(struct atmsvc_msg *) buffer); - from_kernel((struct atmsvc_msg *) buffer,size); -} - - -void to_kernel(struct atmsvc_msg *msg) -{ - int wrote; - - diag("KERNEL",DIAG_DEBUG,"TO KERNEL: %s (%d) for 0x%lx/0x%lx", - as_name[msg->type],msg->reply,msg->vcc,msg->listen_vcc); - /* should be "IO" ... */ - trace_kernel("TO KERNEL",msg); - wrote = write(kernel,msg,sizeof(*msg)); - if (wrote == sizeof(*msg)) return; - if (wrote < 0) { - perror("kernel write"); - return; - } - diag(COMPONENT,DIAG_ERROR,"bad kernel write: wanted %d, wrote %d", - sizeof(*msg),wrote); -} - - -static void close_kernel(void) -{ - (void) close(kernel); /* may get major complaints from the kernel ... */ -} - - -/* ----- signaling interface ----------------------------------------------- */ - - -static int open_signaling(SIG_ENTITY *sig) -{ - struct atm_qos qos; - int s; - - if ((s = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) { - perror("socket"); - return -1; - } - memset(&qos,0,sizeof(qos)); - qos.aal = ATM_AAL5; - qos.rxtp.max_sdu = qos.txtp.max_sdu = MAX_Q_MSG; - if (sig->sig_qos) { - if (text2qos(sig->sig_qos,&qos,T2Q_DEFAULTS) < 0) { - fprintf(stderr,"invalid qos: %s\n",sig->sig_qos); - return -1; - } - } - else { - if (sig->sig_pcr == -1) - qos.rxtp.traffic_class = qos.txtp.traffic_class = ATM_UBR; - else { - qos.rxtp.traffic_class = qos.txtp.traffic_class = ATM_CBR; - qos.rxtp.min_pcr = qos.txtp.min_pcr = sig->sig_pcr; - } - } - if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { - perror("setsockopt SO_ATMQOS"); - return -1; - } - sig->signaling_pvc.sap_family = AF_ATMPVC; - if (bind(s,(struct sockaddr *) &sig->signaling_pvc, - sizeof(sig->signaling_pvc)) < 0) { - perror("bind"); - return -1; - } - return s; -} - - -static void recv_signaling(SIG_ENTITY *sig) -{ - static unsigned char buffer[MAX_Q_MSG]; - int size; - - size = read(sig->signaling,buffer,MAX_Q_MSG); - if (size < 1) { - perror("read signaling"); - return; - } - diag(COMPONENT,DIAG_DEBUG,"FROM NET (%d.%d.%d): %s PDU (%d bytes)", - S_PVC(sig),pdu_name[size > 3 && !(size & 3) ? buffer[size-4] & 0xf : 0], - size); - if (debug) diag_dump(COMPONENT,DIAG_DEBUG,NULL,buffer,size); - from_net(sig,buffer,size); -} - - -void to_net(SIG_ENTITY *sig,void *msg,int size) -{ - int wrote; - - diag(COMPONENT,DIAG_DEBUG,"TO NET (%d.%d.%d): %s PDU (%d bytes)",S_PVC(sig), - pdu_name[size > 3 && !(size & 3) ? ((unsigned char *) msg)[size-4] & 0xf - : 0],size); - if (debug) diag_dump(COMPONENT,DIAG_DEBUG,NULL,msg,size); - wrote = write(sig->signaling,msg,size); - if (wrote == size) return; - if (wrote < 0) { - perror("signaling write"); - return; - } - diag(COMPONENT,DIAG_WARN,"bad signaling write: wanted %d, wrote %d",size, - wrote); -} - - -static void close_signaling(SIG_ENTITY *sig) -{ - (void) close(sig->signaling); -} - - -/* ----- addresses --------------------------------------------------------- */ - - -LOCAL_ADDR local_addr[MAX_LOCAL_ADDRS+1]; - - -struct sockaddr_atmsvc *get_local(int itf) -{ - LOCAL_ADDR *local; - - for (local = local_addr; local->state != ls_unused; local++) - if (local->state == ls_same && atmsvc_addr_in_use(local->addr) && - (local->itf == itf || itf == ATM_ITF_ANY)) return &local->addr; - return NULL; -} - - -int get_addr(int itf) -{ - struct atmif_sioc req; - struct sockaddr_atmsvc buffer[MAX_LOCAL_ADDRS]; - LOCAL_ADDR *from,*to; - int addrs,i; - - for (from = to = local_addr; from->state != ls_unused; from++) - if (from->state != ls_removed) { - from->state = itf == from->itf ? ls_removed : ls_same; - *to++ = *from; - } - req.number = itf; - req.arg = buffer; - req.length = sizeof(buffer); - if (ioctl(entities->signaling,ATM_GETADDR,&req) < 0) - diag(COMPONENT,DIAG_FATAL,"ioctl ATM_GETADDR yields \"%s\"", - strerror(errno)); - addrs = req.length/sizeof(struct sockaddr_atmsvc); - for (i = 0; i < addrs; i++) { - for (from = local_addr; from->state != ls_unused; from++) - if (from->itf == itf && atm_equal((struct sockaddr *) (buffer+i), - (struct sockaddr *) &from->addr,0,0)) break; - if (from->state != ls_unused) from->state = ls_same; - else if (to == local_addr+MAX_LOCAL_ADDRS-1) - diag(COMPONENT,DIAG_WARN,"local address table overflow"); - else { - to->state = ls_added; - to->itf = itf; - to->addr = buffer[i]; - to++; - } - } - to->state = ls_unused; - return addrs; -} - - -/* ----- common part ------------------------------------------------------- */ - - -int open_all(void) -{ - SIG_ENTITY *sig,*purge; - - if (kernel == -1) kernel = open_kernel(); - if (kernel < 0) return -1; - for (sig = entities; sig; sig = sig->next) { - sig->signaling = open_signaling(sig); - if (sig->signaling < 0) { - for (purge = entities; purge != sig; purge = purge->next) - close_signaling(purge); - close_kernel(); - return -1; - } - } - local_addr[0].state = ls_unused; - return 0; -} - - -void close_all(void) -{ - SIG_ENTITY *sig; - - close_kernel(); - for (sig = entities;sig; sig = sig->next) close_signaling(sig); -} - - -void init_current_time(void) -{ - gettimeofday(&now,NULL); -} - - -void poll_loop(void) -{ - SIG_ENTITY *sig; - fd_set perm,set; - int fds,ret; - - FD_ZERO(&perm); - FD_SET(kernel,&perm); - fds = kernel+1; - for (sig = entities; sig; sig = sig->next) { - FD_SET(sig->signaling,&perm); - if (fds <= sig->signaling) fds = sig->signaling+1; - } - gettimeofday(&now,NULL); - while (!stop) { - set = perm; - poll_signals(); - /* - * Here we have a small race condition: if a signal is delivered after - * poll_signals tests for it but before select sleeps, we miss that - * signal. If it is sent again, we're of course likely to get it. This - * isn't worth fixing, because those signals are only used for - * debugging anyway. - */ - ret = select(fds,&set,NULL,NULL,next_timer()); - if (ret < 0) { - if (errno != EINTR) perror("select"); - } - else { - diag(COMPONENT,DIAG_DEBUG,"----------"); - gettimeofday(&now,NULL); - if (FD_ISSET(kernel,&set)) recv_kernel(); - for (sig = entities; sig; sig = sig->next) - if (FD_ISSET(sig->signaling,&set)) recv_signaling(sig); - expire_timers(); - /* expire timers after handling messges to make sure we don't - time out unnecessarily because of scheduling delays */ - } - } -} - - -/* - * The allocation strategy could be improved as follows: we should try - * vci = prev_vci++ first and only resort to ATM_VCI_ANY if that fails several - * times (and we should actually skip over those which are in use by SVCs. This - * way we avoid using VCIs that just became available. Doing it "right" seems - * to be getting complex, though. - */ - - -int get_pvc(int itf,int *vci) -{ - struct sockaddr_atmpvc addr; - struct atm_qos qos; - int s,error; - - if ((s = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) - diag(COMPONENT,DIAG_FATAL,"get_pvc: %s",strerror(errno)); - memset(&qos,0,sizeof(qos)); - qos.aal = ATM_AAL5; - qos.rxtp.traffic_class = qos.txtp.traffic_class = ATM_UBR; - qos.rxtp.max_sdu = qos.txtp.max_sdu = 1; /* smallest possible SDU size */ - if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) - diag(COMPONENT,DIAG_FATAL,"setsockopt SO_ATMQOS: %s",strerror(errno)); - memset(&addr,0,sizeof(addr)); - addr.sap_family = AF_ATMPVC; - addr.sap_addr.itf = itf; - addr.sap_addr.vpi = 0; /* @@@ */ - addr.sap_addr.vci = ATM_VCI_ANY; - error = 0; - if (bind(s,(struct sockaddr *) &addr,sizeof(addr)) < 0) error = errno; - else { - int size; - - size = sizeof(addr); - if (getsockname(s,(struct sockaddr *) &addr,&size) < 0) - diag(COMPONENT,DIAG_FATAL,"get_pvc: %s",strerror(errno)); - *vci = addr.sap_addr.vci; - return s; - } - (void) close(s); - return -error; -} diff -ur --new-file old/atm/sigd.new/io.h new/atm/sigd.new/io.h --- old/atm/sigd.new/io.h Thu Aug 20 19:50:44 1998 +++ new/atm/sigd.new/io.h Thu Jan 1 01:00:00 1970 @@ -1,43 +0,0 @@ -/* io.h - I/O operations */ - -/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ - - -#ifndef IO_H -#define IO_H - -#include -#include -#include - -#include "proto.h" - - -#define MAX_LOCAL_ADDRS 128 - - -typedef struct { - enum { ls_unused,ls_added,ls_removed,ls_same } state; - int itf; - struct sockaddr_atmsvc addr; -} LOCAL_ADDR; - - -extern LOCAL_ADDR local_addr[]; - - -int open_all(void); -void open_unix(const char *name); -void init_current_time(void); -void poll_loop(void); -void close_all(void); - -void to_kernel(struct atmsvc_msg *msg); -void to_net(SIG_ENTITY *sig,void *msg,int size); - -struct sockaddr_atmsvc *get_local(int itf); -int get_addr(int itf); - -int get_pvc(int itf,int *vci); - -#endif diff -ur --new-file old/atm/sigd.new/kernel.c new/atm/sigd.new/kernel.c --- old/atm/sigd.new/kernel.c Mon Oct 5 19:16:38 1998 +++ new/atm/sigd.new/kernel.c Thu Jan 1 01:00:00 1970 @@ -1,589 +0,0 @@ -/* kernel.c - Processing of incoming kernel messages */ - -/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ - - -#include -#include -#include -#include -#include /* linux/atmsvc.h includes linux/atm.h */ -#include -#include - -#include "atm.h" -#include "atmd.h" -#include "uni.h" -#include "qlib.h" -#include - -#include "proto.h" -#include "sap.h" -#include "io.h" -#include "policy.h" -#include "timeout.h" - - -#define COMPONENT "KERNEL" - - -static int send_setup(SOCKET *sock) -{ - static unsigned long call_ref = 0; - struct sockaddr_atmsvc *local; - SOCKET *walk; - Q_DSC dsc; - int error,size; - - do { - if (++call_ref == 0x7fffff) call_ref = 1; - for (walk = sockets; walk; walk = walk->next) - if (walk->call_ref == call_ref) break; - } - while (walk); - sock->call_ref = call_ref; - q_create(&dsc,q_buffer,MAX_Q_MSG); - local = NULL; - error = 0; - if (atmsvc_addr_in_use(sock->local)) local = &sock->local; - else { - sock->sig = route_call(&sock->remote); - if (!sock->sig) error = -EHOSTUNREACH; - else { - local = get_local(sock->sig->signaling_pvc.sap_addr.itf); - if (!local) local = get_local(ATM_ITF_ANY); - if (local) sock->local = *local; - else { - error = -EADDRNOTAVAIL; - diag(COMPONENT,DIAG_ERROR,"no local address"); - } - } - } - if (local) - if (*local->sas_addr.pub) { - q_assign(&dsc,QF_cgpn_plan,ATM_NP_E164); - q_assign(&dsc,QF_cgpn_type,ATM_TON_INTRNTNL); - q_write(&dsc,QF_cgpn,(void *) local->sas_addr.pub, - strlen(local->sas_addr.pub)); - } - else { - q_assign(&dsc,QF_cgpn_plan,ATM_NP_AEA); - q_assign(&dsc,QF_cgpn_type,ATM_TON_UNKNOWN); - q_write(&dsc,QF_cgpn,(void *) local->sas_addr.prv,ATM_ESA_LEN); - } - q_assign(&dsc,QF_call_ref,call_ref); - q_assign(&dsc,QF_msg_type,ATM_MSG_SETUP); - q_assign(&dsc,QF_aal_type,5); /* AAL 5 */ -#if defined(UNI30) || defined(DYNAMIC_UNI) - if (sock->sig->uni == S_UNI30) - q_assign(&dsc,QF_aal_mode,1); /* Message mode - LANE seems to really - want this */ -#endif - q_assign(&dsc,QF_sscs_type,0); /* unspecified - LANE wants this */ - if (!error) error = sap_encode(&dsc,&sock->remote,&sock->sap,&sock->qos); - q_assign(&dsc,QF_bearer_class,16); /* BCOB-X */ -#if defined(UNI30) || defined(ALLOW_UNI30) || defined(DYNAMIC_UNI) - if (sock->sig->uni & S_UNI30) - q_assign(&dsc,QF_trans_cap,ATM_TC_VBR_NRT_R00); - /* force presence - UNI 3.0 wants this */ -#endif - q_assign(&dsc,QF_upcc,0); /* p2p */ -#if !defined(UNI30) || defined(DYNAMIC_UNI) - if (sock->sig->uni != S_UNI30) - q_assign(&dsc,QF_qos_cs,Q2931_CS_ITU); -#endif - q_assign(&dsc,QF_qos_fw,0); /* QOS 0 */ - q_assign(&dsc,QF_qos_bw,0); - if (sock->sig->mode != sm_user) { - if (!atmpvc_addr_in_use(sock->pvc)) { - int vpci,vci; - - if (sock->sig->mode == sm_switch) - diag(COMPONENT,DIAG_FATAL,"No CI allocator (use -A)"); - vpci = 0; - sock->pvc.sap_addr.itf = get_itf(sock->sig,&vpci); - sock->pvc.sap_addr.vpi = vpci; - vci = get_vci(sock->pvc.sap_addr.itf); - if (vci < 0) { - (void) q_close(&dsc); - return vci; - } - sock->pvc.sap_addr.vci = vci; - } - q_assign(&dsc,QF_vpi,sock->pvc.sap_addr.vpi); - q_assign(&dsc,QF_vci,sock->pvc.sap_addr.vci); - } - if ((size = q_close(&dsc)) < 0) error = -EINVAL; - else if (!error) to_signaling(sock->sig,q_buffer,size); - return error; -} - - -static int send_connect(SOCKET *sock) -{ - Q_DSC dsc; - int size; - - q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_msg_type,ATM_MSG_CONNECT); - q_assign(&dsc,QF_call_ref,sock->call_ref); - if (sock->ep_ref >= 0) q_assign(&dsc,QF_ep_ref,sock->ep_ref); - if (sock->ep_ref <= 0) { /* no AAL parameters if ep_ref present and != 0 */ - q_assign(&dsc,QF_aal_type,5); -#if defined(UNI30) || defined(DYNAMIC_UNI) - if (sock->sig->uni == S_UNI30) - q_assign(&dsc,QF_aal_mode,1); /* Message mode - LANE seems to - really want this */ -#endif - q_assign(&dsc,QF_sscs_type,0); /* unspecified - LANE wants this */ - q_assign(&dsc,QF_fw_max_sdu,sock->qos.rxtp.max_sdu); - q_assign(&dsc,QF_bw_max_sdu,sock->qos.txtp.max_sdu); - } - if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); - return 0; -} - - -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - -static void send_modify_request(SOCKET *sock) -{ - Q_DSC dsc; - int size; - - q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_msg_type,ATM_MSG_MODIFY_REQ); - q_assign(&dsc,QF_call_ref,sock->call_ref); - if (sock->new_qos.txtp.traffic_class) - q_assign(&dsc,QF_fw_pcr_01,SELECT_TOP_PCR(sock->new_qos.txtp)); - if (sock->new_qos.rxtp.traffic_class) - q_assign(&dsc,QF_bw_pcr_01,SELECT_TOP_PCR(sock->new_qos.rxtp)); - if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); -} - - -static void send_modify_ack(SOCKET *sock) -{ - Q_DSC dsc; - int size; - - q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_msg_type,ATM_MSG_MODIFY_ACK); - q_assign(&dsc,QF_call_ref,sock->call_ref); - if (sock->qos.rxtp.traffic_class != ATM_NONE && - sock->qos.rxtp.max_pcr < sock->new_qos.rxtp.max_pcr) { - q_assign(&dsc,QF_type_of_report,ATM_TOR_MOD_CONF); - START_TIMER(sock,T361); - } - if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); -} - -#endif - - -static void dispatch(SOCKET *sock,struct atmsvc_msg *msg) -{ - int error; - - switch (msg->type) { - case as_bind: /* only in NULL state */ - if (sock) break; - if (msg->svc.sas_family != AF_ATMSVC) { - SEND_ERROR(msg->vcc,-EAFNOSUPPORT); - return; - } - if (!atmsvc_addr_in_use(msg->svc)) -#ifdef BE_PICKY_ABOUT_BINDING_LOCAL_WILDCARD_ADDRESSES - if (local_addr[0].state != ls_same) - SEND_ERROR(msg->vcc,-EADDRNOTAVAIL); - else -#endif - send_kernel(msg->vcc,0,as_okay,0,NULL,NULL, - &local_addr[0].addr,NULL,NULL); - else { - LOCAL_ADDR *walk; - - for (walk = local_addr; walk->state != ls_unused; walk++) - if (walk->state == ls_same && - atm_equal((struct sockaddr *) &walk->addr, - (struct sockaddr *) &msg->svc,(ATM_ESA_LEN-1)*8, - AXE_WILDCARD)) break; - if(*msg->svc.sas_addr.pub) - diag(COMPONENT,DIAG_DEBUG,"binding to E.164 address " - "%s\n",msg->svc.sas_addr.pub); - if (walk->state == ls_unused) { - SEND_ERROR(msg->vcc,-EADDRNOTAVAIL); - return; - } - sock->sig = get_sig_entity(walk->itf); - if (!sock->sig) { - diag(COMPONENT,DIAG_ERROR,"signaling entity lookup failed"); - SEND_ERROR(msg->vcc,-EADDRNOTAVAIL); - return; - } - send_kernel(msg->vcc,0,as_okay,0,NULL,NULL,NULL,NULL,NULL); - } - return; - case as_connect: /* NULL state only */ - if (sock) break; - if (!allow(&msg->svc,ACL_OUT)) { - SEND_ERROR(msg->vcc,-EACCES); - return; - } - sock = new_sock(msg->vcc); - sock->remote = msg->svc; - sock->qos = msg->qos; - sock->sap = msg->sap; - sock->state = ss_connecting; - sock->pvc = msg->pvc; - error = send_setup(sock); - if (error) { - SEND_ERROR(msg->vcc,error); - free_sock(sock); - return; - } - START_TIMER(sock,T303); - new_state(sock,ss_connecting); - return; - case as_accept: - if (sock->state == ss_zombie) { - SEND_ERROR(msg->vcc,-ECONNABORTED); /* -ERESTARTSYS ? */ - free_sock(sock); - return; - } - if (sock->state != ss_indicated && sock->state != ss_proceeding) - break; - if (sock->state == ss_indicated && sock->sig->mode != sm_user) - diag(COMPONENT,DIAG_FATAL,"No CI allocator (use -A)"); - error = send_connect(sock); - if (!error) { - START_TIMER(sock,T313); - new_state(sock,ss_accepting); - return; - } - SEND_ERROR(sock->id,error); - send_release(sock,0); /* @@@ */ - START_TIMER(sock,T308_1); - new_state(sock,ss_wait_rel); - return; - case as_reject: /* ZOMBIE, INDICATED, or PROCEEDING */ - switch (sock->state) { - case ss_indicated: - send_release_complete(sock->sig,sock->call_ref, - ATM_CV_CALL_REJ); - /* fall through */ - case ss_zombie: - free_sock(sock); - return; - case ss_proceeding: - send_release(sock,ATM_CV_CALL_REJ); - /* @@@ should use msg->reply */ - START_TIMER(sock,T308_1); - new_state(sock,ss_wait_rel); - return; - default: - break; - } - break; - case as_listen: /* NULL */ - if (sock) break; - if (msg->svc.sas_family != AF_ATMSVC) { - SEND_ERROR(msg->vcc,-EAFNOSUPPORT); - return; - } - if (msg->qos.aal != ATM_AAL5) { - SEND_ERROR(msg->vcc,-EINVAL); - return; - } - if (lookup_sap(&msg->svc,&msg->sap,&msg->qos,NULL,NULL,NULL,1)) { - SEND_ERROR(msg->vcc,-EADDRINUSE); - return; - } - sock = new_sock(msg->vcc); - sock->local = msg->svc; - sock->sap = msg->sap; - sock->qos = msg->qos; - send_kernel(sock->id,0,as_okay,0,NULL,NULL,NULL,NULL,NULL); - sock->state = ss_listening; - return; - case as_close: /* all but INDICATED, PROCEEDING, ZOMBIE, and WAIT_REL */ - if (sock && (sock->state == ss_indicated || - sock->state == ss_proceeding || sock->state == ss_zombie || - sock->state == ss_wait_rel)) break; - switch (sock ? sock->state : ss_null) { - case ss_listening: - send_close(sock); - if (sock->listen) new_state(sock,ss_listen_zombie); - else free_sock(sock); - return; - case ss_zombie: - send_close(sock); - /* fall through */ - case ss_wait_close: - free_sock(sock); - /* fall through */ - case ss_null: - case ss_rel_req: - return; - case ss_connecting: - case ss_accepting: -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - case ss_mod_req: -#endif - STOP_TIMER(sock); - /* fall through */ -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - case ss_mod_lcl: - case ss_mod_rcv: - case ss_mod_fin_ok: - case ss_mod_fin_fail: - case ss_mod_fin_ack: -#endif - case ss_connected: -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - if (timer_handler(sock->conn_timer) == on_T361) - STOP_TIMER(sock); -#endif - if (sock->state == ss_connected) - diag(COMPONENT,DIAG_INFO,"Active close (CR 0x%06X)", - sock->call_ref); - send_release(sock, -#ifdef DYNAMIC_UNI - sock->sig->uni != S_UNI30 ? ATM_CV_NORMAL_CLEAR : - ATM_CV_NORMAL_UNSPEC -#else -#if defined(UNI31) || defined(UNI40) - ATM_CV_NORMAL_CLEAR -#else - ATM_CV_NORMAL_UNSPEC -#endif -#endif - ); - START_TIMER(sock,T308_1); - new_state(sock,ss_rel_req); - return; - case ss_rel_ind: - send_release_complete(sock->sig,sock->call_ref,0); /* @@@ */ - free_sock(sock); - return; - default: - break; - } - break; - case as_identify: - if (sock->state != ss_indicated && sock->state != ss_proceeding) - break; - if (!atmpvc_addr_in_use(msg->pvc)) { - if (sock->sig->mode == sm_switch) - diag(COMPONENT,DIAG_FATAL,"No CI allocator (use -A)"); - return; - } - if (sock->sig->mode == sm_net) - diag(COMPONENT,DIAG_FATAL,"CI allocation role conflict"); - sock->pvc = msg->pvc; - if (send_call_proceeding(sock)) - diag(COMPONENT,DIAG_FATAL,"s_c_p failed"); - new_state(sock,ss_proceeding); - return; -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - case as_modify: - if (sock && !(sock->sig->uni & S_Q2963_1)) { - send_kernel(sock->id,0,as_okay,-ENOPROTOOPT,NULL,NULL,NULL, - NULL,NULL); - return; - } - if (sock && (sock->state == ss_mod_lcl || - sock->state == ss_mod_req || sock->state == ss_mod_rcv || - sock->state == ss_mod_fin_ok || sock->state == ss_mod_fin_fail || - sock->state == ss_mod_fin_ack)) { - send_kernel(sock->id,0,as_okay,-EALREADY,NULL,NULL,NULL,NULL, - NULL); - return; - } - if (!sock || sock->state != ss_connected || !sock->owner) { - send_kernel(sock->id,0,as_okay,-EBADFD,NULL,NULL,NULL,NULL, - NULL); - return; - } - if (sock->qos.txtp.traffic_class != msg->qos.txtp.traffic_class || - sock->qos.rxtp.traffic_class != msg->qos.rxtp.traffic_class) { - /* @@@ may do more checking */ - send_kernel(sock->id,0,as_okay,-EINVAL,NULL,NULL,NULL,NULL, - NULL); - return; - } - sock->new_qos = msg->qos; - send_kernel(sock->id,0,as_modify,ATM_MF_INC_RSV | ATM_MF_DEC_SHP, - NULL,NULL,NULL,NULL,&msg->qos); - new_state(sock,ss_mod_lcl); - return; - case as_okay: - switch (sock ? sock->state : ss_null) { - case ss_mod_lcl: - send_modify_request(sock); - START_TIMER(sock,T360); - new_state(sock,ss_mod_req); - return; - case ss_mod_rcv: - send_modify_ack(sock); - sock->qos = sock->new_qos; - new_state(sock,ss_connected); - return; - case ss_mod_fin_ok: - send_kernel(sock->id,0,as_okay,0,NULL,NULL,NULL,NULL,NULL); - new_state(sock,ss_connected); - return; - case ss_mod_fin_fail: - send_kernel(sock->id,0,as_okay,sock->error,NULL,NULL,NULL, - NULL,NULL); - sock->error = 0; - /* fall through */ - case ss_mod_fin_ack: - new_state(sock,ss_connected); - /* fall through */ - default: - return; /* ignore stray as_okay */ - } - case as_error: - switch (sock ? sock->state : ss_null) { - case ss_mod_lcl: - send_kernel(sock->id,0,as_okay,msg->reply,NULL,NULL,NULL, - NULL,NULL); - new_state(sock,ss_connected); - return; - case ss_mod_rcv: - send_modify_reject(sock,ATM_CV_RES_UNAVAIL); - new_state(sock,ss_connected); - return; - case ss_mod_fin_ok: - diag(COMPONENT,DIAG_ERROR,"QOS commit failed"); - send_kernel(sock->id,0,as_okay,0,NULL,NULL,NULL,NULL,NULL); - /* @@@ clear call instead ? */ - new_state(sock,ss_connected); - return; - case ss_mod_fin_fail: - diag(COMPONENT,DIAG_ERROR,"QOS rollback failed"); - send_kernel(sock->id,0,as_okay,sock->error,NULL,NULL,NULL, - NULL,NULL); - sock->error = 0; - /* @@@ clear call instead ? */ - new_state(sock,ss_connected); - return; - case ss_mod_fin_ack: - /* @@@ maybe we should even clear the call now */ - diag(COMPONENT,DIAG_ERROR,"QOS commit failed"); - new_state(sock,ss_connected); - return; - default: - return; /* ignore stray as_error */ - } -#endif - default: - diag(COMPONENT,DIAG_WARN,"invalid message %d",(int) msg->type); - return; - } - diag(COMPONENT,DIAG_WARN,"message %s is incompatible with state %s (%d)", - as_name[msg->type],state_name[sock ? sock->state : ss_null], - (int) (sock ? sock->state : ss_null)); -} - - -static void dispatch_listen(SOCKET *sock,struct atmsvc_msg *msg) -{ - SOCKET *next; - - if (!sock) { - diag(COMPONENT,DIAG_WARN,"message %s is incompatible with state %s " - "(%d)",as_name[msg->type],state_name[ss_null],ss_null); - return; - } - if (!(next = sock->listen)) { - diag(COMPONENT,DIAG_WARN, - "socket 0x%lx got accept/reject/identify with empty listen queue", - msg->vcc); - return; - } - sock->listen = next->listen; - if (sock->state == ss_listen_zombie && !sock->listen) free_sock(sock); - next->listen = NULL; - next->id = msg->vcc; - dispatch(next,msg); -} - - -void itf_load(int itf) -{ - char buf[MAX_ATM_ADDR_LEN+1]; - LOCAL_ADDR *walk; - - (void) get_addr(itf); - for (walk = local_addr; walk->state != ls_unused; walk++) - if (walk->itf == itf) { - if (atm2text(buf,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) - &walk->addr,pretty) < 0) strcpy(buf,""); - switch (walk->state) { - case ls_added: - diag(COMPONENT,DIAG_INFO,"Added local ATM address %s at " - "itf %d",buf,itf); - walk->state = ls_same; - break; - case ls_removed: - diag(COMPONENT,DIAG_INFO,"Removed local ATM address %s at " - "itf %d",buf,itf); - walk->state = ls_unused; -/* - * This is probably wrong. What if we delete an entry from the middle of - * the list ? @@@ - */ - /* @@@ delete SVCs using that address ? */ - break; - default: - break; - } - } -} - - -void from_kernel(struct atmsvc_msg *msg,int size) -{ - void (*dispatcher)(SOCKET *,struct atmsvc_msg *); - SOCKET *curr; - - if (msg->type == as_itf_notify) { - itf_load(msg->pvc.sap_addr.itf); - return; - } - if (msg->type == as_terminate) { -#if 0 /* need to pass some ID ... @@@ */ - if (mode != sm_switch) { - diag(COMPONENT,DIAG_ERROR,"Ignoring as_terminate received in %s " - "mode",mode == sm_user ? "USER" : "NETWORK"); - return; - } - clear_all_calls(sig); -#endif - stop = 1; - diag(COMPONENT,DIAG_INFO,"Going down on as_terminate"); - /* - * Fix this - we need to shut it down more gracefully. - */ - return; - } - if (msg->listen_vcc && (msg->type == as_accept || msg->type == as_reject || - msg->type == as_identify)) { - dispatcher = dispatch_listen; - for (curr = sockets; curr; curr = curr->next) - if (msg->listen_vcc == curr->id && (curr->state == ss_listening || - curr->state == ss_listen_zombie)) - break; - } - else { - dispatcher = dispatch; - for (curr = sockets; curr; curr = curr->next) - if (msg->vcc == curr->id) break; - } - diag(COMPONENT,DIAG_DEBUG,"FROM KERNEL: %s for socket %p (0x%lx/0x%lx) " - "in state %s",as_name[msg->type],curr,msg->vcc,msg->listen_vcc, - state_name[curr ? curr->state : ss_null]); - dispatcher(curr,msg); -} diff -ur --new-file old/atm/sigd.new/mkmess.pl new/atm/sigd.new/mkmess.pl --- old/atm/sigd.new/mkmess.pl Wed Jan 31 19:12:06 1996 +++ new/atm/sigd.new/mkmess.pl Thu Jan 1 01:00:00 1970 @@ -1,16 +0,0 @@ -#!/usr/bin/perl -while (<>) { - next if !/ATM_CV_/; - chop; - chop($_ = $_.<>) unless /\*\//; - s/\s+/ /g; - /ATM_CV_\S+\s+(\d+)\s+\/\*\s*(.*\S)\s*\*\//; - $map[$1] = $2; -} -print "/* THIS IS A MACHINE-GENERATED FILE. DO NOT EDIT ! */\n\n"; -print "const char *cause_text[] = {\n"; -for ($i = 0; $i < 128; $i++) { - print " \"".(defined $map[$i] ? $map[$i] : "unknown cause $i")."\"". - ($i == 127 ? "\n" : ",\n"); -} -print "};\n"; diff -ur --new-file old/atm/sigd.new/policy.c new/atm/sigd.new/policy.c --- old/atm/sigd.new/policy.c Thu Apr 9 14:51:34 1998 +++ new/atm/sigd.new/policy.c Thu Jan 1 01:00:00 1970 @@ -1,54 +0,0 @@ -/* policy.c - Access control policies */ - -/* Written 1997,1998 by Werner Almesberger, EPFL-LRC/ICA */ - - -#include -#include - -#include "proto.h" /* for "pretty" */ -#include "policy.h" - - -#define COMPONENT "POLICY" - - -static RULE *rules = NULL; -static RULE **next = &rules; - - -void add_rule(RULE *rule) -{ - rule->hits = 0; - rule->next = NULL; - *next = rule; - next = &rule->next; -} - - -int allow(const struct sockaddr_atmsvc *addr,int direction) -{ - RULE *rule; - char buffer[MAX_ATM_ADDR_LEN+1]; - int count; - - if ((direction & (ACL_IN | ACL_OUT)) == (ACL_IN | ACL_OUT)) - diag(COMPONENT,DIAG_ERROR,"allow: ACL_IN && ACL_OUT"); - count = 0; - for (rule = rules; rule; rule = rule->next) { - count++; - if (!(rule->type & direction)) continue; - if (!atm_equal((struct sockaddr *) addr, - (struct sockaddr *) &rule->addr,rule->mask,AXE_PRVOPT | - (rule->mask == -1 ? 0 : AXE_WILDCARD))) continue; - rule->hits++; - if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) addr, - pretty) < 0) - strcpy(buffer,""); - diag(COMPONENT,DIAG_DEBUG,"Rule %d: %s call %s %s",count, - rule->type & ACL_ALLOW ? "allowed" : "rejected", - direction & ACL_IN ? "from" : "to",buffer); - return rule->type & ACL_ALLOW; - } - return 1; -} diff -ur --new-file old/atm/sigd.new/policy.h new/atm/sigd.new/policy.h --- old/atm/sigd.new/policy.h Wed Oct 29 21:03:15 1997 +++ new/atm/sigd.new/policy.h Thu Jan 1 01:00:00 1970 @@ -1,27 +0,0 @@ -/* policy.h - Access control policies */ - -/* Written 1997 by Werner Almesberger, EPFL-LRC */ - - -#ifndef POLICY_H -#define POLICY_H - -#define ACL_ALLOW 1 -#define ACL_REJECT 2 -#define ACL_IN 4 -#define ACL_OUT 8 - - -typedef struct _rule { - int type; - struct sockaddr_atmsvc addr; - int mask; /* -1 for none */ - int hits; - struct _rule *next; -} RULE; - - -void add_rule(RULE *rule); -int allow(const struct sockaddr_atmsvc *addr,int direction); - -#endif diff -ur --new-file old/atm/sigd.new/proto.c new/atm/sigd.new/proto.c --- old/atm/sigd.new/proto.c Fri Aug 21 00:04:03 1998 +++ new/atm/sigd.new/proto.c Thu Jan 1 01:00:00 1970 @@ -1,437 +0,0 @@ -/* proto.c - Common protocol functions and structures */ - -/* Written 1995-1998 by Werner Almesberger, EPFL-LRC */ - - -#include -#include -#include -#include -#include - -#include "atmd.h" -#include "uni.h" -#include "qlib.h" -#include - -#include "io.h" -#include "proto.h" -#include "sap.h" - - -#define COMPONENT "SIGD" - - -const char *state_name[] = { /* formatting aligned with STATE */ - "", "ss_null", "ss_listening", "ss_connecting", - "ss_connected", "ss_indicated", "ss_accepting", "ss_zombie", - "ss_wait_rel", "ss_wait_close","ss_rel_req", "ss_rel_ind", - "ss_proceeding","ss_listen_zombie", - "ss_mod_lcl", "ss_mod_req", "ss_mod_rcv", "ss_mod_fin_ack", - "ss_mod_fin_ok","ss_mod_fin_fail" - }; - -const char *cs_name[] = { - "NULL", "CALL_INIT", "", "OUT_PROC", - "", "", "CALL_PRES", "", - "CONN_REQ", "IN_PROC", "ACTIVE", "REL_REQ", - "REL_IND", "MOD_REQ", "MOD_RCV" }; - -const char *as_name[] = { "","as_bind","as_connect","as_accept", - "as_reject","as_listen","as_okay","as_error","as_indicate","as_close", - "as_itf_notify","as_modify","as_identify","as_terminate" }; - -const CALL_STATE state_map[] = { /* formatting aligned with STATE */ - cs_null, cs_null, cs_null, cs_call_init, - cs_active, cs_in_proc, cs_conn_req, cs_null, - cs_rel_req, cs_null, cs_rel_req, cs_rel_ind, - cs_in_proc, cs_null, -#ifdef Q2963_1 - cs_active, cs_mod_req, cs_mod_rcv, cs_active, - cs_active, cs_active -#endif - }; - -const PARTY_STATE eps_map[] = { - ps_null, ps_add_init, ps_null, ps_add_init, /* 0 */ - ps_null, ps_null, ps_add_recv, ps_null, /* 4 */ - ps_active, ps_add_recv, ps_active, ps_active, /* 8 */ - ps_active }; /*12 */ - - -SIG_ENTITY *entities = &_entity; -SOCKET *sockets = NULL; -unsigned char q_buffer[MAX_Q_MSG]; - - -SOCKET *new_sock(unsigned long id) -{ - SOCKET *sock; - - sock = alloc_t(SOCKET); - sock->sig = NULL; - sock->state = ss_invalid; - memset(&sock->pvc,0,sizeof(sock->pvc)); - sock->qos.txtp.traffic_class = sock->qos.rxtp.traffic_class = ATM_UBR; - sock->id = id; - memset(&sock->local,0,sizeof(sock->local)); - memset(&sock->remote,0,sizeof(sock->remote)); - memset(&sock->sap,0,sizeof(sock->sap)); - sock->error = 0; - sock->call_state = cs_null; - sock->ep_ref = -1; - sock->conn_timer = NULL; - sock->listen = NULL; - sock->next = sockets; - sockets = sock; - return sock; -} - - -void free_sock(SOCKET *sock) -{ - SOCKET **walk; - - diag(COMPONENT,DIAG_DEBUG,"freeing socket 0x%lx@%p",sock->id,sock); - for (walk = &sockets; *walk != sock; walk = &(*walk)->next); - if (!*walk) - diag(COMPONENT,DIAG_FATAL, - "INTERNAL ERROR: freeing non-existing socket 0x%lx",sock->id); - *walk = sock->next; - if (sock->conn_timer) { - diag(COMPONENT,DIAG_ERROR,"socket 0x%lx has timer (%p) running", - sock->id,sock->conn_timer->callback); - stop_timer(sock->conn_timer); - } - if (sock->listen) - diag(COMPONENT,DIAG_ERROR,"socket 0x%lx has non-empty listen queue", - sock->id); - sock->state = ss_invalid; - free(sock); -} - - -void new_state(SOCKET *sock,STATE state) -{ - diag(COMPONENT,DIAG_DEBUG,"socket 0x%lx enters state %s (UNI %s)", - sock->id,state_name[state],cs_name[state_map[state]]); - sock->state = state; - sock->call_state = state_map[state]; -} - - -SOCKET *lookup_sap(const struct sockaddr_atmsvc *addr, - const struct atm_sap *sap,const struct atm_qos *qos, - struct sockaddr_atmsvc *res_addr,struct atm_sap *res_sap, - struct atm_qos *res_qos,int exact_match) -{ - SOCKET *walk,*wildcard; - int new_wc; - - new_wc = !atmsvc_addr_in_use(*addr); - wildcard = NULL; - for (walk = sockets; walk; walk = walk->next) - if (walk->state == ss_listening && sap_compat(&walk->local, - addr,res_addr,&walk->sap,sap,res_sap,&walk->qos,qos,res_qos)) - if (atmsvc_addr_in_use(walk->local)) return walk; - else if (exact_match) { - if (new_wc) return walk; - } - else wildcard = walk; - return wildcard; -} - - -const char *mid2name(unsigned char mid) -{ - switch (mid) { - case ATM_MSG_NATIONAL: - return "National specific message escape"; - case ATM_MSG_SETUP: - return "SETUP"; - case ATM_MSG_ALERTING: - return "ALERTING"; - case ATM_MSG_CALL_PROC: - return "CALL_PROCEEDING"; - case ATM_MSG_CONNECT: - return "CONNECT"; - case ATM_MSG_CONN_ACK: - return "CONNECT_ACK"; - case ATM_MSG_RESTART: - return "RESTART"; - case ATM_MSG_RELEASE: - return "RELEASE"; - case ATM_MSG_REST_ACK: - return "REST_ACK"; - case ATM_MSG_REL_COMP: - return "REL_COMP"; - case ATM_MSG_NOTIFY: - return "NOTIFY"; - case ATM_MSG_STATUS_ENQ: - return "STATUS_ENQ"; - case ATM_MSG_STATUS: - return "STATUS"; - case ATM_MSG_ADD_PARTY: - return "ADD_PARTY"; - case ATM_MSG_ADD_PARTY_ACK: - return "ADD_PARTY_ACK"; - case ATM_MSG_ADD_PARTY_REJ: - return "ADD_PARTY_REJECT"; - case ATM_MSG_PARTY_ALERT: - return "PARTY_ALERTING"; - case ATM_MSG_DROP_PARTY: - return "DROP_PARTY"; - case ATM_MSG_DROP_PARTY_ACK: - return "DROP_PARTY_ACK"; - case ATM_MSG_MODIFY_REQ: - return "MODIFY_REQUEST"; - case ATM_MSG_MODIFY_ACK: - return "MODIFY_ACK"; - case ATM_MSG_MODIFY_REJ: - return "MODIFY_REJECT"; - case ATM_MSG_CONN_AVAIL: - return "CONN_AVAIL"; - case ATM_MSG_LEAF_FAILURE: - return "LEAF SETUP FAIL"; - case ATM_MSG_LEAF_REQUEST: - return "LEAF SETUP REQ"; - case ATM_MSG_RESERVED: - return "Reserved..."; - default: - return "???"; - } -} - - -void send_kernel(unsigned long vcc,unsigned long listen_vcc, - enum atmsvc_msg_type type,int reply,const struct sockaddr_atmpvc *pvc, - const struct sockaddr_atmsvc *svc,const struct sockaddr_atmsvc *local, - const struct atm_sap *sap,const struct atm_qos *qos) -{ - struct atmsvc_msg *msg; - - msg = alloc_t(struct atmsvc_msg); - msg->vcc = vcc; - msg->listen_vcc = listen_vcc; - msg->type = type; - msg->reply = reply; - if (pvc) msg->pvc = *pvc; - else memset(&msg->pvc,0,sizeof(msg->pvc)); - if (sap) msg->sap = *sap; - else memset(&msg->sap,0,sizeof(msg->sap)); - if (qos) msg->qos = *qos; - else memset(&msg->qos,0,sizeof(msg->qos)); - if (local) msg->local = *local; - else memset(&msg->local,0,sizeof(msg->local)); - if (svc) msg->svc = *svc; - else memset(&msg->svc,0,sizeof(msg->svc)); - to_kernel(msg); - free(msg); -} - - -void send_release(SOCKET *sock,unsigned char reason,...) -{ - va_list ap; - Q_DSC dsc; - int size; - - q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_msg_type,ATM_MSG_RELEASE); - q_assign(&dsc,QF_call_ref,sock->call_ref); - q_assign(&dsc,QF_cause,reason); - va_start(ap,reason); - switch (reason) { - case ATM_CV_TIMER_EXP: - { - char buf[4]; - - sprintf(buf,"%d",va_arg(ap,int)); - q_write(&dsc,QF_timer,buf,3); - break; - } - default: - } - va_end(ap); - if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); -} - - -void send_release_complete(SIG_ENTITY *sig,unsigned long call_ref, - unsigned char cause) -{ - Q_DSC dsc; - int size; - - q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_msg_type,ATM_MSG_REL_COMP); - q_assign(&dsc,QF_call_ref,call_ref); - if (cause) q_assign(&dsc,QF_cause,cause); /* @@@ more data */ - if ((size = q_close(&dsc)) >= 0) to_signaling(sig,q_buffer,size); -} - - -void send_modify_reject(SOCKET *sock,unsigned char reason) -{ - Q_DSC dsc; - int size; - - q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_msg_type,ATM_MSG_MODIFY_REJ); - q_assign(&dsc,QF_call_ref,sock->call_ref); - q_assign(&dsc,QF_cause,reason); - if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); -} - - -void set_error(SOCKET *sock,int code) -{ - if (!sock->error) sock->error = code; -} - - -void send_close(SOCKET *sock) -{ - if (sock->error == 1234) diag(COMPONENT,DIAG_FATAL,"BUG! BUG! BUG!"); - send_kernel(sock->id,0L,as_close,sock->error,NULL,NULL,NULL,NULL,NULL); - sock->error = 1234; -} - - -void q_report(int severity,const char *msg,...) -{ - va_list ap; - - va_start(ap,msg); - vdiag("QMSG",severity,msg,ap); - va_end(ap); -} - - -int get_vci(int itf) -{ - SOCKET *walk; - int s,vci; - - s = get_pvc(itf,&vci); - if (s < 0) return s; - for (walk = sockets; walk; walk = walk->next) - if (walk->pvc.sap_addr.itf == itf && walk->pvc.sap_addr.vci == vci) { - vci = get_vci(itf); /* this recursion will keep all the busy ones - open until we return */ - break; - } - (void) close(s); - return vci; -} - - -void enter_vpci(SIG_ENTITY *sig,int vpci,int itf) -{ - VPCI *entry; - - for (entry = sig->vpcis; entry; entry = entry->next) - if (entry->vpci == vpci) { - diag(COMPONENT,DIAG_ERROR,"ignoring duplicate VPCI %d (itf %d)", - vpci,itf); - return; - } - entry = alloc_t(VPCI); - entry->vpci = vpci; - entry->itf = itf; - entry->next = sig->vpcis; - sig->vpcis = entry; -} - - -int get_itf(SIG_ENTITY *sig,int *vpci) -{ - VPCI *best,*walk; - - best = NULL; - for (walk = sig->vpcis; walk; walk = walk->next) - if (walk->vpci <= *vpci && (!best || best->vpci < walk->vpci)) - best = walk; - if (!best) return sig->signaling_pvc.sap_addr.itf; - *vpci -= best->vpci; - return best->itf; -} - - -void init_addr(SIG_ENTITY *sig) -{ - VPCI *walk; - - itf_load(sig->signaling_pvc.sap_addr.itf); - for (walk = sig->vpcis; walk; walk = walk->next) itf_load(walk->itf); -} - - -/* - * The following code is stolen from switch/route.c. Eventually, all this - * should move into a library. - */ - - -#include - - -typedef struct _route { - struct sockaddr_atmsvc addr; - int len; - SIG_ENTITY *sig; - struct _route *next; -} ROUTE; - - -static ROUTE *routes = NULL; - - -void add_route(SIG_ENTITY *sig,struct sockaddr_atmsvc *addr,int len) -{ - ROUTE *route; - - for (route = routes; route; route = route->next) - if (route->len == len && (!len || atm_equal((struct sockaddr *) addr, - (struct sockaddr *) &route->addr,len, - AXE_PRVOPT | (len == INT_MAX ? 0 : AXE_WILDCARD)))) - diag(COMPONENT,DIAG_FATAL,"duplicate route"); - route = alloc_t(ROUTE); - if (addr) route->addr = *addr; - route->len = len; - route->sig = sig; - route->next = routes; - routes = route; -} - - -SIG_ENTITY *route_call(struct sockaddr_atmsvc *addr) -{ - ROUTE *best,*route; - int best_len; - - if (!routes) return entities; - best = NULL; - best_len = -1; - for (route = routes; route; route = route->next) - if (route->len > best_len && (!route->len || - atm_equal((struct sockaddr *) addr,(struct sockaddr *) &route->addr, - route->len, - AXE_PRVOPT | (route->len == INT_MAX ? 0 : AXE_WILDCARD)))) { - if (route->len == INT_MAX) return route->sig; - best_len = route->len; - best = route; - } - return best ? best->sig : NULL; -} - - -SIG_ENTITY *get_sig_entity(int itf) -{ - SIG_ENTITY *sig; - - for (sig = entities; sig; sig = sig->next) - if (sig->signaling_pvc.sap_addr.itf == itf) return sig; - /* should also check for vpcis @@@ */ - return NULL; -} diff -ur --new-file old/atm/sigd.new/proto.h new/atm/sigd.new/proto.h --- old/atm/sigd.new/proto.h Mon Oct 5 18:28:59 1998 +++ new/atm/sigd.new/proto.h Thu Jan 1 01:00:00 1970 @@ -1,170 +0,0 @@ -/* proto.h - Common protocol functions and structures */ - -/* Written 1995-1998 by Werner Almesberger, EPFL-LRC */ - - -#ifndef PROTO_H -#define PROTO_H - -#include -#include - -#include "atmsap.h" -#include "atmd.h" -#include "saal.h" - - -typedef enum { /* formatting aligned with state_map and others */ - ss_invalid, ss_null, ss_listening, ss_connecting, - ss_connected, ss_indicated, ss_accepting, ss_zombie, - ss_wait_rel, ss_wait_close, ss_rel_req, ss_rel_ind, - ss_proceeding, ss_listen_zombie, -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - ss_mod_lcl, ss_mod_req, ss_mod_rcv, ss_mod_fin_ack, - ss_mod_fin_ok, ss_mod_fin_fail -#endif -} STATE; - -typedef enum { cs_null,cs_call_init,cs_out_proc = 3,cs_conn_req = 8, - cs_in_proc,cs_active,cs_rel_req,cs_rel_ind, -#if defined(Q2963_1) || defined (DYNAMIC_UNI) - cs_mod_req,cs_mod_rcv -#endif - } CALL_STATE; - -typedef enum { ps_null,ps_add_init,ps_add_recv = 6,ps_drop_init = 11, - ps_drop_recv,ps_active = 10 } PARTY_STATE; - -#define S_UNI30 1 -#define S_UNI31 2 -#define S_UNI40 4 -#define S_Q2963_1 8 - -typedef enum { sm_unknown,sm_user,sm_net,sm_switch } SIGNALING_MODE; - -typedef struct _vpci { - int vpci; - int itf; - struct _vpci *next; -} VPCI; - -typedef struct _sig_entity { - int signaling; /* fd */ - int uni; - SIGNALING_MODE mode; - int sig_pcr; /* @@@ remove soon */ - const char *sig_qos; - struct sockaddr_atmpvc signaling_pvc; - SAAL_DSC saal; - VPCI *vpcis; - struct _sig_entity *next; -} SIG_ENTITY; - -typedef struct _socket { - STATE state; - SIG_ENTITY *sig; - struct sockaddr_atmpvc pvc; - /* --- socket layer information ---------------------------------------- */ - unsigned long id; - struct sockaddr_atmsvc local; /* local address */ - struct sockaddr_atmsvc remote; /* remote address */ - struct atm_sap sap; /* SAP (BHLI and BLLI) */ - struct atm_qos qos; /* QOS parameters */ -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - struct atm_qos new_qos; /* during modification */ - int owner; /* non-zero if connection owner */ -#endif - int error; /* error code for close */ - /* --- UNI information ------------------------------------------------- */ - CALL_STATE call_state; - unsigned long call_ref; /* bit 24 like when sending */ - short ep_ref; /* endpoint reference; -1 for p2p */ - TIMER *conn_timer; /* current connection timer */ - /* --- some meta-information ------------------------------------------- */ - struct _socket *listen; /* to pending connections, also used for "more" */ - struct _socket *next; /* next socket */ -} SOCKET; - -extern SOCKET *sockets; - -/* - * SOCKET uses a horrible linked list structure. Lists should be at least - * doubly-linked and there should be a few hashes (by id and by call_ref) for - * reasonable fast lookup. All this will have to wait till that version is - * stable enough to be useful to test the "real" thing against it. - */ - -#define S_PVC(e) \ - (e)->signaling_pvc.sap_addr.itf, \ - (e)->signaling_pvc.sap_addr.vpi, \ - (e)->signaling_pvc.sap_addr.vci - -extern SIG_ENTITY *entities; -extern SIG_ENTITY _entity; - -extern const CALL_STATE state_map[]; -extern const PARTY_STATE eps_map[]; -extern const char *state_name[],*cs_name[],*as_name[]; - -extern unsigned char q_buffer[]; - -#define DEFAULT_TRACE_SIZE 20 - -extern int pretty; -extern const char *dump_dir; - -extern int stop; - - -#define SEND_ERROR(vcc,code) \ - send_kernel(vcc,0L,as_error,code,NULL,NULL,NULL,NULL,NULL) - - -void poll_signals(void); - -void from_kernel(struct atmsvc_msg *msg,int size); -void itf_load(int itf); - -void to_uni(SIG_ENTITY *sig,void *msg,int size); -void send_kernel(unsigned long vcc,unsigned long listen_vcc, - enum atmsvc_msg_type type,int reply,const struct sockaddr_atmpvc *pvc, - const struct sockaddr_atmsvc *svc,const struct sockaddr_atmsvc *local, - const struct atm_sap *sap,const struct atm_qos *qos); -void from_net(SIG_ENTITY *sig,void *msg,int size); -void to_signaling(SIG_ENTITY *sig,void *msg,int size); -void saal_failure(SIG_ENTITY *sig); -void saal_okay(SIG_ENTITY *sig); -void clear_all_calls(SIG_ENTITY *sig); -void clear_all_calls_on_T309(SIG_ENTITY *sig); - -SOCKET *new_sock(unsigned long id); -void free_sock(SOCKET *sock); -void new_state(SOCKET *sock,STATE state); -SOCKET *lookup_sap(const struct sockaddr_atmsvc *addr, - const struct atm_sap *sap,const struct atm_qos *qos, - struct sockaddr_atmsvc *res_addr,struct atm_sap *res_sap, - struct atm_qos *res_qos,int exact_match); - -void send_release(SOCKET *sock,unsigned char reason,...); -void send_release_complete(SIG_ENTITY *sig,unsigned long call_ref, - unsigned char cause); -int send_call_proceeding(SOCKET *sock); -void send_modify_reject(SOCKET *sock,unsigned char reason); - -const char *mid2name(unsigned char mid); - -void set_error(SOCKET *sock,int code); -void send_close(SOCKET *sock); - -int get_vci(int itf); - -void enter_vpci(SIG_ENTITY *sig,int vpci,int itf); -int get_itf(SIG_ENTITY *sig,int *vpci); -void init_addr(SIG_ENTITY *sig); - -void add_route(SIG_ENTITY *sig,struct sockaddr_atmsvc *addr,int len); -SIG_ENTITY *route_call(struct sockaddr_atmsvc *addr); - -SIG_ENTITY *get_sig_entity(int itf); - -#endif diff -ur --new-file old/atm/sigd.new/sap.c new/atm/sigd.new/sap.c --- old/atm/sigd.new/sap.c Mon Oct 5 18:27:42 1998 +++ new/atm/sigd.new/sap.c Thu Jan 1 01:00:00 1970 @@ -1,341 +0,0 @@ -/* sap.c - SAP manipulations */ - -/* Written 1996-1998 by Werner Almesberger, EPFL-LRC/ICA */ - - -#include -#include -#include -#include -#include /* sigh, again */ -#include - -#include "atm.h" -#include "atmd.h" -#include "uni.h" -#include "qlib.h" -#include - -#include "common.h" -#include "sap.h" - - -#define COMPONENT "SAP" - - -static int class_compat(const struct atm_trafprm *tx, - const struct atm_trafprm *rx) -{ - if (tx->traffic_class == ATM_NONE || tx->traffic_class == ATM_ANYCLASS) - return 1; - if (rx->traffic_class == ATM_UBR || rx->traffic_class == ATM_ANYCLASS) - return 1; - /* don't apply CAC to PCR */ - if (tx->traffic_class != rx->traffic_class) return 0; - /* ignore special cases like CBR to VBR for now */ - switch (tx->traffic_class) { - case ATM_CBR: - if (!rx->max_pcr || rx->max_pcr == ATM_MAX_PCR) return 1; - return tx->min_pcr <= rx->max_pcr; - /* Actually, we shouldn't look at min_pcr, because there's no - bandwidth negotiation anyway. */ - default: - diag(COMPONENT,DIAG_ERROR,"unsupported traffic class %d\n", - tx->traffic_class); - return 0; - } -} - - -int sap_compat(const struct sockaddr_atmsvc *old_addr, - const struct sockaddr_atmsvc *new_addr,struct sockaddr_atmsvc *res_addr, - const struct atm_sap *old_sap,const struct atm_sap *new_sap, - struct atm_sap *res_sap,const struct atm_qos *old_qos, - const struct atm_qos *new_qos,struct atm_qos *res_qos) -{ - if (atmsvc_addr_in_use(*old_addr) && - !atm_equal((struct sockaddr *) old_addr,(struct sockaddr *) new_addr,0,0)) - return 0; - if (res_qos) *res_qos = *new_qos; - if (old_qos->txtp.max_sdu && new_qos->rxtp.max_sdu && - old_qos->txtp.max_sdu > new_qos->rxtp.max_sdu) return 0; - if (new_qos->txtp.max_sdu && old_qos->rxtp.max_sdu && - new_qos->txtp.max_sdu > old_qos->rxtp.max_sdu) return 0; - if (!class_compat(&old_qos->txtp,&new_qos->rxtp) || - !class_compat(&new_qos->txtp,&old_qos->rxtp)) return 0; - if (!sap_equal(old_sap,new_sap, - SXE_COMPATIBLE | SXE_NEGOTIATION | (res_sap ? SXE_RESULT : 0),res_sap)) - return 0; - return 1; -} - - -static int encode_blli(Q_DSC *dsc,const struct atm_blli *blli) -{ - if (blli->l2_proto != ATM_L2_NONE) { - q_assign(dsc,QF_uil2_proto,blli->l2_proto); - switch (blli->l2_proto) { - case ATM_L2_X25_LL: - case ATM_L2_X25_ML: - case ATM_L2_HDLC_ARM: - case ATM_L2_HDLC_NRM: - case ATM_L2_HDLC_ABM: - case ATM_L2_Q922: - case ATM_L2_ISO7776: - if (blli->l2.itu.mode != ATM_IMD_NONE) - q_assign(dsc,QF_l2_mode,blli->l2.itu.mode); - if (blli->l2.itu.window) - q_assign(dsc,QF_window_size,blli->l2.itu.window); - break; - case ATM_L2_USER: - q_assign(dsc,QF_user_l2,blli->l2.user); - break; - default: - break; - } - } - if (blli->l3_proto != ATM_L3_NONE) { - q_assign(dsc,QF_uil3_proto,blli->l3_proto); - switch (blli->l3_proto) { - case ATM_L3_X25: - case ATM_L3_ISO8208: - case ATM_L3_X223: - if (blli->l3.itu.mode != ATM_IMD_NONE) - q_assign(dsc,QF_l3_mode,blli->l3.itu.mode); - if (blli->l3.itu.def_size) - q_assign(dsc,QF_def_pck_size,blli->l3.itu.def_size); - if (blli->l3.itu.window) - q_assign(dsc,QF_pck_win_size,blli->l3.itu.window); - break; - case ATM_L3_TR9577: - q_assign(dsc,QF_ipi_high,blli->l3.tr9577.ipi >> 1); - q_assign(dsc,QF_ipi_low,blli->l3.tr9577.ipi & 1); - if (blli->l3.tr9577.ipi == NLPID_IEEE802_1_SNAP) { - q_write(dsc,QF_oui,blli->l3.tr9577.snap,3); - q_write(dsc,QF_pid,blli->l3.tr9577.snap+3,2); - } - break; - case ATM_L3_USER: - q_assign(dsc,QF_user_l3,blli->l3.user); - break; - default: - diag(COMPONENT,DIAG_ERROR,"bad l3_proto (%d)", - blli->l3_proto); - return -EINVAL; - } - } - return 0; -} - - -int sap_encode(Q_DSC *dsc,const struct sockaddr_atmsvc *addr, - const struct atm_sap *sap,const struct atm_qos *qos) -{ - int error,pcr; - - if (*addr->sas_addr.pub) - q_write(dsc,QF_cdpn_e164,(void *) addr->sas_addr.pub, - strlen(addr->sas_addr.pub)); - else if (*addr->sas_addr.prv) - q_write(dsc,QF_cdpn_esa,(void *) addr->sas_addr.prv,ATM_ESA_LEN); - else return -EDESTADDRREQ; - if (qos->txtp.traffic_class == ATM_UBR || qos->rxtp.traffic_class == - ATM_UBR) q_assign(dsc,QF_best_effort,0); -#if defined(UNI40) || defined(DYNAMIC_UNI) - if (qos->txtp.traffic_class == ATM_CBR || qos->rxtp.traffic_class == - ATM_CBR) q_assign(dsc,QF_trans_cap,ATM_TC_CBR); -#endif - switch (qos->txtp.traffic_class) { - case ATM_NONE: - q_assign(dsc,QF_fw_pcr_01,0); - break; - case ATM_UBR: - /* fall through */ - case ATM_CBR: - /* here's a bit of policy: send the highest value we have */ - pcr = SELECT_TOP_PCR(qos->txtp); - diag(COMPONENT,DIAG_DEBUG,"fwd %d (%d..%d)",pcr, - qos->txtp.min_pcr,qos->txtp.max_pcr); - if (pcr == ATM_MAX_PCR) pcr = ATM_OC3_PCR; - q_assign(dsc,QF_fw_pcr_01,pcr); - break; - default: - diag(COMPONENT,DIAG_ERROR,"bad TX class (%d)", - qos->txtp.traffic_class); - return -EINVAL; - } - switch (qos->rxtp.traffic_class) { - case ATM_NONE: - q_assign(dsc,QF_bw_pcr_01,0); - break; - case ATM_UBR: - /* fall through */ - case ATM_CBR: - pcr = SELECT_TOP_PCR(qos->rxtp); - diag(COMPONENT,DIAG_DEBUG,"bwd %d (%d..%d)",pcr, - qos->rxtp.min_pcr,qos->rxtp.max_pcr); - if (pcr == ATM_MAX_PCR) pcr = ATM_OC3_PCR; - q_assign(dsc,QF_bw_pcr_01,pcr); - break; - default: - diag(COMPONENT,DIAG_ERROR,"bad RX class (%d)", - qos->rxtp.traffic_class); - return -EINVAL; - } - if (qos->txtp.max_sdu) q_assign(dsc,QF_fw_max_sdu,qos->txtp.max_sdu); - if (qos->rxtp.max_sdu) q_assign(dsc,QF_bw_max_sdu,qos->rxtp.max_sdu); - /* @@@ bearer class ? */ - /* @@@ QOS class ? */ - if (sap->bhli.hl_type != ATM_HL_NONE) { - q_assign(dsc,QF_hli_type,sap->bhli.hl_type-1); - switch (sap->bhli.hl_type) { - case ATM_HL_ISO: - q_write(dsc,QF_iso_hli,sap->bhli.hl_info,sap->bhli.hl_length); - break; - case ATM_HL_USER: - q_write(dsc,QF_user_hli,sap->bhli.hl_info,sap->bhli.hl_length); - break; -#if defined(UNI30) || defined(DYNAMIC_UNI) -/* @@@ fail this if UNI != 3.0 */ - case ATM_HL_HLP: - q_write(dsc,QF_hlp,sap->bhli.hl_info,4); - break; -#endif - case ATM_HL_VENDOR: - q_write(dsc,QF_hli_oui,sap->bhli.hl_info,3); - q_write(dsc,QF_app_id, sap->bhli.hl_info+3,4); - break; - default: - diag(COMPONENT,DIAG_ERROR,"bad hl_type (%d)", - sap->bhli.hl_type); - return -EINVAL; - } - } - if (!blli_in_use(sap->blli[0])) return 0; - q_instance(dsc,QG_blli1); - error = encode_blli(dsc,sap->blli); - if (error) return 0; - if (!blli_in_use(sap->blli[1])) return 0; - q_instance(dsc,QG_blli2); - error = encode_blli(dsc,sap->blli+1); - if (error) return 0; - if (!blli_in_use(sap->blli[2])) return 1; - q_instance(dsc,QG_blli3); - return encode_blli(dsc,sap->blli+2); -} - - -static void decode_blli(Q_DSC *dsc,struct atm_blli *blli) -{ -#define GET(var,field) \ - ({ if (q_present(dsc,field)) blli->var = q_fetch(dsc,field); }) - - if (q_present(dsc,QF_uil2_proto)) { - blli->l2_proto = q_fetch(dsc,QF_uil2_proto); - GET(l2.itu.mode,QF_l2_mode); - GET(l2.itu.window,QF_window_size); - GET(l2.user,QF_user_l2); - } - if (q_present(dsc,QF_uil3_proto)) { - blli->l3_proto = q_fetch(dsc,QF_uil3_proto); - GET(l3.itu.mode,QF_l3_mode); - GET(l3.itu.def_size,QF_def_pck_size); - GET(l3.itu.window,QF_pck_win_size); - GET(l3.user,QF_user_l3); - if (q_present(dsc,QF_ipi_high)) { - blli->l3.tr9577.ipi = q_fetch(dsc,QF_ipi_high) << 1; - if (blli->l3.tr9577.ipi != NLPID_IEEE802_1_SNAP) - blli->l3.tr9577.ipi |= q_fetch(dsc,QF_ipi_low); - else if (!q_present(dsc,QF_oui)) blli->l3.tr9577.ipi |= 1; - else { - q_read(dsc,QF_oui,blli->l3.tr9577.snap,3); - q_read(dsc,QF_pid,blli->l3.tr9577.snap+3,2); - } - } - } -#undef GET -} - - -void sap_decode(Q_DSC *dsc,struct sockaddr_atmsvc *addr,struct atm_sap *sap, - struct atm_qos *qos) -{ - memset(addr,0,sizeof(*addr)); - memset(sap,0,sizeof(*sap)); - memset(qos,0,sizeof(*qos)); - addr->sas_family = AF_ATMSVC; - if (q_present(dsc,QF_cdpn_e164)) - (void) q_read(dsc,QF_cdpn_e164,(void *) &addr->sas_addr.pub, - ATM_E164_LEN); - else if (q_present(dsc,QF_cdpn_esa)) - (void) q_read(dsc,QF_cdpn_esa,(void *) &addr->sas_addr.prv, - ATM_ESA_LEN); - if (q_present(dsc,QF_aal_type)) - if (q_fetch(dsc,QF_aal_type) != 5) - diag(COMPONENT,DIAG_ERROR,"AAL type %d requested", - q_fetch(dsc,QF_aal_type)); - if (q_present(dsc,QF_best_effort)) { - qos->txtp.traffic_class = qos->rxtp.traffic_class = ATM_UBR; - diag(COMPONENT,DIAG_DEBUG,"UBR"); - } - else { - qos->txtp.traffic_class = qos->rxtp.traffic_class = ATM_CBR; - diag(COMPONENT,DIAG_DEBUG,"CBR"); - } - qos->txtp.max_pcr = qos->rxtp.max_pcr = 0; - /* unbalanced decoding - always sets upper bound */ - if (q_present(dsc,QF_fw_pcr_01)) { - qos->rxtp.min_pcr = 0; - qos->rxtp.max_pcr = q_fetch(dsc,QF_fw_pcr_01); - } - if (q_present(dsc,QF_bw_pcr_01)) { - qos->txtp.min_pcr = 0; - qos->txtp.max_pcr = q_fetch(dsc,QF_bw_pcr_01); - } - if (!qos->txtp.max_pcr) qos->txtp.traffic_class = ATM_NONE; - if (!qos->rxtp.max_pcr) qos->rxtp.traffic_class = ATM_NONE; - diag(COMPONENT,DIAG_DEBUG,"fwd %d..%d bwd %d..%d", - qos->rxtp.min_pcr,qos->rxtp.max_pcr,qos->txtp.min_pcr, - qos->txtp.max_pcr); - /* SHOULD ... fail call if anything is missing ... @@@ */ - if (q_present(dsc,QF_bw_max_sdu)) - qos->txtp.max_sdu = q_fetch(dsc,QF_bw_max_sdu); - if (q_present(dsc,QF_fw_max_sdu)) - qos->rxtp.max_sdu = q_fetch(dsc,QF_fw_max_sdu); - if (q_present(dsc,QG_bhli)) { - sap->bhli.hl_type = q_fetch(dsc,QF_hli_type)+1; - switch (sap->bhli.hl_type) { - case ATM_HL_ISO: - sap->bhli.hl_length = q_length(dsc,QF_iso_hli); - q_read(dsc,QF_iso_hli,sap->bhli.hl_info,sap->bhli.hl_length); - break; - case ATM_HL_USER: - sap->bhli.hl_length = q_length(dsc,QF_user_hli); - q_read(dsc,QF_user_hli,sap->bhli.hl_info,sap->bhli.hl_length); - break; -#if defined(UNI30) || defined(DYNAMIC_UNI) -/* @@@ fail this is UNI != 3.0 */ - case ATM_HL_HLP: - sap->bhli.hl_length = 4; - q_read(dsc,QF_hlp,sap->bhli.hl_info,4); - break; -#endif - case ATM_HL_VENDOR: - sap->bhli.hl_length = 7; - q_read(dsc,QF_hli_oui,sap->bhli.hl_info,3); - q_read(dsc,QF_app_id,sap->bhli.hl_info+3,4); - break; - default: - diag(COMPONENT,DIAG_FATAL,"unrecognized hl_type"); - } - } - if (!q_present(dsc,QG_blli1)) return; - q_instance(dsc,QG_blli1); - decode_blli(dsc,sap->blli); - if (!q_present(dsc,QG_blli2)) return; - q_instance(dsc,QG_blli2); - decode_blli(dsc,sap->blli+1); - if (!q_present(dsc,QG_blli3)) return; - q_instance(dsc,QG_blli3); - decode_blli(dsc,sap->blli+2); -} diff -ur --new-file old/atm/sigd.new/sap.h new/atm/sigd.new/sap.h --- old/atm/sigd.new/sap.h Wed Nov 5 00:23:04 1997 +++ new/atm/sigd.new/sap.h Thu Jan 1 01:00:00 1970 @@ -1,24 +0,0 @@ -/* sap.h - SAP manipulations */ - -/* Written 1996,1997 by Werner Almesberger, EPFL-LRC */ - - -#ifndef SAP_H -#define SAP_H - -#include - -#include "atmsap.h" - - -int sap_compat(const struct sockaddr_atmsvc *old_addr, - const struct sockaddr_atmsvc *new_addr,struct sockaddr_atmsvc *res_addr, - const struct atm_sap *old_sap,const struct atm_sap *new_sap, - struct atm_sap *res_sap,const struct atm_qos *old_qos, - const struct atm_qos *new_qos,struct atm_qos *res_qos); -int sap_encode(Q_DSC *dsc,const struct sockaddr_atmsvc *addr, - const struct atm_sap *sap,const struct atm_qos *qos); -void sap_decode(Q_DSC *dsc,struct sockaddr_atmsvc *addr,struct atm_sap *sap, - struct atm_qos *qos); - -#endif diff -ur --new-file old/atm/sigd.new/timeout.c new/atm/sigd.new/timeout.c --- old/atm/sigd.new/timeout.c Mon Oct 5 19:00:15 1998 +++ new/atm/sigd.new/timeout.c Thu Jan 1 01:00:00 1970 @@ -1,120 +0,0 @@ -/* timeout.c - Processing of signaling timeout events */ - -/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ - - -#include -#include -#include -#include - -#include "atmd.h" - -#include "uni.h" -#include "proto.h" -#include "timeout.h" - - -#define COMPONENT "UNI" - - -static void complain(SOCKET *sock,const char *timer) -{ - diag(COMPONENT,DIAG_FATAL,"Timer %s expired in incompatible state %s", - timer,state_name[sock->state]); -} - - -void on_T303(void *user) /* CONNECTING */ -{ - SOCKET *sock = user; - - diag(COMPONENT,DIAG_DEBUG,"T303 on 0x%lx",sock->id); - if (sock->state != ss_connecting) complain(sock,"T303"); - SEND_ERROR(sock->id,-ETIMEDOUT); - sock->conn_timer = NULL; - free_sock(sock); -} - - -void on_T308_1(void *user) /* WAIT_REL or REL_REQ */ -{ - SOCKET *sock = user; - - diag(COMPONENT,DIAG_DEBUG,"T308_1 on 0x%lx",sock->id); - if (sock->state != ss_wait_rel && sock->state != ss_rel_req) - complain(sock,"T308_1"); - send_release(sock,ATM_CV_TIMER_EXP,308); /* @@@ ? */ - sock->conn_timer = NULL; - START_TIMER(sock,T308_2); -} - - -void on_T308_2(void *user) /* WAIT_REL or REL_REQ */ -{ - SOCKET *sock = user; - - diag(COMPONENT,DIAG_WARN,"Trouble: T308_2 has expired"); - if (sock->state != ss_wait_rel && sock->state != ss_rel_req) - complain(sock,"T308_2"); - sock->conn_timer = NULL; - if (sock->state == ss_rel_req) send_close(sock); - free_sock(sock); -} - - -void on_T309(void *user) -{ - diag(COMPONENT,DIAG_DEBUG,"T309 has expired"); - clear_all_calls_on_T309(user); -} - - -void on_T310(void *user) -{ - on_T303(user); - diag(COMPONENT,DIAG_DEBUG,"(it's actually T310)"); -} - - -void on_T313(void *user) /* ACCEPTING */ -{ - SOCKET *sock = user; - - diag(COMPONENT,DIAG_DEBUG,"T313 on 0x%lx",sock->id); - if (sock->state != ss_accepting) complain(sock,"T313"); - send_release(sock,ATM_CV_TIMER_EXP,313); - sock->conn_timer = NULL; - START_TIMER(sock,T308_1); - new_state(sock,ss_rel_req); -} - - -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - -void on_T360(void *user) -{ - SOCKET *sock = user; - - diag(COMPONENT,DIAG_DEBUG,"T360 on 0x%lx",sock->id); - if (sock->state != ss_mod_req) complain(sock,"T360"); - send_release(sock,ATM_CV_TIMER_EXP,360); - sock->conn_timer = NULL; - START_TIMER(sock,T308_1); - new_state(sock,ss_rel_req); -} - - -void on_T361(void *user) -{ - SOCKET *sock = user; - - diag(COMPONENT,DIAG_DEBUG,"T361 on 0x%lx",sock->id); - if (sock->state != ss_connected) complain(sock,"T361"); - sock->qos = sock->new_qos; - send_kernel(sock->id,0,as_modify,ATM_MF_SET,NULL,NULL,NULL,NULL,&sock->qos); - sock->conn_timer = NULL; - new_state(sock,ss_mod_fin_ack); -} - -#endif diff -ur --new-file old/atm/sigd.new/timeout.h new/atm/sigd.new/timeout.h --- old/atm/sigd.new/timeout.h Mon Oct 20 17:05:28 1997 +++ new/atm/sigd.new/timeout.h Thu Jan 1 01:00:00 1970 @@ -1,34 +0,0 @@ -/* timeout.h - Processing of signaling timeout events */ - -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ - - -#ifndef TIMEOUT_H -#define TIMEOUT_H - -#define T303_TIME 4000000 /* 4 sec */ -#define T308_1_TIME 30000000 /* 30 sec */ -#define T308_2_TIME 30000000 /* 30 sec */ -#define T309_TIME 10000000 /* 10 sec */ -#define T310_TIME 10000000 /* 10 sec */ -#define T313_TIME 4000000 /* 4 sec */ - -#define T360_TIME 30000000 /* 30 sec */ -#define T361_TIME 20000000 /* 20 sec */ - - -#define START_TIMER(u,t) { assert(!u->conn_timer); \ - u->conn_timer = start_timer(t##_TIME,on_##t,u); } -#define STOP_TIMER(u) { stop_timer(u->conn_timer); u->conn_timer = NULL; } - - -void on_T303(void *user); -void on_T308_1(void *user); -void on_T308_2(void *user); -void on_T309(void *user); -void on_T310(void *user); -void on_T313(void *user); -void on_T360(void *user); -void on_T361(void *user); - -#endif diff -ur --new-file old/atm/sigd.new/trace.c new/atm/sigd.new/trace.c --- old/atm/sigd.new/trace.c Mon Oct 5 09:59:36 1998 +++ new/atm/sigd.new/trace.c Thu Jan 1 01:00:00 1970 @@ -1,293 +0,0 @@ -/* trace.c - Support functions for message tracing */ - -/* Written 1996-1998 by Werner Almesberger, EPFL-LRC/ICA */ - - -#include -#include -#include -#include -#include -#include -#include /* linux/atmsvc.h includes linux/atm.h */ -#include - -#include "atm.h" -#include "atmd.h" -#include "atmsap.h" -#include "trace.h" -#include "proto.h" - - -#define DUMP_MODE -#include "qlib.h" - - -typedef struct _entry { - int number; - struct timeval time; - void (*print)(void *msg,int size); - const char *comment; - struct sockaddr_atmpvc pvc; /* unused if !sap_family */ - void *msg; - int size; - struct _entry *next; -} ENTRY; - - -int trace_size = 0; - -static struct sockaddr_atmpvc null_pvc; -static int current_size = 0; -static int sequence = 0; -static ENTRY *first = NULL,*last = NULL; -static char *string = NULL; -static int curr_len; -static int new_line; - - -static inline void append_chunk(const char *str,int len) -{ - if (!string) curr_len = 0; - if (!(string = realloc(string,curr_len+len+1))) { - perror("realloc"); - exit(1); - } - memcpy(string+curr_len,str,len); - curr_len += len; - string[curr_len] = 0; -} - - -static void vappend(const char *fmt,va_list ap) -{ - const char *walk,*next; - - for (walk = next = fmt; *walk; walk++) - if (*walk == '%') { - if (walk != next) append_chunk(next,walk-next); - if (*++walk == 's') { - const char *str; - - str = va_arg(ap,const char *); - append_chunk(str,strlen(str)); - } - else { - char buf[21]; /* big enough for 64 bits */ - int num; - - while (isdigit(*walk) || *walk == 'l') walk++; /* @@@ FIXME */ - if (*walk != 'd' && *walk != 'x') { - fprintf(stderr,"bad format character %c (%d)\n",*walk, - *walk); - exit(1); - } - num = va_arg(ap,int); - sprintf(buf,*walk == 'd' ? "%d" : "%x",num); - append_chunk(buf,strlen(buf)); - } - next = walk+1; - } - if (walk != next) append_chunk(next,walk-next); -} - - -static void append(const char *fmt,...) -{ - va_list ap; - - va_start(ap,fmt); - vappend(fmt,ap); - va_end(ap); -} - - -static void print_text(void *msg,int size) -{ - append(" %s\n",msg); -} - - -static void append_svc(const struct sockaddr_atmsvc *svc) -{ - char buffer[MAX_ATM_ADDR_LEN+1]; - - if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) svc, - A2T_NAME | A2T_LOCAL | A2T_PRETTY) < 0) strcpy(buffer,""); - append("%s\n",buffer); -} - - -static void append_sap(const struct atm_sap *sap) -{ - char buffer[MAX_ATM_SAP_LEN+1]; - - if (sap2text(buffer,MAX_ATM_SAP_LEN+1,sap,S2T_NAME | S2T_LOCAL) < 0) - strcpy(buffer,""); - append("%s\n",buffer); -} - - -static void append_qos(const struct atm_qos *qos) -{ - char buffer[MAX_ATM_QOS_LEN+1]; - - if (qos2text(buffer,MAX_ATM_QOS_LEN+1,qos,0) < 0) - strcpy(buffer,""); - append("%s\n",buffer); -} - - -static void qd_vdump(const char *msg,va_list ap) -{ - if (new_line) append(" "); - vappend(msg,ap); - if (string && curr_len) new_line = string[curr_len-1] == '\n'; - else new_line = 1; -} - - -void qd_dump(const char *msg,...) -{ - va_list ap; - - va_start(ap,msg); - qd_vdump(msg,ap); - va_end(ap); -} - - -void qd_report(int severity,const char *msg,...) -{ - va_list ap; - - if (severity > Q_ERROR) return; - va_start(ap,msg); - qd_vdump(msg,ap); - va_end(ap); - qd_dump("\n"); -} - - -static void print_uni(void *msg,int size) -{ - Q_DSC dsc; - - (void) qd_open(&dsc,msg,size); - qd_close(&dsc); -} - - -static void print_kernel(void *msg,int size) -{ - static const char *type[] = { "as_catch_null","as_bind","as_connect", - "as_accept","as_reject","as_listen","as_okay","as_error","as_indicate", - "as_close","as_itf_notify","as_modify","as_identify" }; - struct atmsvc_msg *m = msg; - - append(" %s (vcc 0x%x, listen_vcc 0x%x)\n",m->type < sizeof(type)/ - sizeof(*type) ? type[m->type] : "???",m->vcc,m->listen_vcc); - append(" reply %d",m->reply); - if (m->reply) { - const char *error; - - error = strerror(m->reply > 0 ? m->reply : -m->reply); - append(" (%s)",error ? error : "???"); - } - append(", aal %d\n",m->qos.aal); - append(" pvc %d.%d.%d\n",m->pvc.sap_addr.itf,m->pvc.sap_addr.vpi, - m->pvc.sap_addr.vci); - append(" local "); - append_svc(&m->local); - append(" qos "); - append_qos(&m->qos); - append(" svc "); - append_svc(&m->svc); - append(" sap "); - append_sap(&m->sap); -} - - -static void store(void (*print)(void *msg,int size),const char *comment, - const struct sockaddr_atmpvc *pvc,void *msg,int size) -{ - ENTRY *entry; - - entry = alloc_t(ENTRY); - (void) gettimeofday(&entry->time,NULL); - entry->number = sequence++; - entry->print = print; - entry->comment = comment; - entry->pvc = *pvc; - entry->msg = msg; - entry->size = size; - entry->next = NULL; - if (current_size < trace_size) current_size++; - else { /* handle trace_size < 1 (< 0) too */ - ENTRY *next; - - next = first->next; - free(first->msg); - free(first); - if (first == last) last = NULL; /* someone set trace_size < 2 */ - first = next; - } - if (last) last->next = entry; - else first = entry; - last = entry; -} - - -void trace_msg(const char *msg) -{ - char *buf; - - if (!trace_size) return; - buf = alloc(strlen(msg)+1); - strcpy(buf,msg); - store(&print_text,"MESSAGE",&null_pvc,buf,strlen(msg)); -} - - -void trace_uni(const char *comment,const SIG_ENTITY *sig,const void *msg, - int size) -{ - char *buf; - - if (!trace_size) return; - buf = alloc(size); - memcpy(buf,msg,size); - store(&print_uni,comment,&sig->signaling_pvc,buf,size); -} - - -void trace_kernel(const char *comment,const struct atmsvc_msg *msg) -{ - struct atmsvc_msg *buf; - - if (!trace_size) return; - buf = alloc_t(struct atmsvc_msg); - *buf = *msg; - store(&print_kernel,comment,&null_pvc,buf,sizeof(*msg)); -} - - -char *get_trace(void) -{ - ENTRY *walk; - - if (string) { - free(string); - string = NULL; - } - for (walk = first; walk; walk = walk->next) { - append("%6d (%d.%06d) %s",walk->number,walk->time.tv_sec, - walk->time.tv_usec,walk->comment); - if (!walk->pvc.sap_family) append(":\n"); - else append(" (%d.%d.%d):\n",walk->pvc.sap_addr.itf, - walk->pvc.sap_addr.vpi,walk->pvc.sap_addr.vci); - new_line = 1; - walk->print(walk->msg,walk->size); - } - return string; -} diff -ur --new-file old/atm/sigd.new/trace.h new/atm/sigd.new/trace.h --- old/atm/sigd.new/trace.h Thu Aug 20 18:06:41 1998 +++ new/atm/sigd.new/trace.h Thu Jan 1 01:00:00 1970 @@ -1,22 +0,0 @@ -/* trace.h - Support functions for message tracing */ - -/* Written 1996,1998 by Werner Almesberger, EPFL-LRC */ - - -#ifndef TRACE_H -#define TRACE_H - -#include - -#include "proto.h" - - -extern int trace_size; - -void trace_msg(const char *msg); -void trace_uni(const char *comment,const SIG_ENTITY *sig,const void *msg, - int size); -void trace_kernel(const char *comment,const struct atmsvc_msg *msg); -char *get_trace(void); - -#endif diff -ur --new-file old/atm/sigd.new/uni.c new/atm/sigd.new/uni.c --- old/atm/sigd.new/uni.c Tue Oct 6 13:35:36 1998 +++ new/atm/sigd.new/uni.c Thu Jan 1 01:00:00 1970 @@ -1,799 +0,0 @@ -/* uni.c - Processing of incoming UNI signaling messages */ - -/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ - - -#include -#include -#include -#include -#include -#include -#include - -#include "atm.h" -#include "atmd.h" -#include "uni.h" -#include "qlib.h" -#include - -#include "proto.h" -#include "sap.h" -#include "io.h" -#include "policy.h" -#include "timeout.h" -#include "trace.h" - - -#define COMPONENT "UNI" - - -extern const char *cause_text[]; /* from mess.c */ - - -static Q_DSC in_dsc; -static TIMER *t309 = NULL; - - -int send_call_proceeding(SOCKET *sock) -{ - Q_DSC dsc; - int size; - - q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_msg_type,ATM_MSG_CALL_PROC); - q_assign(&dsc,QF_call_ref,sock->call_ref); - if (sock->sig->mode == sm_net) { - int vpci,vci; - - sock->pvc.sap_family = AF_ATMPVC; - vpci = sock->sig->signaling_pvc.sap_addr.itf; - sock->pvc.sap_addr.itf = get_itf(sock->sig,&vpci); - sock->pvc.sap_addr.vpi = vpci; - vci = get_vci(sock->pvc.sap_addr.itf); - if (vci < 0) { - (void) q_close(&dsc); - return vci; - } - sock->pvc.sap_addr.vci = vci; - } - if (sock->sig->mode != sm_user) { - q_assign(&dsc,QF_vpi,sock->pvc.sap_addr.vpi); - q_assign(&dsc,QF_vci,sock->pvc.sap_addr.vci); - } - if (sock->ep_ref >= 0) q_assign(&dsc,QF_ep_ref,sock->ep_ref); - if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); - return 0; -} - - -static void setup_call(SIG_ENTITY *sig,unsigned long call_ref) -{ - SOCKET *sock,*this,**walk; - struct sockaddr_atmsvc in_addr; - struct atm_sap in_sap; - struct atm_qos in_qos; - int i; - - sap_decode(&in_dsc,&in_addr,&in_sap,&in_qos); - if (!atmsvc_addr_in_use(in_addr)) { - send_release_complete(sig,call_ref,ATM_CV_UNALLOC); - return; - } - if (!allow(&in_addr,ACL_IN)) { - send_release_complete(sig,call_ref,ATM_CV_REJ_CLIR); - return; - } - this = new_sock(0); - this->sig = sig; - sock = lookup_sap(&in_addr,&in_sap,&in_qos,&this->local,&this->sap, - &this->qos,0); - if (!sock) { - free_sock(this); - send_release_complete(sig,call_ref,ATM_CV_INCOMP_DEST); - return; - } - this->qos.aal = ATM_AAL5; /* hack @@@ */ - this->state = sig->mode == sm_net ? ss_proceeding : ss_indicated; - this->call_state = cs_in_proc; - this->call_ref = call_ref; - if (q_present(&in_dsc,QF_ep_ref)) - this->ep_ref = q_fetch(&in_dsc,QF_ep_ref); -#ifdef CISCO - else -#endif - if (sig->mode == sm_net) { - int error; - - error = send_call_proceeding(this); - if (error) { - free_sock(this); - send_release_complete(sig,call_ref,ATM_CV_NO_CI); - return; - } - } - /* if (sock->local) *this->local->sas_addr = sock->local->sas_addr; ??? */ - diag(COMPONENT,DIAG_DEBUG,"AAL type %ld",q_fetch(&in_dsc,QF_aal_type)); - if (sig->mode == sm_user) { /* already set by send_call_proceeding */ - int vpci; - - vpci = q_fetch(&in_dsc,QF_vpi); - this->pvc.sap_family = AF_ATMPVC; - this->pvc.sap_addr.itf = get_itf(sig,&vpci); - this->pvc.sap_addr.vpi = vpci; - this->pvc.sap_addr.vci = q_fetch(&in_dsc,QF_vci); - } - diag(COMPONENT,DIAG_DEBUG,"ITF.VPI.VCI: %d.%d.%d",this->pvc.sap_addr.itf, - this->pvc.sap_addr.vpi,this->pvc.sap_addr.vci); - if (q_present(&in_dsc,QF_cgpn)) { /* should handle E.164 too */ - char buffer[MAX_ATM_ADDR_LEN+1]; - int plan; - - plan = q_fetch(&in_dsc,QF_cgpn_plan); - switch (plan) { - case ATM_NP_AEA: - i = q_read(&in_dsc,QF_cgpn,(void *) this->remote.sas_addr.prv, - ATM_ESA_LEN); - break; - case ATM_NP_E164: - i = q_read(&in_dsc,QF_cgpn,(void *) this->remote.sas_addr.pub, - ATM_E164_LEN); - break; - default: - diag(COMPONENT,DIAG_WARN,"Ignoring cgpn with unrecognized " - "numbering plan 0x%x\n",plan); - i = 0; - } - if (i) { - this->remote.sas_family = AF_ATMSVC; - if (atm2text(buffer,MAX_ATM_ADDR_LEN+1, - (struct sockaddr *) &this->remote,pretty) < 0) - strcpy(buffer,""); - diag(COMPONENT,DIAG_DEBUG,"Incoming call from %s",buffer); - } - } - send_kernel(0,sock->id,as_indicate,0,&this->pvc,&this->remote,&in_addr, - &this->sap,&this->qos); - for (walk = &sock->listen; *walk; walk = &(*walk)->listen); - *walk = this; - diag(COMPONENT,DIAG_DEBUG,"SE vpi.vci=%d.%d",this->pvc.sap_addr.vpi, - this->pvc.sap_addr.vci); -} - - -static void send_status(SIG_ENTITY *sig,SOCKET *sock,unsigned long call_ref, - unsigned char cause,...) -{ - va_list ap; - Q_DSC dsc; - int size; - - q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_msg_type,ATM_MSG_STATUS); - if (sock) { - q_assign(&dsc,QF_call_ref,sock->call_ref); - q_assign(&dsc,QF_call_state,(int) sock->call_state); - if (sock->ep_ref >= 0) { - q_assign(&dsc,QF_ep_ref,sock->ep_ref); - q_assign(&dsc,QF_ep_state,eps_map[sock->call_state]); - } - } - else { - q_assign(&dsc,QF_call_ref,call_ref); - q_assign(&dsc,QF_call_state,0); /* U0 - Null / REST 0 - Null */ - } - q_assign(&dsc,QF_cause,cause); - va_start(ap,cause); - switch (cause) { - case ATM_CV_UNKNOWN_MSG_TYPE: - case ATM_CV_INCOMP_MSG: - q_assign(&dsc,QF_bad_msg_type,va_arg(ap,unsigned char)); - break; - case ATM_CV_MAND_IE_MISSING: - case ATM_CV_INVALID_IE: - { - unsigned char ie; - - ie = va_arg(ap,unsigned char); - q_write(&dsc,QF_ie_id6,&ie,1); - break; - } - default: - ; - } - va_end(ap); - if ((size = q_close(&dsc)) >= 0) to_signaling(sig,q_buffer,size); -} - - -static void send_status_enq(SOCKET *sock) -{ - Q_DSC dsc; - int size; - - q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_msg_type,ATM_MSG_STATUS_ENQ); - q_assign(&dsc,QF_call_ref,sock->call_ref); - if (sock->ep_ref >= 0) q_assign(&dsc,QF_ep_ref,sock->ep_ref); - if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); - /* @@@ should start T322 */ -} - - -static void send_connect_ack(SOCKET *sock) -{ - Q_DSC dsc; - int size; - - q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_msg_type,ATM_MSG_CONN_ACK); - q_assign(&dsc,QF_call_ref,sock->call_ref); - if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); -} - - -static void send_restart_ack(SIG_ENTITY *sig,int vpi,int vci) -{ - Q_DSC dsc; - int size; - - q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_msg_type,ATM_MSG_REST_ACK); - q_assign(&dsc,QF_call_ref,0); - if (!vpi && !vci) q_assign(&dsc,QF_rst_class,ATM_RST_ALL_VC); - else { - q_assign(&dsc,QF_rst_class,ATM_RST_IND_VC); - q_assign(&dsc,QF_vpi,vpi); - q_assign(&dsc,QF_vci,vci); - } - if ((size = q_close(&dsc)) >= 0) to_signaling(sig,q_buffer,size); -} - - -static void send_drop_party_ack(SIG_ENTITY *sig,unsigned long call_ref, - short ep_ref,unsigned char cause) -{ - Q_DSC dsc; - int size; - - q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_msg_type,ATM_MSG_DROP_PARTY_ACK); - q_assign(&dsc,QF_call_ref,call_ref); - q_assign(&dsc,QF_ep_ref,ep_ref); - q_assign(&dsc,QF_cause,cause); - if ((size = q_close(&dsc)) >= 0) to_signaling(sig,q_buffer,size); -} - - -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - -static void send_conn_avail(SOCKET *sock) -{ - Q_DSC dsc; - int size; - - q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_msg_type,ATM_MSG_CONN_AVAIL); - q_assign(&dsc,QF_call_ref,sock->call_ref); - if ((size = q_close(&dsc)) >= 0) to_signaling(sock->sig,q_buffer,size); -} - -#endif - - -static void uni_call(SOCKET *sock,unsigned char mid) -{ - char buffer[MAX_ATM_ADDR_LEN+1]; - int error; - - switch (mid) { - case ATM_MSG_STATUS: /* 5.5.6.12 */ - { - CALL_STATE state; - - /* - * NOTE: T322 isn't implemented yet, but when it is, make sure - * to only stop it on STATUS iff the cause is - * ATM_CV_RESP_STAT_ENQ. Supplementary services break if - * you stop on any STATUS. - */ - state = q_fetch(&in_dsc,QF_call_state); - if (state == cs_null) break; /* clear call */ - if (sock->call_state == cs_rel_req || sock->call_state == - cs_rel_ind) return; - if (state != sock->call_state) - diag(COMPONENT,DIAG_WARN,"STATUS %s received in state %s", - cs_name[state],cs_name[sock->call_state]); - } - return; - default: - ; - } - switch (mid) { - case ATM_MSG_CALL_PROC: /* CONNECTING, WAIT_REL, REL_REQ */ - if (sock->state == ss_wait_rel || sock->state == ss_rel_req) { - send_status(sock->sig,sock,0,ATM_CV_INCOMP_MSG, - ATM_MSG_CALL_PROC); - return; - } - if (sock->state != ss_connecting) break; - /* check for 2nd CALL_PROC @@@ */ - STOP_TIMER(sock); - if (q_present(&in_dsc,QG_conn_id)) { - int vpci; - - vpci = q_fetch(&in_dsc,QF_vpi); - sock->pvc.sap_family = AF_ATMPVC; - sock->pvc.sap_addr.itf = get_itf(sock->sig,&vpci); - sock->pvc.sap_addr.vpi = vpci; - sock->pvc.sap_addr.vci = q_fetch(&in_dsc,QF_vci); - diag(COMPONENT,DIAG_DEBUG,"ITF.VPI.VCI: %d.%d.%d", - sock->pvc.sap_addr.itf,sock->pvc.sap_addr.vpi, - sock->pvc.sap_addr.vci); - } - START_TIMER(sock,T310); - sock->call_state = cs_out_proc; - return; - case ATM_MSG_CONNECT: /* CONNECTING, REL_REQ */ - if (sock->state == ss_rel_req) { - send_status(sock->sig,sock,0,ATM_CV_INCOMP_MSG,ATM_MSG_CONNECT); - return; - } - if (sock->state != ss_connecting) break; - STOP_TIMER(sock); - if (q_present(&in_dsc,QG_conn_id)) { - int vpci; - - vpci = q_fetch(&in_dsc,QF_vpi); - sock->pvc.sap_family = AF_ATMPVC; - sock->pvc.sap_addr.itf = get_itf(sock->sig,&vpci); - sock->pvc.sap_addr.vpi = vpci; - sock->pvc.sap_addr.vci = q_fetch(&in_dsc,QF_vci); - diag(COMPONENT,DIAG_DEBUG,"ITF.VPI.VCI: %d/%d.%d", - sock->pvc.sap_addr.itf,sock->pvc.sap_addr.vpi, - sock->pvc.sap_addr.vci); - } - error = 0; - if (!sock->pvc.sap_addr.vpi && !sock->pvc.sap_addr.vci) - error = -EPROTO; - /* more problems */ - if (error) { - set_error(sock,error); - send_release(sock,0); /* @@@ cause follows reason ??? */ - START_TIMER(sock,T308_1); - new_state(sock,ss_rel_req); - return; - } - send_connect_ack(sock); - /* @@@ fill in sock->remote */ - /* @@@ fill in traffic parameters */ - send_kernel(sock->id,0,as_okay,0,&sock->pvc,NULL,&sock->local, - &sock->sap,&sock->qos); - new_state(sock,ss_connected); -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - sock->owner = 1; -#endif - if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) - &sock->remote,0) < 0) strcpy(buffer,""); - diag(COMPONENT,DIAG_INFO,"Active open succeeded (CR 0x%06X, " - "ID 0x%08x, to %s)",sock->call_ref,sock->id,buffer); - return; - case ATM_MSG_CONN_ACK: /* ACCEPTING, WAIT_REL, REL_REQ */ - diag(COMPONENT,DIAG_DEBUG,"CA vpi.vci=%d.%d", - sock->pvc.sap_addr.vpi,sock->pvc.sap_addr.vci); - if (sock->state == ss_wait_rel || sock->state == ss_rel_req) { - send_status(sock->sig,sock,0,ATM_CV_INCOMP_MSG, - ATM_MSG_CONN_ACK); - return; - } - if (sock->state != ss_accepting) break; - STOP_TIMER(sock); - send_kernel(sock->id,0,as_okay,0,NULL,NULL,&sock->local,&sock->sap, - NULL); - new_state(sock,ss_connected); -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - sock->owner = 0; -#endif - if (atm2text(buffer,MAX_ATM_ADDR_LEN+1, (struct sockaddr *) - &sock->remote,0) < 0) strcpy(buffer,""); - diag(COMPONENT,DIAG_INFO,"Passive open succeeded (CR 0x%06X, " - "ID 0x%08x, from %s)",sock->call_ref,sock->id,buffer); - return; - case ATM_MSG_RELEASE: /* all states */ - { - unsigned char cause; - - cause = q_fetch(&in_dsc,QF_cause); - diag(COMPONENT,DIAG_DEBUG,"Cause %d (%s)",cause,cause > 127 ? - "invalid cause" : cause_text[cause]); - } - switch (sock->state) { - case ss_connecting: - set_error(sock,-ECONNREFUSED); - /* fall through */ - case ss_accepting: - set_error(sock,-ECONNRESET); /* ERESTARTSYS ? */ - send_release_complete(sock->sig,sock->call_ref,0); - SEND_ERROR(sock->id,sock->error); - STOP_TIMER(sock); - free_sock(sock); - return; - case ss_rel_req: - send_close(sock); - /* fall through */ - case ss_wait_rel: - STOP_TIMER(sock); - free_sock(sock); - return; -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - case ss_mod_req: -#endif - STOP_TIMER(sock); - /* fall through */ -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - case ss_mod_lcl: - case ss_mod_rcv: - case ss_mod_fin_ok: - case ss_mod_fin_fail: - case ss_mod_fin_ack: -#endif - case ss_connected: - diag(COMPONENT,DIAG_INFO,"Passive close (CR 0x%06X)", - sock->call_ref); -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - if (timer_handler(sock->conn_timer) == on_T361) - STOP_TIMER(sock); -#endif - send_close(sock); - new_state(sock,ss_rel_ind); - return; - case ss_indicated: - /* fall through */ - case ss_proceeding: - send_release_complete(sock->sig,sock->call_ref,0); - new_state(sock,ss_zombie); - /* fall through */ - case ss_rel_ind: - return; - default: - send_release_complete(sock->sig,sock->call_ref,0); - /* @@@ should be ATM_CV_INCOMP_MSG */ - break; - } - break; - case ATM_MSG_RESTART: - set_error(sock,-ENETRESET); - /* fall through */ - case ATM_MSG_STATUS: /* fall through when clearing */ - case ATM_MSG_REL_COMP: /* basically any state (except LISTENING and - ZOMBIE) */ - { - unsigned char cause; - - if (mid != ATM_MSG_REL_COMP || !q_present(&in_dsc,QF_cause)) - cause = 0; - else { - cause = q_fetch(&in_dsc,QF_cause); - diag(COMPONENT,DIAG_DEBUG,"Cause %d (%s)",cause, - cause > 127 ? "invalid cause" : cause_text[cause]); - } - switch (sock->state) { - case ss_connecting: - set_error(sock,cause == ATM_CV_UNALLOC ? - -EADDRNOTAVAIL : cause == ATM_CV_RES_UNAVAIL || -#if defined(UNI31) || defined(UNI40) || defined(DYNAMIC_UNI) - cause == ATM_CV_UCR_UNAVAIL_NEW || -#endif - cause == ATM_CV_NO_ROUTE_DEST ? -EHOSTUNREACH : - cause == ATM_CV_NUM_CHANGED ? -EREMCHG : - cause == ATM_CV_DEST_OOO ? -EHOSTDOWN : - -ECONNREFUSED); - /* fall through */ - case ss_accepting: - set_error(sock,-ECONNRESET); /* ERESTARTSYS ? */ - SEND_ERROR(sock->id,sock->error); - STOP_TIMER(sock); - free_sock(sock); - return; - case ss_rel_req: - send_close(sock); - /* fall through */ - case ss_wait_rel: - STOP_TIMER(sock); - free_sock(sock); - return; -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - case ss_mod_req: -#endif - STOP_TIMER(sock); - /* fall through */ -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - case ss_mod_lcl: - case ss_mod_rcv: - case ss_mod_fin_ok: - case ss_mod_fin_fail: - case ss_mod_fin_ack: -#endif - case ss_connected: - diag(COMPONENT,DIAG_INFO,"Passive close (CR 0x%06X)", - sock->call_ref); -#if defined(Q2963_1) || defined(DYNAMIC_UNI) - if (timer_handler(sock->conn_timer) == on_T361) - STOP_TIMER(sock); -#endif - send_close(sock); - /* fall through */ - case ss_rel_ind: - new_state(sock,ss_wait_close); - return; - case ss_indicated: - /* fall through */ - case ss_proceeding: - new_state(sock,ss_zombie); - return; - default: - break; - } - break; /* fail */ - } - case ATM_MSG_ALERTING: - /* - * We basically ignore this junk message, except for the connection - * identifier it may carry. - */ - if (q_present(&in_dsc,QG_conn_id)) { - int vpci; - - vpci = q_fetch(&in_dsc,QF_vpi); - sock->pvc.sap_family = AF_ATMPVC; - sock->pvc.sap_addr.itf = get_itf(sock->sig,&vpci); - sock->pvc.sap_addr.vpi = vpci; - sock->pvc.sap_addr.vci = q_fetch(&in_dsc,QF_vci); - diag(COMPONENT,DIAG_DEBUG,"ITF.VPI.VCI: %d.%d.%d", - sock->pvc.sap_addr.itf,sock->pvc.sap_addr.vpi, - sock->pvc.sap_addr.vci); - } - return; - case ATM_MSG_NOTIFY: - /* silently ignore this junk */ - return; -#if defined(Q2963_1) || defined(DYNAMIC_UNI) -/* - * Buglet ahead: should actually test "call_state" - */ - case ATM_MSG_MODIFY_REQ: - if (!(sock->sig->uni & S_Q2963_1)) goto _default; - if (sock->state != ss_connected || sock->owner) break; - sock->new_qos = sock->qos; - if (q_present(&in_dsc,QF_fw_pcr_01)) - sock->new_qos.rxtp.max_pcr = q_fetch(&in_dsc,QF_fw_pcr_01); - if (q_present(&in_dsc,QF_bw_pcr_01)) - sock->new_qos.txtp.max_pcr = q_fetch(&in_dsc,QF_bw_pcr_01); - send_kernel(sock->id,0,as_modify,ATM_MF_INC_RSV | ATM_MF_DEC_RSV | - ATM_MF_DEC_SHP,NULL,NULL,NULL,NULL,&sock->new_qos); - new_state(sock,ss_mod_rcv); - return; - case ATM_MSG_MODIFY_ACK: - if (!(sock->sig->uni & S_Q2963_1)) goto _default; - if (sock->state != ss_mod_req) break; - STOP_TIMER(sock); - sock->qos = sock->new_qos; - if (q_present(&in_dsc,QG_bbrt)) send_conn_avail(sock); - send_kernel(sock->id,0,as_modify,ATM_MF_SET,NULL,NULL,NULL,NULL, - &sock->qos); - new_state(sock,ss_mod_fin_ok); - return; - case ATM_MSG_MODIFY_REJ: - if (!(sock->sig->uni & S_Q2963_1)) goto _default; - if (sock->state != ss_mod_req) break; - STOP_TIMER(sock); - sock->error = -EAGAIN; - send_kernel(sock->id,0,as_modify,ATM_MF_SET,NULL,NULL,NULL,NULL, - &sock->qos); - new_state(sock,ss_mod_fin_fail); - return; - case ATM_MSG_CONN_AVAIL: - if (!(sock->sig->uni & S_Q2963_1)) goto _default; - if (sock->state != ss_connected || !sock->owner) break; - STOP_TIMER(sock); - send_kernel(sock->id,0,as_modify,ATM_MF_SET,NULL,NULL,NULL,NULL, - &sock->qos); - new_state(sock,ss_mod_fin_ack); - return; - _default: /* jump here if we don't want to understand a message */ -#endif - default: - diag(COMPONENT,DIAG_WARN,"Bad signaling message %d",mid); - send_status(sock->sig,sock,0,ATM_CV_UNKNOWN_MSG_TYPE,mid); - return; - } - diag(COMPONENT,DIAG_WARN, - "Signaling message %s is incompatible with state %s/%s (%d?%d)", - mid2name(mid),state_name[sock->state],cs_name[sock->call_state], - (int) sock->state,(int) sock->call_state); - send_status(sock->sig,sock,0,ATM_CV_INCOMP_MSG,mid); -} - - -void clear_all_calls(SIG_ENTITY *sig) -{ - SOCKET *curr,*next; - - for (curr = sockets; curr; curr = next) { - next = curr->next; - if (curr->sig == sig && curr->call_state != cs_null) - uni_call(curr,ATM_MSG_RESTART); - } -} - - -void clear_all_calls_on_T309(SIG_ENTITY *sig) -{ - clear_all_calls(sig); - t309 = NULL; -} - - -void saal_failure(SIG_ENTITY *sig) -{ - SOCKET *curr,*next; - - trace_msg("SAAL went down"); - for (curr = sockets; curr; curr = next) { - next = curr->next; - if (curr->sig == sig && curr->call_state != cs_null) - if (curr->call_state != cs_active) - uni_call(curr,ATM_MSG_RESTART); - else if (!t309) t309 = start_timer(T309_TIME,on_T309,sig); - } -} - - -void saal_okay(SIG_ENTITY *sig) -{ - SOCKET *curr; - - trace_msg("SAAL came up"); -#ifdef THOMFLEX - /* - * Some versions of the Thomson Thomflex 5000 won't do any signaling before - * they get a RESTART. Whenever SAAL comes up, this may indicate that the - * switch got booted, so we send that RESTART. We also have to clear all - * pending connections, which isn't that nice ... Note that the rest of the - * RESTART state machine is not implemented, so the RESTART ACKNOWLEDGE - * will yield a warning. - */ - { - Q_DSC dsc; - int size; - - clear_all_calls(sig); - q_create(&dsc,q_buffer,MAX_Q_MSG); - q_assign(&dsc,QF_msg_type,QMSG_RESTART); - q_assign(&dsc,QF_call_ref,0); - q_assign(&dsc,QF_rst_class,ATM_RST_ALL_VC); - if ((size = q_close(&dsc)) >= 0) to_signaling(sig,q_buffer,size); - } -#endif - if (!t309) return; - stop_timer(t309); - t309 = NULL; - for (curr = sockets; curr; curr = curr->next) - if (curr->sig == sig && curr->call_state != cs_null) - send_status_enq(curr); -} - - -static void process_uni(SIG_ENTITY *sig,void *msg) -{ - SOCKET *curr; - unsigned long call_ref; - unsigned char mid; - - call_ref = q_fetch(&in_dsc,QF_call_ref)^0x800000; - mid = q_fetch(&in_dsc,QF_msg_type); - if (mid == ATM_MSG_REST_ACK) return; - if (mid == ATM_MSG_RESTART) { /* 5.5.5.2 */ - int rst_class; - - rst_class = q_fetch(&in_dsc,QF_rst_class); - switch (rst_class) { - case ATM_RST_IND_VC: - { - int vpi,vci; - - if (!q_present(&in_dsc,QG_conn_id)) { - send_status(sig,NULL,0L,ATM_CV_MAND_IE_MISSING, - ATM_IE_CONN_ID); - return; - } - vpi = q_fetch(&in_dsc,QF_vpi); - vci = q_fetch(&in_dsc,QF_vci); - for (curr = sockets; curr; curr = curr->next) - if (curr->sig == sig && curr->pvc.sap_addr.vpi == vpi && - curr->pvc.sap_addr.vci == vci) break; - if (!curr) { - send_status(sig,NULL,0L,ATM_CV_INVALID_IE, - ATM_IE_CONN_ID); - return; - } - uni_call(curr,mid); - send_restart_ack(sig,vpi,vci); - } - break; - case ATM_RST_ALL_VC: - clear_all_calls(sig); - send_restart_ack(sig,0,0); - break; - default: - send_status(sig,NULL,0L,ATM_CV_INVALID_IE,ATM_IE_RESTART); - } - return; - } - if (!(call_ref & 0x7fffff)) { - return; /* bad things happen ... @@@ */ - } - for (curr = sockets; curr; curr = curr->next) - if (curr->sig == sig && curr->call_ref == call_ref) break; - diag(COMPONENT,DIAG_DEBUG,"FROM SAAL %d.%d.%d: %s (0x%02X) CR 0x%06lx for " - "0x%lx",S_PVC(sig),mid2name(((unsigned char *) msg)[5]), - ((unsigned char *)msg)[5],call_ref,curr ? curr->id : 0); - if (mid == ATM_MSG_SETUP) { - if (!curr) setup_call(sig,call_ref); - return; - } - if (mid == ATM_MSG_STATUS_ENQ) { - send_status(curr->sig,curr,call_ref,ATM_CV_RESP_STAT_ENQ); - return; - } - if (curr && q_present(&in_dsc,QF_ep_ref) && mid != ATM_MSG_ADD_PARTY && - mid != ATM_MSG_DROP_PARTY_ACK) - if (curr->ep_ref != q_fetch(&in_dsc,QF_ep_ref)) { - send_drop_party_ack(sig,call_ref,q_fetch(&in_dsc,QF_ep_ref), - ATM_CV_INV_EPR); - return; - } - if (!curr || curr->call_state == cs_null) { - if (mid != ATM_MSG_REL_COMP) - if (mid != ATM_MSG_STATUS) - send_release_complete(sig,call_ref,ATM_CV_INV_CR); - else if (q_fetch(&in_dsc,QF_call_state) != (int) cs_null) - send_release_complete(sig,call_ref,ATM_CV_INCOMP_MSG); - return; - } - uni_call(curr,mid); -} - - -static void abort_call(SIG_ENTITY *sig,unsigned char *msg,int size) -{ - SOCKET *curr; - unsigned long call_ref; - - if (size < 6) { - diag(COMPONENT,DIAG_ERROR,"message too short (%d bytes)",size); - return; - } - /* hope that at least the call ref is okay ... */ - call_ref = ((msg[3] << 16) | (msg[4] << 8) | msg[5])^0x800000; - diag(COMPONENT,DIAG_ERROR,"can't parse message - aborting the call " - "(CR 0x%06lx)",call_ref); - for (curr = sockets; curr; curr = curr->next) - if (curr->sig == sig && curr->call_ref == call_ref) { - uni_call(curr,ATM_MSG_RESTART); - break; - } - send_release_complete(sig,call_ref,ATM_CV_PROTOCOL_ERROR); -} - - -void to_uni(SIG_ENTITY *sig,void *msg,int size) -{ - if (q_open(&in_dsc,msg,size) < 0) { - abort_call(sig,msg,size); - return; - } - process_uni(sig,msg); - if (q_close(&in_dsc) < 0) - diag(COMPONENT,DIAG_ERROR,"q_close returned <0 in to_uni"); -} diff -ur --new-file old/atm/sigd.old/Makefile new/atm/sigd.old/Makefile --- old/atm/sigd.old/Makefile Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/Makefile Sun Nov 1 17:36:34 1998 @@ -0,0 +1,39 @@ +LIBS=-L../saal -lsaal -latmd -lfl # lex may want -ll here +LIBDEPS=../saal/libsaal.a ../lib/libatmd.a +INCLUDES=-I../qgen -I../saal -I. +OBJS=atmsigd.o io.o kernel.o mess.o proto.o uni.o sap.o timeout.o trace.o \ + policy.o lex.yy.o y.tab.o +EXTOBJS=../qgen/q.out.o ../qgen/qd.dump.o +#BOOTPGMS=atmsigd # don't install anymore +PGMS=atmsigd.old +TRASH=mess.c +#MAN4=atmsigd.conf.4 # don't install anymore +#MAN8=atmsigd.8 # don't install anymore + +include ../Rules.make +CFLAGS_NOWARN += $(STANDARDS) + +atmsigd.old: $(OBJS) $(EXTOBJS) + $(CC) $(LDFLAGS) -o atmsigd.old $(OBJS) $(EXTOBJS) \ + $(LDLIBS) $(LIBS) + +lex.yy.c: cfg.l y.tab.h ../lib/atm.h + $(LEX) cfg.l + +y.tab.c y.tab.h: cfg.y ../lib/atmd.h proto.h io.h + $(YACC) -d cfg.y + +mess.c: ../qgen/uni.h mkmess.pl + perl ./mkmess.pl <../qgen/uni.h >mess.c + +# +# The following hack makes sure that "make depend" finds q.out.h and is +# happy with it. Once qgen has been built, there will be ../qgen/q.out.h, +# which is first in the include file search path and therefore gets +# included. An second "make depend" will also use the right file. +# + +depend: fake_q.out.h + +fake_q.out.h: + echo "! This must not compile" >q.out.h diff -ur --new-file old/atm/sigd.old/atmsigd.8 new/atm/sigd.old/atmsigd.8 --- old/atm/sigd.old/atmsigd.8 Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/atmsigd.8 Thu Aug 20 18:04:23 1998 @@ -0,0 +1,105 @@ +.TH ATMSIGD 8 "June 25, 1998" "Linux" "Maintenance Commands" +.SH NAME +atmsigd \- ATM signaling demon +.SH SYNOPSIS +.B atmsigd +.RB [ \-b ] +.RB [ \-c\ \fIconfig_file\fP ] +.RB [ \-d ] +.RB [ \-D\ \fIdump_dir\fP ] +.RB [ \-l\ \fIlogfile\fP ] +.RB [ \-m\ \fImode\fP ] +.RB [ \-n ] +.RB [ \-q\ \fIqos\fP ] +.RB [ \-t\ \fItrace_length\fP ] +.RB [ [\fIitf\fP.]\fIvpi\fP.\fIvci\fP +.RB [ \fIinput\ output\fP ] ] +.SH DESCRIPTION +\fBatmsigd\fP implements the ATM UNI signaling protocol. Requests to +establish, accept, or close ATM SVCs are sent from the kernel (using a +comparably simple protocol) to the signaling demon, which then performs +the dialog with the network. +.P +Note that \fBatmsigd\fP is not able to accept or establish connections +until the local ATM address of the interface is configured by \fBilmid\fP +or manually using \fBatmaddr\fP. +.P +The default signaling VC (interface 0, VPI 0, VCI 5) can be overridden on +the command line by specifying a different PVC address. +.P +When overriding the default VC, optionally a pair of named pipes to use for +communicating with the user of signaling can be specified. Normally, the +kernel is the user of signaling and \fBatmsigd\fP opens a special socket for +communication with it. +.P +If \fBatmsigd\fP is killed, all system calls requiring interaction with it +will return with an error and set \fBerrno\fP to \fBEUNATCH\fP. +.SH OPTIONS +.IP \fB\-b\fP +Run in background (i.e. in a forked child process) after initializing. +.IP \fB\-c\ \fIconfig_file\fP +Use the specified configuration file instead of \fB/etc/atmsigd.conf\fP +If an option is specified in the configuration file and on the command +line, the command line has priority. +.IP \fB\-d\fP +Enables (lots of) debugging output. By default, \fBatmsigd\fP is comparably +quiet. +.IP \fB\-D\ \fIdump_dir\fP +Specifies the directory to which \fBatmsigd\fP will write status and trace +dumps. If tracing is not yet enabled, the trace size is automatically +set to a (small) default value. +.IP \fB\-l\ \fIlogfile\fP +Write diagnostic messages to the specified file. The special name +\fBsyslog\fP is used to send diagnostics to the system logger, \fBstderr\fP +is used to send diagnostics to standard error. If \fB\-l\fP is absent, the +setting in \fBatmsigd.conf\fP is used. If \fBatmsigd\fP doesn't specify a +destination either, messages are written to standard error. +.IP \fB\-m\ \fImode\fP +Set the mode of operation. The following modes are available: \fBuser\fP for +the user side (the default), \fBnetwork\fP for the network side (useful if you +have two PCs but no switch), and \fBswitch\fP for operation with a signaling +relay in a switch. +.IP \fB\-n\fP +Prints addresses in numeric format only, i.e. no address to name translation +is attempted. +.IP \fB\-q\ \fIqos\fP +Configures the signaling VC to use the specified quality of service (see +qos(7) for the syntax). +By default, UBR at link speed is used on the signaling VC. +.IP \fB\-t\ \fItrace_length\fP +Enables tracing and sets the number +of entries that should be kept in the trace buffer. +.SH FILES +.PD 0 +.TP 25 +.B /etc/atmsigd.conf +default configuration file +.TP 25 +.B /var/tmp/atmsigd.\fIpid\fB.status.\fIversion\fP +default location of status dumps +.TP 25 +.B /var/tmp/atmsigd.\fIpid\fB.trace.\fIversion\fP +default location of signaling trace dumps +.PD +.SH DEBUGGING +When receiving a \fBSIGUSR1\fP signals, \fBatmsigd\fP dumps the list of all +internal socket descriptors. With \fBSIGUSR2\fP, it dumps the contents of +the trace buffer. If a dump directory was set, dumps are written to files +called \fBatmsigd.\fP\fIpid\fP\fB.status.\fP\fInumber\fP and +\fBatmsigd.\fP\fIpid\fP\fB.trace.\fP\fInumber\fP, respectively, with +\fInumber\fP +starting at zero and being incremented for every dump. If no dump directory +is set, dumps are written to standard error. +.P +Dumps are also generated whenever \fBatmsigd\fP detects a fatal error and +terminates. No attempt is made to catch signals like \fBSIGSEGV\fP. +.SH BUGS +The generation of traces is a comparably slow +process which may already take several seconds for only 100 trace entries. +To generate a trace dump, \fBatmsigd\fP therefore forks a child process that +runs in parallel to the signaling demon. +.SH AUTHOR +Werner Almesberger, EPFL ICA +.SH "SEE ALSO" +atmaddr(8), atmsigd.conf(4), ilmid(8), qos(7) +.\"{{{}}} diff -ur --new-file old/atm/sigd.old/atmsigd.c new/atm/sigd.old/atmsigd.c --- old/atm/sigd.old/atmsigd.c Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/atmsigd.c Mon Oct 5 17:52:08 1998 @@ -0,0 +1,462 @@ +/* atmsigd.c - ATM signaling demon */ + +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "atm.h" +#include "atmd.h" +#include "qlib.h" + +#include "io.h" +#include "proto.h" +#include "saal.h" +#include "trace.h" + + +#define COMPONENT "SIGD" +#define CONFIG_FILE "/etc/atmsigd.conf" + + +extern int yyparse(void); +extern FILE *yyin; + +int debug = 0; +int pretty = A2T_PRETTY | A2T_NAME | A2T_LOCAL; +int sig_pcr = -1; /* obsolete */ +const char *sig_qos = NULL; +const char *dump_dir = NULL; + +SIGNALING_MODE mode = sm_user; +int net = 0; +int allocate_ci = 1; + + +/* ------------------------------ SAAL relays ------------------------------ */ + + +static SAAL_DSC saal; + + +static void q_estab_conf(void *user_data,void *uu_data,int uu_length) +{ + saal_okay(); +} + + +static void q_rel_ind(void *user_data,void *uu_data,int uu_length) +{ + saal_failure(); + saal_estab_req(&saal,NULL,0); +} + + +static void q_restart(void *user_data,void *uu_data,int uu_length,int ind) +{ + saal_failure(); + if (!ind) saal_okay(); /* actually, ind should probably never be zero */ +} + + +void from_net(void *buffer,int size) +{ + saal_pdu(&saal,buffer,size); +} + + +void to_signaling(void *msg,int size) +{ + trace_uni("TO NETWORK",msg,size); + diag(COMPONENT,DIAG_DEBUG,"TO SAAL: %s (0x%02x) CR 0x%06x (%d bytes)", + mid2name(((unsigned char *) msg)[5]),((unsigned char *) msg)[5], + (((unsigned char *) msg)[2] << 16) | (((unsigned char *) msg)[3] << 8) | + ((unsigned char *) msg)[4],size); + saal_send(&saal,msg,size); +} + + +static void q_data_ind(void *user_data,void *data,int length) +{ + trace_uni("FROM NETWORK",data,length); + to_uni(data,length); +} + + +static void q_cpcs_send(void *user_data,void *data,int length) +{ + to_net(data,length); +} + + +static SAAL_USER_OPS ops = { + NULL, /* no q_estab_ind - 5.5.6.9 says 5.5.6.11 and 5.5.6.11 says "may" */ + q_estab_conf, + q_rel_ind, + NULL, /* no q_rel_conf - what to do ? */ + q_restart, + q_data_ind, + NULL, /* no q_unitdata */ + q_cpcs_send +}; + + +/* -------------------------------- signals -------------------------------- */ + + +static volatile int got_usr1 = 0,got_usr2 = 0; + + +static void dump_addr(FILE *file,const char *label,struct sockaddr_atmsvc *addr) +{ + char buffer[MAX_ATM_ADDR_LEN+1]; + int i; + + if (!atmsvc_addr_in_use(*addr)) return; + fprintf(file," %s ",label); + if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) addr,A2T_NAME | + A2T_PRETTY | A2T_LOCAL) >= 0) fprintf(file,"%s\n",buffer); + else { + fprintf(file,"\n"); + } +} + + +static void dump_sap(FILE *file,const char *label,struct atm_sap *sap) +{ + char buffer[MAX_ATM_SAP_LEN+1]; + int i; + + fprintf(file," %s ",label); + if (sap2text(buffer,MAX_ATM_SAP_LEN+1,sap,S2T_NAME | S2T_LOCAL) >= 0) + fprintf(file,"%s\n",buffer); + else { + fprintf(file,"\n"); + } +} + + +static void dump_status(FILE *file,const char *banner) +{ + SOCKET *walk; + + if (sockets) fprintf(file,"%s\n\n",banner); + for (walk = sockets; walk; walk = walk->next) { + fprintf(file,"0x%lx: %s, CR 0x%06lX, PVC %d.%d.%d\n",walk->id, + state_name[walk->state],walk->call_ref,walk->pvc.sap_addr.itf, + walk->pvc.sap_addr.vpi,walk->pvc.sap_addr.vci); + dump_addr(file,"local ",&walk->local); + dump_addr(file,"remote",&walk->remote); + dump_sap(file,"sap",&walk->sap); + } +} + + +static void dump_trace(FILE *file,const char *banner) +{ + static int busy = 0; + char *trace; + + if (busy++) abort(); + trace = get_trace(); + if (trace) { + fprintf(file,"%s\n\n",banner); + fprintf(file,"%s",trace); + } + busy--; +} + + +void poll_signals(void) +{ + static status_num = 0,trace_num = 0; + char path[PATH_MAX+1]; + FILE *file; + + if (got_usr1) { + got_usr1 = 0; + if (!dump_dir) file = stderr; + else { + sprintf(path,"atmsigd.%d.status.%d",getpid(),status_num++); + if ((file = fopen(path,"w"))) + diag(COMPONENT,DIAG_INFO,"Dumping to %s",path); + else { + perror(path); + file = stderr; + } + } + dump_status(file,"Status dump (on SIGUSR1)"); + if (file != stderr) (void) fclose(file); + } + if (got_usr2) { + pid_t pid; + + got_usr2 = 0; + if (!dump_dir) file = stderr; + else { + sprintf(path,"atmsigd.%d.trace.%d",getpid(),trace_num++); + if ((file = fopen(path,"w"))) + diag(COMPONENT,DIAG_INFO,"Dumping to %s",path); + else { + perror(path); + file = stderr; + } + } + if (!(pid = fork())) + dump_trace(file,"Message trace (on SIGUSR2)"); + else if (pid < 0) perror("fork"); + if (file != stderr) (void) fclose(file); + if (!pid) exit(0); + } +} + + +static void handle_signal(int sig) +{ + switch (sig) { + case SIGUSR1: + got_usr1 = 1; + break; + case SIGUSR2: + got_usr2 = 1; + break; + default: + break; + } +} + + +static void setup_signals(void) +{ + struct sigaction act; + + (void) signal(SIGCHLD,SIG_IGN); /* reap children automatially */ + act.sa_handler = handle_signal; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + if (sigaction(SIGUSR1,&act,NULL) < 0) { + perror("sigaction"); + exit(1); + } + if (sigaction(SIGUSR2,&act,NULL) < 0) { + perror("sigaction"); + exit(1); + } +} + + +/* ------------------------------- main ... ------------------------------- */ + + +static void trace_on_exit(int status,void *dummy) +{ + char path[PATH_MAX+1]; + FILE *file; + + if (!status) return; + if (!dump_dir) file = stderr; + else { + sprintf(path,"atmsigd.%d.trace.exit",getpid()); + if (!(file = fopen(path,"w"))) { + perror(path); + file = stderr; + } + } + dump_trace(file,"Message trace (after error exit)"); + if (file != stderr) (void) fclose(file); +} + + +static void usage(const char *name) +{ + fprintf(stderr,"usage: %s [ -b ] [ -c config_file ] [ -d ] " + "[ -D dump_dir ]\n" + " [ -l logfile ] [ -n ] [ -m user|network|switch ] [ -q qos ]\n" + " [ -t trace_length ] [ [itf.]vpi.vci [ socket_path ] ]\n",name); + exit(1); +} + + +int main(int argc,char **argv) +{ + const char *config_file; + char *end; + int c,background; + + set_application("atmsigd"); + config_file = CONFIG_FILE; + dump_dir = NULL; + background = 0; + memset(&signaling_pvc,0,sizeof(signaling_pvc)); + signaling_pvc.sap_addr.vci = 5; + /* 1st pass to get the -c option */ + while ((c = getopt(argc,argv,"Abc:dD:l:m:nNP:q:t:")) != EOF) + if (c == 'c') config_file = optarg; + if (!(yyin = fopen(config_file,"r"))) + diag(COMPONENT,DIAG_WARN,"%s not found. - Using defaults.",config_file); + else if (yyparse()) + diag(COMPONENT,DIAG_FATAL,"Error in config file. - Aborting."); + /* process all other options but -c */ + optind = 0; + while ((c = getopt(argc,argv,"Abc:dD:l:m:nNP:q:t:")) != EOF) + switch (c) { + case 'A': + allocate_ci = 0; + break; + case 'b': + background = 1; + break; + case 'c': + /* already handled */ + break; + case 'd': + set_verbosity(NULL,DIAG_DEBUG); + set_verbosity("QMSG",DIAG_INFO); + set_verbosity("SSCOP",DIAG_INFO); + debug = 1; + /*q_dump = 1;*/ + break; + case 'D': + dump_dir = optarg; + if (!trace_size) trace_size = DEFAULT_TRACE_SIZE; + break; + case 'l': + set_logfile(optarg); + break; + case 'm': + if (!strcmp(optarg,"user")) mode = sm_user; + else if (!strcmp(optarg,"network")) mode = sm_net; + else if (!strcmp(optarg,"switch")) mode = sm_switch; + else usage(argv[0]); + break; + case 'n': + pretty = A2T_PRETTY; + break; + case 'N': + net = 1; + break; + case 'q': + if (sig_pcr != -1) usage(argv[0]); + sig_qos = optarg; + break; + case 'P': /* obsolete */ + if (sig_qos) usage(argv[0]); + sig_pcr = strtol(optarg,&end,0); + if (*end) usage(argv[0]); + break; + case 't': + trace_size = strtol(optarg,&end,0); + if (*end) usage(argv[0]); + break; + default: + usage(argv[0]); + } + switch (mode) { + case sm_unknown: + if (net) { + if (allocate_ci) { + mode = sm_net; + diag(COMPONENT,DIAG_WARN,"option -N is obsolete, " + "please use -m network instead"); + } + else { + mode = sm_switch; + diag(COMPONENT,DIAG_WARN,"options -N -A are obsolete, " + "please use -m switch instead"); + } + } + else if (allocate_ci) mode = sm_user; + else usage(argv[0]); + break; + case sm_user: + allocate_ci = 1; /* should be ignored anyway */ + net = 0; + break; + case sm_net: + allocate_ci = 1; + net = 1; + break; + case sm_switch: + allocate_ci = 0; + net = 1; + break; + default: + abort(); + } + if (optind < argc) { + if (text2atm(argv[optind],(struct sockaddr *) &signaling_pvc, + sizeof(signaling_pvc),T2A_PVC) < 0) + diag(COMPONENT,DIAG_FATAL,"text2atm \"%s\": failed",argv[optind]); + optind++; + if (optind == argc-1) { + open_unix(argv[optind]); + optind++; + } + } + if (optind != argc) usage(argv[0]); + diag(COMPONENT,DIAG_INFO,"Linux ATM signaling " +#ifdef UNI30 + "UNI 3.0" +#endif +#ifdef UNI31 + "UNI 3.1" +#ifdef ALLOW_UNI30 + "+3.0compat" +#endif +#endif +#ifdef UNI40 + "UNI 4.0" +#ifdef Q2963_1 + "+Q.2963.1" +#endif +#endif + "/AAL5, version " VERSION); + if (dump_dir) + if (chdir(dump_dir) < 0) + diag(COMPONENT,DIAG_ERROR,"chdir %s: %s",dump_dir,strerror(errno)); + diag(COMPONENT,DIAG_INFO,"Acting as %s", + mode == sm_user ? "USER side" : + mode == sm_net ? "NETWORK side" : "SWITCH"); + if (open_all()) return 1; + init_current_time(); + if (mode != sm_switch) init_addr(); + q_start(); + start_saal(&saal,&ops,NULL, +#ifdef UNI30 + sscop_qsaal1 +#else + sscop_q2110 +#endif + ); + saal_estab_req(&saal,NULL,0); + setup_signals(); + if (background) { + pid_t pid; + + pid = fork(); + if (pid < 0) + diag(COMPONENT,DIAG_FATAL,"fork: %s",strerror(errno)); + if (pid) { + diag(COMPONENT,DIAG_DEBUG,"Backgrounding (PID %d)",pid); + exit(0); + } + } + (void) on_exit(trace_on_exit,NULL); + poll_loop(); + close_all(); + stop_saal(&saal); + return 0; +} diff -ur --new-file old/atm/sigd.old/atmsigd.conf.4 new/atm/sigd.old/atmsigd.conf.4 --- old/atm/sigd.old/atmsigd.conf.4 Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/atmsigd.conf.4 Thu Aug 20 18:04:24 1998 @@ -0,0 +1,113 @@ +.TH ATMSIGD.CONF 4 "June 25, 1998" "Linux" "File Formats" +.SH NAME +atmsigd.conf \- configuration file for the ATM signaling demon +.SH SYNOPSIS +.B /etc/atmsigd.conf +.SH DESCRIPTION +\fBatmsigd.conf\fP contains configuration data for \fBatmsigd\fP. +\fBatmsigd\fP reads \fBatmsigd.conf\fP after parsing the command +line options, before connecting to the ATM network. +.P +Configuration parameters are arranged in functional groups. In order to +set a parameter, the name of the group, the name of the parameter, and +the parameter value(s) have to be specified, e.g. +.nf +.sp + sig level debug +.sp +.fi +decreases the logging threshold for messages related to signaling to the +\fBdebug\fP level. The following options are recognized: +.IP \fBdebug\ dump\ \fIpath\fP +Specifies the directory to which \fBatmsigd\fP will write status and trace +dumps. If tracing is not yet enabled, the trace size is automatically +set to a (small) default value. +.IP \fBdebug\ level\ \fIlevel\fP +Sets the default debug level to \fIlevel\fP. \fIlevel\fP can be any of +\fBdebug\fP, \fBinfo\fP, \fBwarn\fP, \fBerror\fP, and \fBfatal\fP. Only +messages with the same or a higher priority than the debug level are printed. +Note that +the command-line option \fB\-d\fP generates even more output (e.g. hexdumps +of all packets passing between \fBatmsigd\fP and the network) than +\fBdebug level debug\fP. +.IP \fBdebug\ log\ \fIpath\fP +Specifies the file to which \fBatmsigd\fP writes logging messages. When +using the special file name \fBsyslog\fP, messages are send to the +system logger instead. Log messages are written to standard output if no log +file is specified. Writing to standard output can also be explicitly requested +by using the special file name \fBstderr\fP. +.IP \fBdebug\ trace\ \fP[\fInumber\fP] +Enables tracing and optionally sets the number of entries that should be +kept in the trace buffer. A (small) default is used if the number is +omitted. +.IP \fBio\ level\ \fIlevel\fP +Sets the debug level for IO-related messages to \fIlevel\fP. +.IP \fBio\ qos\ \fIqos\fP +Configures the signaling VC to use the specified QOS (see qos(7) for the +syntax). By default, UBR at link speed is used on the signaling VC. +.IP \fBio\ vc\ \fP[\fIitf\fB.\fP]\fIvpi\fB.\fIvci\fP +Uses the specified VC for signaling messages instead of the usual 0.0.5. +.IP \fBsaal\ level\ \fIlevel\fP +Sets the debug level for messages related to SAAL (i.e. SSCF and SSCOP) to +\fIlevel\fP. +.IP \fBsig\ level\ \fIlevel\fP +Sets the debug level for messages related to signaling (Q.2931 or ISP) to +\fIlevel\fP. +.IP \fBsig\ mode\ \fImode\fP +Set the mode of operation. The following modes are available: \fBuser\fP for +the user side, \fBnetwork\fP for the network side, and \fBswitch\fP for +operation in a switch. The default behaviour is \fBuser\fP. +.IP \fBsig\ uni30\fP +Use UNI 3.0 signaling. This option is not implemented. The signaling mode +must be configured at compile time. +.IP \fBsig\ uni31\fP +Use UNI 3.1 signaling. This option is not implemented. The signaling mode +must be configured at compile time. +.IP \fBsig\ vpci\ \fIvpci\fB\ itf\ \fIitf\fP +Sets up a very simplistic type of routing. All calls with VPCI values +equal to or greater than \fIvpci\fP will be routed to \fIitf\fP, and their +VPI values will be set to the signaled VPCI minus \fIvpci\fP. Multiple +\fBsig vpci\fP entries can be used to support an arbitrary number of +interfaces. +Example: with \fBsig vpci 4 itf 1\fP, a call signaled for +VPCI/VCI 0.x is routed to 0.0.x, a call signaled for 6.y is routed to +1.2.y, etc. +.IP \fBpolicy\ level\ \fIlevel\fP +Sets the debug level for messages related to policy decisions to \fIlevel\fP. +.IP \fBpolicy\ \fIdecision\ direction\ address\fP +Takes the specified \fIdecision\fP for calls from or to \fIaddress\fP. +\fIdecision\fP can be either \fBallow\fP or \fBreject\fP. \fIdirection\fP is +either \fBfrom\fP or \fBto\fP. The \fIaddress\fP may be wildcarded by +prepending a slash and the number of significant bits (NSAP) or digits (E.164). +The rules are searched in the order in which they appear in \fBatmsigd.conf\fP +until the first match. If no rule matches, the call is allowed. +.P +When setting multiple parameters in the same group, the group name doesn't +have to be repeated if it is followed by the parameters in curly braces. +Example: +.nf +.sp + debug { + level warn + dump /var/tmp + log syslog + trace 100 + } +.sp +.fi +.P +Line breaks can be inserted in \fBatmsigd.conf\fP wherever spaces or tabs +are allowed. Everything between a `#' and the end of the line is considered +a comment. The `#' character cannot be escaped. +.P +If an option is specified in \fBatmsigd.conf\fP and on the command +line, the command line has priority. +.COMPATIBILITY +For historical reasons, synonyms (e.g. abbreviated or long forms) exist for +most keywords. Future versions of \fBatmsigd\fP will only recognize the +syntax described on this man page. +.SH AUTHOR +Werner Almesberger, EPFL ICA +.SH "SEE ALSO" +atmsigd(8), qos(7), syslogd(8) +.\"{{{}}} diff -ur --new-file old/atm/sigd.old/cfg.l new/atm/sigd.old/cfg.l --- old/atm/sigd.old/cfg.l Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/cfg.l Thu Aug 20 18:04:24 1998 @@ -0,0 +1,100 @@ +%{ +/* cfg.l - configuration language */ + +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ + + +#include +#include +#include +#include + +#include "atm.h" + +#include "y.tab.h" + + +static int lineno = 1; +static int token; /* f@#%ing flex doesn't grok return after BEGIN */ + + +void yyerror(const char *s); +void yywarn(const char *s); + +%} + +%s N +%s P + +%% + BEGIN(N); + +level return TOK_LEVEL; +debug return TOK_DEBUG; +info return TOK_INFO; +warn return TOK_WARN; +error return TOK_ERROR; +fatal return TOK_FATAL; +sig return TOK_SIG; +uni30 return TOK_UNI30; +uni31 return TOK_UNI31; +uni40 return TOK_UNI40; +[qQ].2963.1 return TOK_Q2963_1; +mode return TOK_MODE; +user return TOK_USER; +network return TOK_NET; +switch return TOK_SWITCH; +saal return TOK_SAAL; +vc return TOK_VC; +io return TOK_IO; +itf return TOK_ITF; +vpci return TOK_VPCI; +pcr return TOK_PCR; +policy return TOK_POLICY; +allow return TOK_ALLOW; +reject return TOK_REJECT; +dump { BEGIN(P); + token = TOK_DUMP_DIR; } +log { BEGIN(P); + token = TOK_LOGFILE; } +qos { BEGIN(P); /* syntacticly close to a path */ + token = TOK_QOS; } +from { BEGIN(P); /* syntacticly close to a path */ + token = TOK_FROM; } +to { BEGIN(P); /* syntacticly close to a path */ + token = TOK_TO; } +trace return TOK_TRACE; +[0-9]+ { char *end; + yylval.num = strtoul(yytext,&end,10); + if (*end) yyerror("invalid number"); + return TOK_NUMBER; } +[0-9]+\.[0-9]+(\.[0-9]+)? { + if (text2atm(yytext,(struct sockaddr *) &yylval.pvc, + sizeof(yylval.pvc),T2A_PVC) < 0) + yyerror("invalid signaling channel"); + return TOK_PVC; + } +

[^\t\n ]+ { BEGIN(N); + yylval.str = strdup(yytext); /* tiny leak ... */ + if (!yylval.str) { + perror("strdup"); + exit(1); + } + return token; } +\n?[\t ]* lineno += *yytext == '\n'; +#[^\n]*\n lineno++; +. return *yytext; + +%% + +void yywarn(const char *s) +{ + fprintf(stderr,"line %d: %s near \"%s\"\n",lineno,s,yytext); +} + + +void yyerror(const char *s) +{ + yywarn(s); + exit(1); +} diff -ur --new-file old/atm/sigd.old/cfg.y new/atm/sigd.old/cfg.y --- old/atm/sigd.old/cfg.y Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/cfg.y Thu Aug 20 18:04:24 1998 @@ -0,0 +1,301 @@ +%{ +/* cfg.y - configuration language */ + +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ + + +#include +#include + +#include "atm.h" +#include "atmd.h" + +#include "proto.h" +#include "io.h" +#include "trace.h" +#include "policy.h" + + +static RULE *rule; + + +static int hex2num(char digit) +{ + if (isdigit(digit)) return digit-'0'; + if (islower(digit)) return toupper(digit)-'A'+10; + return digit-'A'+10; +} + + +static void put_address(char *address) +{ + char *mask; + + mask = strchr(address,'/'); + if (mask) *mask++ = 0; + if (text2atm(address,(struct sockaddr *) &rule->addr,sizeof(rule->addr), + T2A_SVC | T2A_WILDCARD | T2A_NAME | T2A_LOCAL) < 0) { + yyerror("invalid address"); + return; + } + if (!mask) rule->mask = -1; + else rule->mask = strtol(mask,NULL,10); + add_rule(rule); +} + +%} + +%union { + int num; + char *str; + struct sockaddr_atmpvc pvc; +}; + + +%token TOK_LEVEL TOK_DEBUG TOK_INFO TOK_WARN TOK_ERROR TOK_FATAL +%token TOK_SIG TOK_UNI30 TOK_UNI31 TOK_UNI40 TOK_Q2963_1 TOK_SAAL +%token TOK_VC TOK_IO TOK_MODE TOK_USER TOK_NET TOK_SWITCH TOK_VPCI +%token TOK_ITF TOK_PCR TOK_TRACE TOK_POLICY TOK_ALLOW TOK_REJECT +%token TOK_NUMBER +%token TOK_DUMP_DIR TOK_LOGFILE TOK_QOS TOK_FROM TOK_TO +%token TOK_PVC + +%type level opt_trace_size action + +%% + +all: + | item all + ; + +item: + TOK_LEVEL level + { + set_verbosity(NULL,$2); + } + | TOK_SIG sig + | TOK_SAAL saal + | TOK_IO io + | TOK_DEBUG debug + | TOK_POLICY policy + ; + +sig: + sig_item + | '{' sig_items '}' + ; + +sig_items: + | sig_item sig_items + ; + +saal: + saal_item + | '{' saal_items '}' + ; + +saal_items: + | saal_item saal_items + ; + +io: + io_item + | '{' io_items '}' + ; + +io_items: + | io_item io_items + ; + +debug: + debug_item + | '{' debug_items '}' + ; + +debug_items: + | debug_item debug_items + ; + +policy: + policy_item + | '{' policy_items '}' + ; + +policy_items: + | policy_item policy_items + ; + +sig_item: + TOK_LEVEL level + { + set_verbosity("UNI",$2); + set_verbosity("KERNEL",$2); + set_verbosity("SAP",$2); + } + | TOK_VPCI TOK_NUMBER TOK_ITF TOK_NUMBER + { + enter_vpci($2,$4); + } + | TOK_UNI30 + { +#ifndef UNI30 + yyerror("Sorry, not supported yet"); +#endif + } + | TOK_UNI31 + { +#ifndef UNI31 + yyerror("Sorry, not supported yet"); +#endif + } + | TOK_UNI40 + { +#ifndef UNI40 + yyerror("Sorry, not supported yet"); +#endif + } + | TOK_Q2963_1 + { +#ifndef Q2963_1 + yyerror("Sorry, not supported yet"); +#endif + } + | TOK_NET + { + yywarn("sig net is obsolete, please use sig mode net instead"); + net = 1; + } + | TOK_MODE mode + ; + +saal_item: + TOK_LEVEL level + { + set_verbosity("SSCF",$2); + set_verbosity("SSCOP",$2); + } + ; + +io_item: + TOK_LEVEL level + { + set_verbosity("IO",$2); + } + | TOK_VC TOK_PVC + { + signaling_pvc = $2; + } + | TOK_PCR TOK_NUMBER + { + sig_pcr = $2; + } + | TOK_QOS + { + sig_qos = $1; + } + ; + +debug_item: + TOK_LEVEL level + { + set_verbosity(NULL,$2); + } + | TOK_DUMP_DIR + { + dump_dir = $1; + if (!trace_size) trace_size = DEFAULT_TRACE_SIZE; + } + | TOK_LOGFILE + { + set_logfile($1); + } + | TOK_TRACE opt_trace_size + { + trace_size = $2; + } + ; + +opt_trace_size: + { + $$ = DEFAULT_TRACE_SIZE; + } + | TOK_NUMBER + { + $$ = $1; + } + ; + +level: + TOK_DEBUG + { + $$ = DIAG_DEBUG; + } + | TOK_INFO + { + $$ = DIAG_INFO; + } + | TOK_WARN + { + $$ = DIAG_WARN; + } + | TOK_ERROR + { + $$ = DIAG_ERROR; + } + | TOK_FATAL + { + $$ = DIAG_FATAL; + } + ; + +mode: + TOK_USER + { + mode = sm_user; + } + | TOK_NET + { + mode = sm_net; + } + | TOK_SWITCH + { + mode = sm_switch; + } + ; + +policy_item: + TOK_LEVEL level + { + set_verbosity("POLICY",$2); + } + | action + { + rule = alloc_t(RULE); + rule->type = $1; + } + direction + ; + +action: + TOK_ALLOW + { + $$ = ACL_ALLOW; + } + | TOK_REJECT + { + $$ = ACL_REJECT; + } + ; + +direction: + TOK_FROM + { + rule->type |= ACL_IN; + put_address($1); + } + | TOK_TO + { + rule->type |= ACL_OUT; + put_address($1); + } + ; diff -ur --new-file old/atm/sigd.old/io.c new/atm/sigd.old/io.c --- old/atm/sigd.old/io.c Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/io.c Wed Sep 23 20:02:07 1998 @@ -0,0 +1,354 @@ +/* io.c - I/O operations */ + +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* linux/atmsvc.h includes linux/atm.h */ +#include + +#include "atm.h" +#include "atmd.h" +#include "uni.h" +#include "pdu.h" + +#include "proto.h" +#include "io.h" +#include "trace.h" + + +#define COMPONENT "IO" + + +struct timeval now; +struct sockaddr_atmpvc signaling_pvc; + +int stop = 0; + +static int kernel = -1,signaling; +static int need_connect = 0; /* non-zero if connection to kernel isn't + bi-directional yet */ + + +/* ----- kernel interface -------------------------------------------------- */ + + +static int open_kernel(void) +{ + int s; + + if ((s = socket(PF_ATMSVC,SOCK_DGRAM,0)) < 0) { + perror("socket"); + return -1; + } + if (ioctl(s,ATMSIGD_CTRL,0) < 0) { + perror("ioctl ATMSIGD_CTRL"); + return -1; + } + return s; +} + + +void open_unix(const char *path) +{ + kernel = un_create(path,0600); + if (kernel < 0) + diag(COMPONENT,DIAG_FATAL,"un_create %s: %s",path,strerror(errno)); + need_connect = 1; +} + + +static void recv_kernel(void) +{ + static unsigned char buffer[sizeof(struct atmsvc_msg)+1]; + int size; + + if (!need_connect) size = read(kernel,buffer,sizeof(buffer)); + else { + size = un_recv_connect(kernel,buffer,sizeof(buffer)); + need_connect = 0; + } + if (size < 0) { + diag(COMPONENT,DIAG_ERROR,"read kernel: %s",strerror(errno)); + return; + } + if (size != sizeof(struct atmsvc_msg)) + diag(COMPONENT,DIAG_FATAL,"kernel message size %d != %d",size, + sizeof(struct atmsvc_msg)); + trace_kernel("FROM KERNEL",(struct atmsvc_msg *) buffer); + from_kernel((struct atmsvc_msg *) buffer,size); +} + + +void to_kernel(struct atmsvc_msg *msg) +{ + int wrote; + + diag("KERNEL",DIAG_DEBUG,"TO KERNEL: %s (%d) for 0x%lx/0x%lx", + as_name[msg->type],msg->reply,msg->vcc,msg->listen_vcc); + /* should be "IO" ... */ + trace_kernel("TO KERNEL",msg); + wrote = write(kernel,msg,sizeof(*msg)); + if (wrote == sizeof(*msg)) return; + if (wrote < 0) { + perror("kernel write"); + return; + } + diag(COMPONENT,DIAG_ERROR,"bad kernel write: wanted %d, wrote %d", + sizeof(*msg),wrote); +} + + +static void close_kernel(void) +{ + (void) close(kernel); /* may get major complaints from the kernel ... */ +} + + +/* ----- signaling interface ----------------------------------------------- */ + + +static int open_signaling(void) +{ + struct atm_qos qos; + int s; + + if ((s = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) { + perror("socket"); + return -1; + } + memset(&qos,0,sizeof(qos)); + qos.aal = ATM_AAL5; + qos.rxtp.max_sdu = qos.txtp.max_sdu = MAX_Q_MSG; + if (sig_qos) { + if (text2qos(sig_qos,&qos,T2Q_DEFAULTS) < 0) { + fprintf(stderr,"invalid qos: %s\n",sig_qos); + return -1; + } + } + else { + if (sig_pcr == -1) + qos.rxtp.traffic_class = qos.txtp.traffic_class = ATM_UBR; + else { + qos.rxtp.traffic_class = qos.txtp.traffic_class = ATM_CBR; + qos.rxtp.min_pcr = qos.txtp.min_pcr = sig_pcr; + } + } + if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { + perror("setsockopt SO_ATMQOS"); + return -1; + } + signaling_pvc.sap_family = AF_ATMPVC; + if (bind(s,(struct sockaddr *) &signaling_pvc,sizeof(signaling_pvc)) < 0) { + perror("bind"); + return -1; + } + return s; +} + + +static void recv_signaling(void) +{ + static unsigned char buffer[MAX_Q_MSG]; + int size; + + size = read(signaling,buffer,MAX_Q_MSG); + if (size < 1) { + perror("read signaling"); + return; + } + diag(COMPONENT,DIAG_DEBUG,"FROM NET: %s PDU (%d bytes)", + pdu_name[size > 3 && !(size & 3) ? buffer[size-4] & 0xf : 0],size); + if (debug) diag_dump(COMPONENT,DIAG_DEBUG,NULL,buffer,size); + from_net(buffer,size); +} + + +void to_net(void *msg,int size) +{ + int wrote; + + diag(COMPONENT,DIAG_DEBUG,"TO NET: %s PDU (%d bytes)", + pdu_name[size > 3 && !(size & 3) ? ((unsigned char *) msg)[size-4] & 0xf + : 0],size); + if (debug) diag_dump(COMPONENT,DIAG_DEBUG,NULL,msg,size); + wrote = write(signaling,msg,size); + if (wrote == size) return; + if (wrote < 0) { + perror("signaling write"); + return; + } + diag(COMPONENT,DIAG_WARN,"bad signaling write: wanted %d, wrote %d",size, + wrote); +} + + +static void close_signaling(void) +{ + (void) close(signaling); +} + + +/* ----- addresses --------------------------------------------------------- */ + + +LOCAL_ADDR local_addr[MAX_ADDRS+1]; + + +int get_addr(int itf) +{ + struct atmif_sioc req; + struct sockaddr_atmsvc buffer[MAX_ADDRS]; + LOCAL_ADDR *from,*to; + int addrs,i; + + for (from = to = local_addr; from->state != ls_unused; from++) + if (from->state != ls_removed) { + from->state = itf == from->itf ? ls_removed : ls_same; + *to++ = *from; + } + req.number = itf; + req.arg = buffer; + req.length = sizeof(buffer); + if (ioctl(signaling,ATM_GETADDR,&req) < 0) + diag(COMPONENT,DIAG_FATAL,"ioctl ATM_GETADDR yields \"%s\"", + strerror(errno)); + addrs = req.length/sizeof(struct sockaddr_atmsvc); + for (i = 0; i < addrs; i++) { + for (from = local_addr; from->state != ls_unused; from++) + if (from->itf == itf && atm_equal((struct sockaddr *) (buffer+i), + (struct sockaddr *) &from->addr,0,0)) break; + if (from->state != ls_unused) from->state = ls_same; + else if (to == local_addr+MAX_ADDRS-1) + diag(COMPONENT,DIAG_WARN,"local address table overflow"); + else { + to->state = ls_added; + to->itf = itf; + to->addr = buffer[i]; + to++; + } + } + to->state = ls_unused; + return addrs; +} + + +/* ----- common part ------------------------------------------------------- */ + + +int open_all(void) +{ + if (kernel == -1) kernel = open_kernel(); + if (kernel < 0) return -1; + signaling = open_signaling(); + if (signaling < 0) { + close_kernel(); + return -1; + } + local_addr[0].state = ls_unused; + return 0; +} + + +void close_all(void) +{ + close_kernel(); + close_signaling(); +} + + +void init_current_time(void) +{ + gettimeofday(&now,NULL); +} + + +void poll_loop(void) +{ + fd_set perm,set; + int fds,ret; + + FD_ZERO(&perm); + FD_SET(kernel,&perm); + FD_SET(signaling,&perm); + fds = kernel > signaling ? kernel+1 : signaling+1; + gettimeofday(&now,NULL); + while (!stop) { + set = perm; + poll_signals(); + /* + * Here we have a small race condition: if a signal is delivered after + * poll_signals tests for it but before select sleeps, we miss that + * signal. If it is sent again, we're of course likely to get it. This + * isn't worth fixing, because those signals are only used for + * debugging anyway. + */ + ret = select(fds,&set,NULL,NULL,next_timer()); + if (ret < 0) { + if (errno != EINTR) perror("select"); + } + else { + diag(COMPONENT,DIAG_DEBUG,"----------"); + gettimeofday(&now,NULL); + if (FD_ISSET(kernel,&set)) recv_kernel(); + if (FD_ISSET(signaling,&set)) recv_signaling(); + expire_timers(); + /* expire timers after handling messges to make sure we don't + time out unnecessarily because of scheduling delays */ + } + } +} + + +/* + * The allocation strategy could be improved as follows: we should try + * vci = prev_vci++ first and only resort to ATM_VCI_ANY if that fails several + * times (and we should actually skip over those which are in use by SVCs. This + * way we avoid using VCIs that just became available. Doing it "right" seems + * to be getting complex, though. + */ + + +int get_pvc(int itf,int *vci) +{ + struct sockaddr_atmpvc addr; + struct atm_qos qos; + int s,error; + + if ((s = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) + diag(COMPONENT,DIAG_FATAL,"get_pvc: %s",strerror(errno)); + memset(&qos,0,sizeof(qos)); + qos.aal = ATM_AAL5; + qos.rxtp.traffic_class = qos.txtp.traffic_class = ATM_UBR; + qos.rxtp.max_sdu = qos.txtp.max_sdu = 1; /* smallest possible SDU size */ + if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) + diag(COMPONENT,DIAG_FATAL,"setsockopt SO_ATMQOS: %s",strerror(errno)); + memset(&addr,0,sizeof(addr)); + addr.sap_family = AF_ATMPVC; + addr.sap_addr.itf = itf; + addr.sap_addr.vpi = 0; /* @@@ */ + addr.sap_addr.vci = ATM_VCI_ANY; + error = 0; + if (bind(s,(struct sockaddr *) &addr,sizeof(addr)) < 0) error = errno; + else { + int size; + + size = sizeof(addr); + if (getsockname(s,(struct sockaddr *) &addr,&size) < 0) + diag(COMPONENT,DIAG_FATAL,"get_pvc: %s",strerror(errno)); + *vci = addr.sap_addr.vci; + return s; + } + (void) close(s); + return -error; +} diff -ur --new-file old/atm/sigd.old/io.h new/atm/sigd.old/io.h --- old/atm/sigd.old/io.h Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/io.h Thu Aug 20 18:04:24 1998 @@ -0,0 +1,41 @@ +/* io.h - I/O operations */ + +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ + + +#ifndef IO_H +#define IO_H + +#include +#include +#include + + +#define MAX_ADDRS 128 + + +typedef struct { + enum { ls_unused,ls_added,ls_removed,ls_same } state; + int itf; + struct sockaddr_atmsvc addr; +} LOCAL_ADDR; + + +extern LOCAL_ADDR local_addr[]; +extern struct sockaddr_atmpvc signaling_pvc; + + +int open_all(void); +void open_unix(const char *name); +void init_current_time(void); +void poll_loop(void); +void close_all(void); + +void to_kernel(struct atmsvc_msg *msg); +void to_net(void *msg,int size); + +int get_addr(int itf); + +int get_pvc(int itf,int *vci); + +#endif diff -ur --new-file old/atm/sigd.old/kernel.c new/atm/sigd.old/kernel.c --- old/atm/sigd.old/kernel.c Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/kernel.c Mon Sep 7 15:37:16 1998 @@ -0,0 +1,571 @@ +/* kernel.c - Processing of incoming kernel messages */ + +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ + + +#include +#include +#include +#include +#include /* linux/atmsvc.h includes linux/atm.h */ +#include +#include + +#include "atm.h" +#include "atmd.h" +#include "uni.h" +#include "qlib.h" +#include + +#include "proto.h" +#include "sap.h" +#include "io.h" +#include "policy.h" +#include "timeout.h" + + +#define COMPONENT "KERNEL" + + +static int send_setup(SOCKET *sock) +{ + static unsigned long call_ref = 0; + struct sockaddr_atmsvc *local; + SOCKET *walk; + Q_DSC dsc; + int error,size; + + do { + if (++call_ref == 0x7fffff) call_ref = 1; + for (walk = sockets; walk; walk = walk->next) + if (walk->call_ref == call_ref) break; + } + while (walk); + sock->call_ref = call_ref; + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_call_ref,call_ref); + q_assign(&dsc,QF_msg_type,ATM_MSG_SETUP); + q_assign(&dsc,QF_aal_type,5); /* AAL 5 */ +#ifdef UNI30 + q_assign(&dsc,QF_aal_mode,1); /* Message mode - LANE seems to really want + this */ +#endif + q_assign(&dsc,QF_sscs_type,0); /* unspecified - LANE wants this */ + error = sap_encode(&dsc,&sock->remote,&sock->sap,&sock->qos); + q_assign(&dsc,QF_bearer_class,16); /* BCOB-X */ +#if defined(UNI30) || defined(ALLOW_UNI30) + q_assign(&dsc,QF_trans_cap,ATM_TC_VBR_NRT_R00); + /* force presence - UNI 3.0 wants this */ +#endif + q_assign(&dsc,QF_upcc,0); /* p2p */ +#ifndef UNI30 + q_assign(&dsc,QF_qos_cs,Q2931_CS_ITU); +#endif + q_assign(&dsc,QF_qos_fw,0); /* QOS 0 */ + q_assign(&dsc,QF_qos_bw,0); + local = NULL; + if (atmsvc_addr_in_use(sock->local)) local = &sock->local; + else if (local_addr[0].state == ls_same && + atmsvc_addr_in_use(local_addr[0].addr)) + local = &local_addr[0].addr; + if (!local) { + if (!error) error = -EADDRNOTAVAIL; + } + else if (*local->sas_addr.pub) { + q_assign(&dsc,QF_cgpn_plan,ATM_NP_E164); + q_assign(&dsc,QF_cgpn_type,ATM_TON_INTRNTNL); + q_write(&dsc,QF_cgpn,(void *) local->sas_addr.pub, + strlen(local->sas_addr.pub)); + } + else { + q_assign(&dsc,QF_cgpn_plan,ATM_NP_AEA); + q_assign(&dsc,QF_cgpn_type,ATM_TON_UNKNOWN); + q_write(&dsc,QF_cgpn,(void *) local->sas_addr.prv,ATM_ESA_LEN); + } + if (net) { + if (!atmpvc_addr_in_use(sock->pvc)) { + int vci; + + if (!allocate_ci) + diag(COMPONENT,DIAG_FATAL,"No CI allocator (use -A)"); + vci = get_vci(0); + if (vci < 0) { + (void) q_close(&dsc); + return vci; + } + sock->pvc.sap_addr.itf = get_itf(0); + sock->pvc.sap_addr.vpi = 0; + sock->pvc.sap_addr.vci = vci; + } + q_assign(&dsc,QF_vpi,sock->pvc.sap_addr.vpi); + q_assign(&dsc,QF_vci,sock->pvc.sap_addr.vci); + } + if ((size = q_close(&dsc)) < 0) error = -EINVAL; + else if (!error) to_signaling(q_buffer,size); + return error; +} + + +static int send_connect(SOCKET *sock) +{ + Q_DSC dsc; + int size; + + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_msg_type,ATM_MSG_CONNECT); + q_assign(&dsc,QF_call_ref,sock->call_ref); + if (sock->ep_ref >= 0) q_assign(&dsc,QF_ep_ref,sock->ep_ref); + if (sock->ep_ref <= 0) { /* no AAL parameters if ep_ref present and != 0 */ + q_assign(&dsc,QF_aal_type,5); +#ifdef UNI30 + q_assign(&dsc,QF_aal_mode,1); /* Message mode - LANE seems to really + want this */ +#endif + q_assign(&dsc,QF_sscs_type,0); /* unspecified - LANE wants this */ + q_assign(&dsc,QF_fw_max_sdu,sock->qos.rxtp.max_sdu); + q_assign(&dsc,QF_bw_max_sdu,sock->qos.txtp.max_sdu); + } + if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + return 0; +} + + +#ifdef Q2963_1 + +static void send_modify_request(SOCKET *sock) +{ + Q_DSC dsc; + int size; + + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_msg_type,ATM_MSG_MODIFY_REQ); + q_assign(&dsc,QF_call_ref,sock->call_ref); + if (sock->new_qos.txtp.traffic_class) + q_assign(&dsc,QF_fw_pcr_01,SELECT_TOP_PCR(sock->new_qos.txtp)); + if (sock->new_qos.rxtp.traffic_class) + q_assign(&dsc,QF_bw_pcr_01,SELECT_TOP_PCR(sock->new_qos.rxtp)); + if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); +} + + +static void send_modify_ack(SOCKET *sock) +{ + Q_DSC dsc; + int size; + + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_msg_type,ATM_MSG_MODIFY_ACK); + q_assign(&dsc,QF_call_ref,sock->call_ref); + if (sock->qos.rxtp.traffic_class != ATM_NONE && + sock->qos.rxtp.max_pcr < sock->new_qos.rxtp.max_pcr) { + q_assign(&dsc,QF_type_of_report,ATM_TOR_MOD_CONF); + START_TIMER(sock,T361); + } + if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); +} + +#endif + + +static int bind_check(SOCKET *sock,struct sockaddr_atmsvc *local) +{ + struct sockaddr_atmsvc *use; + + if (atmsvc_addr_in_use(sock->local)) return 0; + if (atmsvc_addr_in_use(*local)) use = local; + else { + if (local_addr[0].state != ls_same) { + diag(COMPONENT,DIAG_ERROR,"no local address"); + return -EADDRNOTAVAIL; + } + use = &local_addr[0].addr; + } + sock->local = *use; + return 0; +} + + +static void dispatch(SOCKET *sock,struct atmsvc_msg *msg) +{ + int error; + + switch (msg->type) { + case as_bind: /* only in NULL state */ + if (sock) break; + if (msg->svc.sas_family != AF_ATMSVC) { + SEND_ERROR(msg->vcc,-EAFNOSUPPORT); + return; + } + if (!atmsvc_addr_in_use(msg->svc)) +#ifdef BE_PICKY_ABOUT_BINDING_LOCAL_WILDCARD_ADDRESSES + if (local_addr[0].state != ls_same) + SEND_ERROR(msg->vcc,-EADDRNOTAVAIL); + else +#endif + send_kernel(msg->vcc,0,as_okay,0,NULL,NULL, + &local_addr[0].addr,NULL,NULL); + else { + LOCAL_ADDR *walk; + + for (walk = local_addr; walk->state != ls_unused; walk++) + if (walk->state == ls_same && + atm_equal((struct sockaddr *) &walk->addr, + (struct sockaddr *) &msg->svc,(ATM_ESA_LEN-1)*8, + AXE_WILDCARD)) break; + if(*msg->svc.sas_addr.pub) + diag(COMPONENT,DIAG_DEBUG,"binding to E.164 address " + "%s\n",msg->svc.sas_addr.pub); + if (walk->state == ls_unused) + SEND_ERROR(msg->vcc,-EADDRNOTAVAIL); + else send_kernel(msg->vcc,0,as_okay,0,NULL,NULL,NULL,NULL,NULL); + } + return; + case as_connect: /* NULL state only */ + if (sock) break; + if (!allow(&msg->svc,ACL_OUT)) { + SEND_ERROR(msg->vcc,-EACCES); + return; + } + sock = new_sock(msg->vcc); + error = bind_check(sock,&msg->local); + if (error) { + free_sock(sock); + SEND_ERROR(msg->vcc,error); + return; + } + sock->remote = msg->svc; + sock->qos = msg->qos; + sock->sap = msg->sap; + sock->state = ss_connecting; + sock->pvc = msg->pvc; + error = send_setup(sock); + if (error) { + SEND_ERROR(msg->vcc,error); + free_sock(sock); + return; + } + START_TIMER(sock,T303); + new_state(sock,ss_connecting); + return; + case as_accept: + if (sock->state == ss_zombie) { + SEND_ERROR(msg->vcc,-ECONNABORTED); /* -ERESTARTSYS ? */ + free_sock(sock); + return; + } + if (sock->state != ss_indicated && sock->state != ss_proceeding) + break; + if (sock->state == ss_indicated && net) + diag(COMPONENT,DIAG_FATAL,"No CI allocator (use -A)"); + error = send_connect(sock); + if (!error) { + START_TIMER(sock,T313); + new_state(sock,ss_accepting); + return; + } + SEND_ERROR(sock->id,error); + send_release(sock,0); /* @@@ */ + START_TIMER(sock,T308_1); + new_state(sock,ss_wait_rel); + return; + case as_reject: /* ZOMBIE, INDICATED, or PROCEEDING */ + switch (sock->state) { + case ss_indicated: + send_release_complete(sock->call_ref,ATM_CV_CALL_REJ); + /* fall through */ + case ss_zombie: + free_sock(sock); + return; + case ss_proceeding: + send_release(sock,ATM_CV_CALL_REJ); + /* @@@ should use msg->reply */ + START_TIMER(sock,T308_1); + new_state(sock,ss_wait_rel); + return; + default: + break; + } + break; + case as_listen: /* NULL */ + if (sock) break; + if (msg->svc.sas_family != AF_ATMSVC) { + SEND_ERROR(msg->vcc,-EAFNOSUPPORT); + return; + } + if (msg->qos.aal != ATM_AAL5) { + SEND_ERROR(msg->vcc,-EINVAL); + return; + } + if (lookup_sap(&msg->svc,&msg->sap,&msg->qos,NULL,NULL,NULL,1)) { + SEND_ERROR(msg->vcc,-EADDRINUSE); + return; + } + sock = new_sock(msg->vcc); + sock->local = msg->svc; + sock->sap = msg->sap; + sock->qos = msg->qos; + send_kernel(sock->id,0,as_okay,0,NULL,NULL,NULL,NULL,NULL); + sock->state = ss_listening; + return; + case as_close: /* all but INDICATED, PROCEEDING, ZOMBIE, and WAIT_REL */ + if (sock && (sock->state == ss_indicated || + sock->state == ss_proceeding || sock->state == ss_zombie || + sock->state == ss_wait_rel)) break; + switch (sock ? sock->state : ss_null) { + case ss_listening: + send_close(sock); + if (sock->listen) new_state(sock,ss_listen_zombie); + else free_sock(sock); + return; + case ss_zombie: + send_close(sock); + /* fall through */ + case ss_wait_close: + free_sock(sock); + /* fall through */ + case ss_null: + case ss_rel_req: + return; + case ss_connecting: + case ss_accepting: +#ifdef Q2963_1 + case ss_mod_req: +#endif + STOP_TIMER(sock); + /* fall through */ +#ifdef Q2963_1 + case ss_mod_lcl: + case ss_mod_rcv: + case ss_mod_fin_ok: + case ss_mod_fin_fail: + case ss_mod_fin_ack: +#endif + case ss_connected: +#ifdef Q2963_1 + if (timer_handler(sock->conn_timer) == on_T361) + STOP_TIMER(sock); +#endif + if (sock->state == ss_connected) + diag(COMPONENT,DIAG_INFO,"Active close (CR 0x%06X)", + sock->call_ref); + send_release(sock, +#if defined(UNI31) || defined(UNI40) + ATM_CV_NORMAL_CLEAR +#else + ATM_CV_NORMAL_UNSPEC +#endif + ); + START_TIMER(sock,T308_1); + new_state(sock,ss_rel_req); + return; + case ss_rel_ind: + send_release_complete(sock->call_ref,0); /* @@@ */ + free_sock(sock); + return; + default: + break; + } + break; + case as_identify: + if (sock->state != ss_indicated && sock->state != ss_proceeding) + break; + if (!atmpvc_addr_in_use(msg->pvc)) { + if (net && !allocate_ci) + diag(COMPONENT,DIAG_FATAL,"No CI allocator (use -A)"); + return; + } + if (net && allocate_ci) + diag(COMPONENT,DIAG_FATAL,"CI allocation role conflict"); + sock->pvc = msg->pvc; + if (send_call_proceeding(sock)) + diag(COMPONENT,DIAG_FATAL,"s_c_p failed"); + new_state(sock,ss_proceeding); + return; +#ifdef Q2963_1 + case as_modify: + if (sock && (sock->state == ss_mod_lcl || + sock->state == ss_mod_req || sock->state == ss_mod_rcv || + sock->state == ss_mod_fin_ok || sock->state == ss_mod_fin_fail || + sock->state == ss_mod_fin_ack)) { + send_kernel(sock->id,0,as_okay,-EALREADY,NULL,NULL,NULL,NULL, + NULL); + return; + } + if (!sock || sock->state != ss_connected || !sock->owner) { + send_kernel(sock->id,0,as_okay,-EBADFD,NULL,NULL,NULL,NULL, + NULL); + return; + } + if (sock->qos.txtp.traffic_class != msg->qos.txtp.traffic_class || + sock->qos.rxtp.traffic_class != msg->qos.rxtp.traffic_class) { + /* @@@ may do more checking */ + send_kernel(sock->id,0,as_okay,-EINVAL,NULL,NULL,NULL,NULL, + NULL); + return; + } + sock->new_qos = msg->qos; + send_kernel(sock->id,0,as_modify,ATM_MF_INC_RSV | ATM_MF_DEC_SHP, + NULL,NULL,NULL,NULL,&msg->qos); + new_state(sock,ss_mod_lcl); + return; + case as_okay: + switch (sock ? sock->state : ss_null) { + case ss_mod_lcl: + send_modify_request(sock); + START_TIMER(sock,T360); + new_state(sock,ss_mod_req); + return; + case ss_mod_rcv: + send_modify_ack(sock); + sock->qos = sock->new_qos; + new_state(sock,ss_connected); + return; + case ss_mod_fin_ok: + send_kernel(sock->id,0,as_okay,0,NULL,NULL,NULL,NULL,NULL); + new_state(sock,ss_connected); + return; + case ss_mod_fin_fail: + send_kernel(sock->id,0,as_okay,sock->error,NULL,NULL,NULL, + NULL,NULL); + sock->error = 0; + /* fall through */ + case ss_mod_fin_ack: + new_state(sock,ss_connected); + /* fall through */ + default: + return; /* ignore stray as_okay */ + } + case as_error: + switch (sock ? sock->state : ss_null) { + case ss_mod_lcl: + send_kernel(sock->id,0,as_okay,msg->reply,NULL,NULL,NULL, + NULL,NULL); + new_state(sock,ss_connected); + return; + case ss_mod_rcv: + send_modify_reject(sock,ATM_CV_RES_UNAVAIL); + new_state(sock,ss_connected); + return; + case ss_mod_fin_ok: + diag(COMPONENT,DIAG_ERROR,"QOS commit failed"); + send_kernel(sock->id,0,as_okay,0,NULL,NULL,NULL,NULL,NULL); + /* @@@ clear call instead ? */ + new_state(sock,ss_connected); + return; + case ss_mod_fin_fail: + diag(COMPONENT,DIAG_ERROR,"QOS rollback failed"); + send_kernel(sock->id,0,as_okay,sock->error,NULL,NULL,NULL, + NULL,NULL); + sock->error = 0; + /* @@@ clear call instead ? */ + new_state(sock,ss_connected); + return; + case ss_mod_fin_ack: + /* @@@ maybe we should even clear the call now */ + diag(COMPONENT,DIAG_ERROR,"QOS commit failed"); + new_state(sock,ss_connected); + return; + default: + return; /* ignore stray as_error */ + } +#endif + default: + diag(COMPONENT,DIAG_WARN,"invalid message %d",(int) msg->type); + return; + } + diag(COMPONENT,DIAG_WARN,"message %s is incompatible with state %s (%d)", + as_name[msg->type],state_name[sock ? sock->state : ss_null], + (int) (sock ? sock->state : ss_null)); +} + + +static void dispatch_listen(SOCKET *sock,struct atmsvc_msg *msg) +{ + SOCKET *next; + + if (!sock) { + diag(COMPONENT,DIAG_WARN,"message %s is incompatible with state %s " + "(%d)",as_name[msg->type],state_name[ss_null],ss_null); + return; + } + if (!(next = sock->listen)) { + diag(COMPONENT,DIAG_WARN, + "socket 0x%lx got accept/reject/identify with empty listen queue", + msg->vcc); + return; + } + sock->listen = next->listen; + if (sock->state == ss_listen_zombie && !sock->listen) free_sock(sock); + next->listen = NULL; + next->id = msg->vcc; + dispatch(next,msg); +} + + +void itf_load(int itf) +{ + char buf[MAX_ATM_ADDR_LEN+1]; + LOCAL_ADDR *walk; + + (void) get_addr(itf); + for (walk = local_addr; walk->state != ls_unused; walk++) + if (walk->itf == itf) { + if (atm2text(buf,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) + &walk->addr,pretty) < 0) strcpy(buf,""); + switch (walk->state) { + case ls_added: + diag(COMPONENT,DIAG_INFO,"Added local ATM address %s at " + "itf %d",buf,itf); + walk->state = ls_same; + break; + case ls_removed: + diag(COMPONENT,DIAG_INFO,"Removed local ATM address %s at " + "itf %d",buf,itf); + walk->state = ls_unused; + /* @@@ delete SVCs using that address ? */ + break; + default: + break; + } + } +} + + +void from_kernel(struct atmsvc_msg *msg,int size) +{ + void (*dispatcher)(SOCKET *,struct atmsvc_msg *); + SOCKET *curr; + + if (msg->type == as_itf_notify) { + itf_load(msg->pvc.sap_addr.itf); + return; + } + if (msg->type == as_terminate) { + if (mode != sm_switch) { + diag(COMPONENT,DIAG_ERROR,"Ignoring as_terminate received in %s " + "mode",mode == sm_user ? "USER" : "NETWORK"); + return; + } + clear_all_calls(); + stop = 1; + diag(COMPONENT,DIAG_INFO,"Going down on as_terminate"); + return; + } + if (msg->listen_vcc && (msg->type == as_accept || msg->type == as_reject || + msg->type == as_identify)) { + dispatcher = dispatch_listen; + for (curr = sockets; curr; curr = curr->next) + if (msg->listen_vcc == curr->id && (curr->state == ss_listening || + curr->state == ss_listen_zombie)) + break; + } + else { + dispatcher = dispatch; + for (curr = sockets; curr; curr = curr->next) + if (msg->vcc == curr->id) break; + } + diag(COMPONENT,DIAG_DEBUG,"FROM KERNEL: %s for socket %p (0x%lx/0x%lx) " + "in state %s",as_name[msg->type],curr,msg->vcc,msg->listen_vcc, + state_name[curr ? curr->state : ss_null]); + dispatcher(curr,msg); +} diff -ur --new-file old/atm/sigd.old/mkmess.pl new/atm/sigd.old/mkmess.pl --- old/atm/sigd.old/mkmess.pl Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/mkmess.pl Thu Aug 20 18:04:24 1998 @@ -0,0 +1,16 @@ +#!/usr/bin/perl +while (<>) { + next if !/ATM_CV_/; + chop; + chop($_ = $_.<>) unless /\*\//; + s/\s+/ /g; + /ATM_CV_\S+\s+(\d+)\s+\/\*\s*(.*\S)\s*\*\//; + $map[$1] = $2; +} +print "/* THIS IS A MACHINE-GENERATED FILE. DO NOT EDIT ! */\n\n"; +print "const char *cause_text[] = {\n"; +for ($i = 0; $i < 128; $i++) { + print " \"".(defined $map[$i] ? $map[$i] : "unknown cause $i")."\"". + ($i == 127 ? "\n" : ",\n"); +} +print "};\n"; diff -ur --new-file old/atm/sigd.old/policy.c new/atm/sigd.old/policy.c --- old/atm/sigd.old/policy.c Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/policy.c Thu Aug 20 18:04:25 1998 @@ -0,0 +1,54 @@ +/* policy.c - Access control policies */ + +/* Written 1997,1998 by Werner Almesberger, EPFL-LRC/ICA */ + + +#include +#include + +#include "proto.h" /* for "pretty" */ +#include "policy.h" + + +#define COMPONENT "POLICY" + + +static RULE *rules = NULL; +static RULE **next = &rules; + + +void add_rule(RULE *rule) +{ + rule->hits = 0; + rule->next = NULL; + *next = rule; + next = &rule->next; +} + + +int allow(const struct sockaddr_atmsvc *addr,int direction) +{ + RULE *rule; + char buffer[MAX_ATM_ADDR_LEN+1]; + int count; + + if ((direction & (ACL_IN | ACL_OUT)) == (ACL_IN | ACL_OUT)) + diag(COMPONENT,DIAG_ERROR,"allow: ACL_IN && ACL_OUT"); + count = 0; + for (rule = rules; rule; rule = rule->next) { + count++; + if (!(rule->type & direction)) continue; + if (!atm_equal((struct sockaddr *) addr, + (struct sockaddr *) &rule->addr,rule->mask,AXE_PRVOPT | + (rule->mask == -1 ? 0 : AXE_WILDCARD))) continue; + rule->hits++; + if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) addr, + pretty) < 0) + strcpy(buffer,""); + diag(COMPONENT,DIAG_DEBUG,"Rule %d: %s call %s %s",count, + rule->type & ACL_ALLOW ? "allowed" : "rejected", + direction & ACL_IN ? "from" : "to",buffer); + return rule->type & ACL_ALLOW; + } + return 1; +} diff -ur --new-file old/atm/sigd.old/policy.h new/atm/sigd.old/policy.h --- old/atm/sigd.old/policy.h Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/policy.h Thu Aug 20 18:04:25 1998 @@ -0,0 +1,27 @@ +/* policy.h - Access control policies */ + +/* Written 1997 by Werner Almesberger, EPFL-LRC */ + + +#ifndef POLICY_H +#define POLICY_H + +#define ACL_ALLOW 1 +#define ACL_REJECT 2 +#define ACL_IN 4 +#define ACL_OUT 8 + + +typedef struct _rule { + int type; + struct sockaddr_atmsvc addr; + int mask; /* -1 for none */ + int hits; + struct _rule *next; +} RULE; + + +void add_rule(RULE *rule); +int allow(const struct sockaddr_atmsvc *addr,int direction); + +#endif diff -ur --new-file old/atm/sigd.old/proto.c new/atm/sigd.old/proto.c --- old/atm/sigd.old/proto.c Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/proto.c Thu Aug 20 18:04:25 1998 @@ -0,0 +1,373 @@ +/* proto.c - Common protocol functions and structures */ + +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC */ + + +#include +#include +#include +#include +#include + +#include "atmd.h" +#include "uni.h" +#include "qlib.h" +#include + +#include "io.h" +#include "proto.h" +#include "sap.h" + + +#define COMPONENT "SIGD" + + +const char *state_name[] = { /* formatting aligned with STATE */ + "", "ss_null", "ss_listening", "ss_connecting", + "ss_connected", "ss_indicated", "ss_accepting", "ss_zombie", + "ss_wait_rel", "ss_wait_close","ss_rel_req", "ss_rel_ind", + "ss_proceeding","ss_listen_zombie", + "ss_mod_lcl", "ss_mod_req", "ss_mod_rcv", "ss_mod_fin_ack", + "ss_mod_fin_ok","ss_mod_fin_fail" + }; + +const char *cs_name[] = { + "NULL", "CALL_INIT", "", "OUT_PROC", + "", "", "CALL_PRES", "", + "CONN_REQ", "IN_PROC", "ACTIVE", "REL_REQ", + "REL_IND", "MOD_REQ", "MOD_RCV" }; + +const char *as_name[] = { "","as_bind","as_connect","as_accept", + "as_reject","as_listen","as_okay","as_error","as_indicate","as_close", + "as_itf_notify","as_modify","as_identify","as_terminate" }; + +const CALL_STATE state_map[] = { /* formatting aligned with STATE */ + cs_null, cs_null, cs_null, cs_call_init, + cs_active, cs_in_proc, cs_conn_req, cs_null, + cs_rel_req, cs_null, cs_rel_req, cs_rel_ind, + cs_in_proc, cs_null, +#ifdef Q2963_1 + cs_active, cs_mod_req, cs_mod_rcv, cs_active, + cs_active, cs_active +#endif + }; + +const PARTY_STATE eps_map[] = { + ps_null, ps_add_init, ps_null, ps_add_init, /* 0 */ + ps_null, ps_null, ps_add_recv, ps_null, /* 4 */ + ps_active, ps_add_recv, ps_active, ps_active, /* 8 */ + ps_active }; /*12 */ + +SOCKET *sockets = NULL; +unsigned char q_buffer[MAX_Q_MSG]; + + +SOCKET *new_sock(unsigned long id) +{ + SOCKET *sock; + + sock = alloc_t(SOCKET); + sock->state = ss_invalid; + memset(&sock->pvc,0,sizeof(sock->pvc)); + sock->qos.txtp.traffic_class = sock->qos.rxtp.traffic_class = ATM_UBR; + sock->id = id; + memset(&sock->local,0,sizeof(sock->local)); + memset(&sock->remote,0,sizeof(sock->remote)); + memset(&sock->sap,0,sizeof(sock->sap)); + sock->error = 0; + sock->call_state = cs_null; + sock->ep_ref = -1; + sock->conn_timer = NULL; + sock->listen = NULL; + sock->next = sockets; + sockets = sock; + return sock; +} + + +void free_sock(SOCKET *sock) +{ + SOCKET **walk; + + diag(COMPONENT,DIAG_DEBUG,"freeing socket 0x%lx@%p",sock->id,sock); + for (walk = &sockets; *walk != sock; walk = &(*walk)->next); + if (!*walk) + diag(COMPONENT,DIAG_FATAL, + "INTERNAL ERROR: freeing non-existing socket 0x%lx",sock->id); + *walk = sock->next; + if (sock->conn_timer) { + diag(COMPONENT,DIAG_ERROR,"socket 0x%lx has timer (%p) running", + sock->id,sock->conn_timer->callback); + stop_timer(sock->conn_timer); + } + if (sock->listen) + diag(COMPONENT,DIAG_ERROR,"socket 0x%lx has non-empty listen queue", + sock->id); + sock->state = ss_invalid; + free(sock); +} + + +void new_state(SOCKET *sock,STATE state) +{ + diag(COMPONENT,DIAG_DEBUG,"socket 0x%lx enters state %s (UNI %s)", + sock->id,state_name[state],cs_name[state_map[state]]); + sock->state = state; + sock->call_state = state_map[state]; +} + + +SOCKET *lookup_sap(const struct sockaddr_atmsvc *addr, + const struct atm_sap *sap,const struct atm_qos *qos, + struct sockaddr_atmsvc *res_addr,struct atm_sap *res_sap, + struct atm_qos *res_qos,int exact_match) +{ + SOCKET *walk,*wildcard; + int new_wc; + + new_wc = !atmsvc_addr_in_use(*addr); + wildcard = NULL; + for (walk = sockets; walk; walk = walk->next) + if (walk->state == ss_listening && sap_compat(&walk->local, + addr,res_addr,&walk->sap,sap,res_sap,&walk->qos,qos,res_qos)) + if (atmsvc_addr_in_use(walk->local)) return walk; + else if (exact_match) { + if (new_wc) return walk; + } + else wildcard = walk; + return wildcard; +} + + +const char *mid2name(unsigned char mid) +{ + switch (mid) { + case ATM_MSG_NATIONAL: + return "National specific message escape"; + case ATM_MSG_SETUP: + return "SETUP"; + case ATM_MSG_ALERTING: + return "ALERTING"; + case ATM_MSG_CALL_PROC: + return "CALL_PROCEEDING"; + case ATM_MSG_CONNECT: + return "CONNECT"; + case ATM_MSG_CONN_ACK: + return "CONNECT_ACK"; + case ATM_MSG_RESTART: + return "RESTART"; + case ATM_MSG_RELEASE: + return "RELEASE"; + case ATM_MSG_REST_ACK: + return "REST_ACK"; + case ATM_MSG_REL_COMP: + return "REL_COMP"; + case ATM_MSG_NOTIFY: + return "NOTIFY"; + case ATM_MSG_STATUS_ENQ: + return "STATUS_ENQ"; + case ATM_MSG_STATUS: + return "STATUS"; + case ATM_MSG_ADD_PARTY: + return "ADD_PARTY"; + case ATM_MSG_ADD_PARTY_ACK: + return "ADD_PARTY_ACK"; + case ATM_MSG_ADD_PARTY_REJ: + return "ADD_PARTY_REJECT"; + case ATM_MSG_PARTY_ALERT: + return "PARTY_ALERTING"; + case ATM_MSG_DROP_PARTY: + return "DROP_PARTY"; + case ATM_MSG_DROP_PARTY_ACK: + return "DROP_PARTY_ACK"; + case ATM_MSG_MODIFY_REQ: + return "MODIFY_REQUEST"; + case ATM_MSG_MODIFY_ACK: + return "MODIFY_ACK"; + case ATM_MSG_MODIFY_REJ: + return "MODIFY_REJECT"; + case ATM_MSG_CONN_AVAIL: + return "CONN_AVAIL"; + case ATM_MSG_LEAF_FAILURE: + return "LEAF SETUP FAIL"; + case ATM_MSG_LEAF_REQUEST: + return "LEAF SETUP REQ"; + case ATM_MSG_RESERVED: + return "Reserved..."; + default: + return "???"; + } +} + + +void send_kernel(unsigned long vcc,unsigned long listen_vcc, + enum atmsvc_msg_type type,int reply,const struct sockaddr_atmpvc *pvc, + const struct sockaddr_atmsvc *svc,const struct sockaddr_atmsvc *local, + const struct atm_sap *sap,const struct atm_qos *qos) +{ + struct atmsvc_msg *msg; + + msg = alloc_t(struct atmsvc_msg); + msg->vcc = vcc; + msg->listen_vcc = listen_vcc; + msg->type = type; + msg->reply = reply; + if (pvc) msg->pvc = *pvc; + else memset(&msg->pvc,0,sizeof(msg->pvc)); + if (sap) msg->sap = *sap; + else memset(&msg->sap,0,sizeof(msg->sap)); + if (qos) msg->qos = *qos; + else memset(&msg->qos,0,sizeof(msg->qos)); + if (local) msg->local = *local; + else memset(&msg->local,0,sizeof(msg->local)); + if (svc) msg->svc = *svc; + else memset(&msg->svc,0,sizeof(msg->svc)); + to_kernel(msg); + free(msg); +} + + +void send_release(SOCKET *sock,unsigned char reason,...) +{ + va_list ap; + Q_DSC dsc; + int size; + + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_msg_type,ATM_MSG_RELEASE); + q_assign(&dsc,QF_call_ref,sock->call_ref); + q_assign(&dsc,QF_cause,reason); + va_start(ap,reason); + switch (reason) { + case ATM_CV_TIMER_EXP: + { + char buf[4]; + + sprintf(buf,"%d",va_arg(ap,int)); + q_write(&dsc,QF_timer,buf,3); + break; + } + default: + } + va_end(ap); + if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); +} + + +void send_release_complete(unsigned long call_ref,unsigned char cause) +{ + Q_DSC dsc; + int size; + + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_msg_type,ATM_MSG_REL_COMP); + q_assign(&dsc,QF_call_ref,call_ref); + if (cause) q_assign(&dsc,QF_cause,cause); /* @@@ more data */ + if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); +} + + +void send_modify_reject(SOCKET *sock,unsigned char reason) +{ + Q_DSC dsc; + int size; + + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_msg_type,ATM_MSG_MODIFY_REJ); + q_assign(&dsc,QF_call_ref,sock->call_ref); + q_assign(&dsc,QF_cause,reason); + if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); +} + + +void set_error(SOCKET *sock,int code) +{ + if (!sock->error) sock->error = code; +} + + +void send_close(SOCKET *sock) +{ + if (sock->error == 1234) diag(COMPONENT,DIAG_FATAL,"BUG! BUG! BUG!"); + send_kernel(sock->id,0L,as_close,sock->error,NULL,NULL,NULL,NULL,NULL); + sock->error = 1234; +} + + +void q_report(int severity,const char *msg,...) +{ + va_list ap; + + va_start(ap,msg); + vdiag("QMSG",severity,msg,ap); + va_end(ap); +} + + +int get_vci(int itf) +{ + SOCKET *walk; + int s,vci; + + s = get_pvc(itf,&vci); + if (s < 0) return s; + for (walk = sockets; walk; walk = walk->next) + if (walk->pvc.sap_addr.vci == vci) { + vci = get_vci(itf); /* this recursion will keep all the busy ones + open until we return */ + break; + } + (void) close(s); + return vci; +} + + +typedef struct _vpci { + int vpci; + int itf; + struct _vpci *next; +} VPCI; + + +static VPCI *vpcis = NULL; + + +void enter_vpci(int vpci,int itf) +{ + VPCI *entry; + + for (entry = vpcis; entry; entry = entry->next) + if (entry->vpci == vpci) { + diag(COMPONENT,DIAG_ERROR,"ignoring duplicate VPCI %d (itf %d)", + vpci,itf); + return; + } + entry = alloc_t(VPCI); + entry->vpci = vpci; + entry->itf = itf; + entry->next = vpcis; + vpcis = entry; +} + + +int get_itf(int *vpci) +{ + VPCI *best,*walk; + + best = NULL; + for (walk = vpcis; walk; walk = walk->next) + if (walk->vpci <= *vpci && (!best || best->vpci < walk->vpci)) + best = walk; + if (!best) return signaling_pvc.sap_addr.itf; + *vpci -= best->vpci; + return best->itf; +} + + +void init_addr(void) +{ + VPCI *walk; + + itf_load(signaling_pvc.sap_addr.itf); + for (walk = vpcis; walk; walk = walk->next) itf_load(walk->itf); +} diff -ur --new-file old/atm/sigd.old/proto.h new/atm/sigd.old/proto.h --- old/atm/sigd.old/proto.h Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/proto.h Thu Aug 20 18:04:25 1998 @@ -0,0 +1,135 @@ +/* proto.h - Common protocol functions and structures */ + +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC */ + + +#ifndef PROTO_H +#define PROTO_H + +#include +#include + +#include "atmsap.h" +#include "atmd.h" + + +typedef enum { /* formatting aligned with state_map and others */ + ss_invalid, ss_null, ss_listening, ss_connecting, + ss_connected, ss_indicated, ss_accepting, ss_zombie, + ss_wait_rel, ss_wait_close, ss_rel_req, ss_rel_ind, + ss_proceeding, ss_listen_zombie, +#ifdef Q2963_1 + ss_mod_lcl, ss_mod_req, ss_mod_rcv, ss_mod_fin_ack, + ss_mod_fin_ok, ss_mod_fin_fail +#endif +} STATE; + +typedef enum { cs_null,cs_call_init,cs_out_proc = 3,cs_conn_req = 8, + cs_in_proc,cs_active,cs_rel_req,cs_rel_ind, +#ifdef Q2963_1 + cs_mod_req,cs_mod_rcv +#endif + } CALL_STATE; + +typedef enum { ps_null,ps_add_init,ps_add_recv = 6,ps_drop_init = 11, + ps_drop_recv,ps_active = 10 } PARTY_STATE; + +typedef struct _socket { + STATE state; + struct sockaddr_atmpvc pvc; + /* --- socket layer information ---------------------------------------- */ + unsigned long id; + struct sockaddr_atmsvc local; /* local address */ + struct sockaddr_atmsvc remote; /* remote address */ + struct atm_sap sap; /* SAP (BHLI and BLLI) */ + struct atm_qos qos; /* QOS parameters */ +#ifdef Q2963_1 + struct atm_qos new_qos; /* during modification */ + int owner; /* non-zero if connection owner */ +#endif + int error; /* error code for close */ + /* --- UNI information ------------------------------------------------- */ + CALL_STATE call_state; + unsigned long call_ref; /* bit 24 like when sending */ + short ep_ref; /* endpoint reference; -1 for p2p */ + TIMER *conn_timer; /* current connection timer */ + /* --- some meta-information ------------------------------------------- */ + struct _socket *listen; /* to pending connections, also used for "more" */ + struct _socket *next; /* next socket */ +} SOCKET; + +/* + * SOCKET uses a horrible linked list structure. Lists should be at least + * doubly-linked and there should be a few hashes (by id and by call_ref) for + * reasonable fast lookup. All this will have to wait till that version is + * stable enough to be useful to test the "real" thing against it. + */ + +typedef enum { sm_unknown,sm_user,sm_net,sm_switch } SIGNALING_MODE; + +extern const CALL_STATE state_map[]; +extern const PARTY_STATE eps_map[]; +extern const char *state_name[],*cs_name[],*as_name[]; + +extern SOCKET *sockets; +extern unsigned char q_buffer[]; + +#define DEFAULT_TRACE_SIZE 20 + +extern SIGNALING_MODE mode; +extern int net; /* @@@ remove soon */ +extern int allocate_ci; /* @@@ remove soon */ +extern int pretty; +extern int sig_pcr; +extern const char *sig_qos; +extern const char *dump_dir; + +extern int stop; + + +#define SEND_ERROR(vcc,code) \ + send_kernel(vcc,0L,as_error,code,NULL,NULL,NULL,NULL,NULL) + + +void poll_signals(void); + +void from_kernel(struct atmsvc_msg *msg,int size); +void itf_load(int itf); + +void to_uni(void *msg,int size); +void send_kernel(unsigned long vcc,unsigned long listen_vcc, + enum atmsvc_msg_type type,int reply,const struct sockaddr_atmpvc *pvc, + const struct sockaddr_atmsvc *svc,const struct sockaddr_atmsvc *local, + const struct atm_sap *sap,const struct atm_qos *qos); +void from_net(void *msg,int size); +void to_signaling(void *msg,int size); +void saal_failure(void); +void saal_okay(void); +void clear_all_calls(void); +void clear_all_calls_on_T309(void); + +SOCKET *new_sock(unsigned long id); +void free_sock(SOCKET *sock); +void new_state(SOCKET *sock,STATE state); +SOCKET *lookup_sap(const struct sockaddr_atmsvc *addr, + const struct atm_sap *sap,const struct atm_qos *qos, + struct sockaddr_atmsvc *res_addr,struct atm_sap *res_sap, + struct atm_qos *res_qos,int exact_match); + +void send_release(SOCKET *sock,unsigned char reason,...); +void send_release_complete(unsigned long call_ref,unsigned char cause); +int send_call_proceeding(SOCKET *sock); +void send_modify_reject(SOCKET *sock,unsigned char reason); + +const char *mid2name(unsigned char mid); + +void set_error(SOCKET *sock,int code); +void send_close(SOCKET *sock); + +int get_vci(int itf); + +void enter_vpci(int vpci,int itf); +int get_itf(int *vpci); +void init_addr(void); + +#endif diff -ur --new-file old/atm/sigd.old/sap.c new/atm/sigd.old/sap.c --- old/atm/sigd.old/sap.c Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/sap.c Thu Aug 20 18:04:25 1998 @@ -0,0 +1,339 @@ +/* sap.c - SAP manipulations */ + +/* Written 1996-1998 by Werner Almesberger, EPFL-LRC/ICA */ + + +#include +#include +#include +#include +#include /* sigh, again */ +#include + +#include "atm.h" +#include "atmd.h" +#include "uni.h" +#include "qlib.h" +#include + +#include "common.h" +#include "sap.h" + + +#define COMPONENT "SAP" + + +static int class_compat(const struct atm_trafprm *tx, + const struct atm_trafprm *rx) +{ + if (tx->traffic_class == ATM_NONE || tx->traffic_class == ATM_ANYCLASS) + return 1; + if (rx->traffic_class == ATM_UBR || rx->traffic_class == ATM_ANYCLASS) + return 1; + /* don't apply CAC to PCR */ + if (tx->traffic_class != rx->traffic_class) return 0; + /* ignore special cases like CBR to VBR for now */ + switch (tx->traffic_class) { + case ATM_CBR: + if (!rx->max_pcr || rx->max_pcr == ATM_MAX_PCR) return 1; + return tx->min_pcr <= rx->max_pcr; + /* Actually, we shouldn't look at min_pcr, because there's no + bandwidth negotiation anyway. */ + default: + diag(COMPONENT,DIAG_ERROR,"unsupported traffic class %d\n", + tx->traffic_class); + return 0; + } +} + + +int sap_compat(const struct sockaddr_atmsvc *old_addr, + const struct sockaddr_atmsvc *new_addr,struct sockaddr_atmsvc *res_addr, + const struct atm_sap *old_sap,const struct atm_sap *new_sap, + struct atm_sap *res_sap,const struct atm_qos *old_qos, + const struct atm_qos *new_qos,struct atm_qos *res_qos) +{ + if (atmsvc_addr_in_use(*old_addr) && + !atm_equal((struct sockaddr *) old_addr,(struct sockaddr *) new_addr,0,0)) + return 0; + if (res_qos) *res_qos = *new_qos; + if (old_qos->txtp.max_sdu && new_qos->rxtp.max_sdu && + old_qos->txtp.max_sdu > new_qos->rxtp.max_sdu) return 0; + if (new_qos->txtp.max_sdu && old_qos->rxtp.max_sdu && + new_qos->txtp.max_sdu > old_qos->rxtp.max_sdu) return 0; + if (!class_compat(&old_qos->txtp,&new_qos->rxtp) || + !class_compat(&new_qos->txtp,&old_qos->rxtp)) return 0; + if (!sap_equal(old_sap,new_sap, + SXE_COMPATIBLE | SXE_NEGOTIATION | (res_sap ? SXE_RESULT : 0),res_sap)) + return 0; + return 1; +} + + +static int encode_blli(Q_DSC *dsc,const struct atm_blli *blli) +{ + if (blli->l2_proto != ATM_L2_NONE) { + q_assign(dsc,QF_uil2_proto,blli->l2_proto); + switch (blli->l2_proto) { + case ATM_L2_X25_LL: + case ATM_L2_X25_ML: + case ATM_L2_HDLC_ARM: + case ATM_L2_HDLC_NRM: + case ATM_L2_HDLC_ABM: + case ATM_L2_Q922: + case ATM_L2_ISO7776: + if (blli->l2.itu.mode != ATM_IMD_NONE) + q_assign(dsc,QF_l2_mode,blli->l2.itu.mode); + if (blli->l2.itu.window) + q_assign(dsc,QF_window_size,blli->l2.itu.window); + break; + case ATM_L2_USER: + q_assign(dsc,QF_user_l2,blli->l2.user); + break; + default: + break; + } + } + if (blli->l3_proto != ATM_L3_NONE) { + q_assign(dsc,QF_uil3_proto,blli->l3_proto); + switch (blli->l3_proto) { + case ATM_L3_X25: + case ATM_L3_ISO8208: + case ATM_L3_X223: + if (blli->l3.itu.mode != ATM_IMD_NONE) + q_assign(dsc,QF_l3_mode,blli->l3.itu.mode); + if (blli->l3.itu.def_size) + q_assign(dsc,QF_def_pck_size,blli->l3.itu.def_size); + if (blli->l3.itu.window) + q_assign(dsc,QF_pck_win_size,blli->l3.itu.window); + break; + case ATM_L3_TR9577: + q_assign(dsc,QF_ipi_high,blli->l3.tr9577.ipi >> 1); + q_assign(dsc,QF_ipi_low,blli->l3.tr9577.ipi & 1); + if (blli->l3.tr9577.ipi == NLPID_IEEE802_1_SNAP) { + q_write(dsc,QF_oui,blli->l3.tr9577.snap,3); + q_write(dsc,QF_pid,blli->l3.tr9577.snap+3,2); + } + break; + case ATM_L3_USER: + q_assign(dsc,QF_user_l3,blli->l3.user); + break; + default: + diag(COMPONENT,DIAG_ERROR,"bad l3_proto (%d)", + blli->l3_proto); + return -EINVAL; + } + } + return 0; +} + + +int sap_encode(Q_DSC *dsc,const struct sockaddr_atmsvc *addr, + const struct atm_sap *sap,const struct atm_qos *qos) +{ + int error,pcr; + + if (*addr->sas_addr.pub) + q_write(dsc,QF_cdpn_e164,(void *) addr->sas_addr.pub, + strlen(addr->sas_addr.pub)); + else if (*addr->sas_addr.prv) + q_write(dsc,QF_cdpn_esa,(void *) addr->sas_addr.prv,ATM_ESA_LEN); + else return -EDESTADDRREQ; + if (qos->txtp.traffic_class == ATM_UBR || qos->rxtp.traffic_class == + ATM_UBR) q_assign(dsc,QF_best_effort,0); +#ifdef UNI40 + if (qos->txtp.traffic_class == ATM_CBR || qos->rxtp.traffic_class == + ATM_CBR) q_assign(dsc,QF_trans_cap,ATM_TC_CBR); +#endif + switch (qos->txtp.traffic_class) { + case ATM_NONE: + q_assign(dsc,QF_fw_pcr_01,0); + break; + case ATM_UBR: + /* fall through */ + case ATM_CBR: + /* here's a bit of policy: send the highest value we have */ + pcr = SELECT_TOP_PCR(qos->txtp); + diag(COMPONENT,DIAG_DEBUG,"fwd %d (%d..%d)",pcr, + qos->txtp.min_pcr,qos->txtp.max_pcr); + if (pcr == ATM_MAX_PCR) pcr = ATM_OC3_PCR; + q_assign(dsc,QF_fw_pcr_01,pcr); + break; + default: + diag(COMPONENT,DIAG_ERROR,"bad TX class (%d)", + qos->txtp.traffic_class); + return -EINVAL; + } + switch (qos->rxtp.traffic_class) { + case ATM_NONE: + q_assign(dsc,QF_bw_pcr_01,0); + break; + case ATM_UBR: + /* fall through */ + case ATM_CBR: + pcr = SELECT_TOP_PCR(qos->rxtp); + diag(COMPONENT,DIAG_DEBUG,"bwd %d (%d..%d)",pcr, + qos->rxtp.min_pcr,qos->rxtp.max_pcr); + if (pcr == ATM_MAX_PCR) pcr = ATM_OC3_PCR; + q_assign(dsc,QF_bw_pcr_01,pcr); + break; + default: + diag(COMPONENT,DIAG_ERROR,"bad RX class (%d)", + qos->rxtp.traffic_class); + return -EINVAL; + } + if (qos->txtp.max_sdu) q_assign(dsc,QF_fw_max_sdu,qos->txtp.max_sdu); + if (qos->rxtp.max_sdu) q_assign(dsc,QF_bw_max_sdu,qos->rxtp.max_sdu); + /* @@@ bearer class ? */ + /* @@@ QOS class ? */ + if (sap->bhli.hl_type != ATM_HL_NONE) { + q_assign(dsc,QF_hli_type,sap->bhli.hl_type-1); + switch (sap->bhli.hl_type) { + case ATM_HL_ISO: + q_write(dsc,QF_iso_hli,sap->bhli.hl_info,sap->bhli.hl_length); + break; + case ATM_HL_USER: + q_write(dsc,QF_user_hli,sap->bhli.hl_info,sap->bhli.hl_length); + break; +#ifdef UNI30 + case ATM_HL_HLP: + q_write(dsc,QF_hlp,sap->bhli.hl_info,4); + break; +#endif + case ATM_HL_VENDOR: + q_write(dsc,QF_hli_oui,sap->bhli.hl_info,3); + q_write(dsc,QF_app_id, sap->bhli.hl_info+3,4); + break; + default: + diag(COMPONENT,DIAG_ERROR,"bad hl_type (%d)", + sap->bhli.hl_type); + return -EINVAL; + } + } + if (!blli_in_use(sap->blli[0])) return 0; + q_instance(dsc,QG_blli1); + error = encode_blli(dsc,sap->blli); + if (error) return 0; + if (!blli_in_use(sap->blli[1])) return 0; + q_instance(dsc,QG_blli2); + error = encode_blli(dsc,sap->blli+1); + if (error) return 0; + if (!blli_in_use(sap->blli[2])) return 1; + q_instance(dsc,QG_blli3); + return encode_blli(dsc,sap->blli+2); +} + + +static void decode_blli(Q_DSC *dsc,struct atm_blli *blli) +{ +#define GET(var,field) \ + ({ if (q_present(dsc,field)) blli->var = q_fetch(dsc,field); }) + + if (q_present(dsc,QF_uil2_proto)) { + blli->l2_proto = q_fetch(dsc,QF_uil2_proto); + GET(l2.itu.mode,QF_l2_mode); + GET(l2.itu.window,QF_window_size); + GET(l2.user,QF_user_l2); + } + if (q_present(dsc,QF_uil3_proto)) { + blli->l3_proto = q_fetch(dsc,QF_uil3_proto); + GET(l3.itu.mode,QF_l3_mode); + GET(l3.itu.def_size,QF_def_pck_size); + GET(l3.itu.window,QF_pck_win_size); + GET(l3.user,QF_user_l3); + if (q_present(dsc,QF_ipi_high)) { + blli->l3.tr9577.ipi = q_fetch(dsc,QF_ipi_high) << 1; + if (blli->l3.tr9577.ipi != NLPID_IEEE802_1_SNAP) + blli->l3.tr9577.ipi |= q_fetch(dsc,QF_ipi_low); + else if (!q_present(dsc,QF_oui)) blli->l3.tr9577.ipi |= 1; + else { + q_read(dsc,QF_oui,blli->l3.tr9577.snap,3); + q_read(dsc,QF_pid,blli->l3.tr9577.snap+3,2); + } + } + } +#undef GET +} + + +void sap_decode(Q_DSC *dsc,struct sockaddr_atmsvc *addr,struct atm_sap *sap, + struct atm_qos *qos) +{ + memset(addr,0,sizeof(*addr)); + memset(sap,0,sizeof(*sap)); + memset(qos,0,sizeof(*qos)); + addr->sas_family = AF_ATMSVC; + if (q_present(dsc,QF_cdpn_e164)) + (void) q_read(dsc,QF_cdpn_e164,(void *) &addr->sas_addr.pub, + ATM_E164_LEN); + else if (q_present(dsc,QF_cdpn_esa)) + (void) q_read(dsc,QF_cdpn_esa,(void *) &addr->sas_addr.prv, + ATM_ESA_LEN); + if (q_present(dsc,QF_aal_type)) + if (q_fetch(dsc,QF_aal_type) != 5) + diag(COMPONENT,DIAG_ERROR,"AAL type %d requested", + q_fetch(dsc,QF_aal_type)); + if (q_present(dsc,QF_best_effort)) { + qos->txtp.traffic_class = qos->rxtp.traffic_class = ATM_UBR; + diag(COMPONENT,DIAG_DEBUG,"UBR"); + } + else { + qos->txtp.traffic_class = qos->rxtp.traffic_class = ATM_CBR; + diag(COMPONENT,DIAG_DEBUG,"CBR"); + } + qos->txtp.max_pcr = qos->rxtp.max_pcr = 0; + /* unbalanced decoding - always sets upper bound */ + if (q_present(dsc,QF_fw_pcr_01)) { + qos->rxtp.min_pcr = 0; + qos->rxtp.max_pcr = q_fetch(dsc,QF_fw_pcr_01); + } + if (q_present(dsc,QF_bw_pcr_01)) { + qos->txtp.min_pcr = 0; + qos->txtp.max_pcr = q_fetch(dsc,QF_bw_pcr_01); + } + if (!qos->txtp.max_pcr) qos->txtp.traffic_class = ATM_NONE; + if (!qos->rxtp.max_pcr) qos->rxtp.traffic_class = ATM_NONE; + diag(COMPONENT,DIAG_DEBUG,"fwd %d..%d bwd %d..%d", + qos->rxtp.min_pcr,qos->rxtp.max_pcr,qos->txtp.min_pcr, + qos->txtp.max_pcr); + /* SHOULD ... fail call if anything is missing ... @@@ */ + if (q_present(dsc,QF_bw_max_sdu)) + qos->txtp.max_sdu = q_fetch(dsc,QF_bw_max_sdu); + if (q_present(dsc,QF_fw_max_sdu)) + qos->rxtp.max_sdu = q_fetch(dsc,QF_fw_max_sdu); + if (q_present(dsc,QG_bhli)) { + sap->bhli.hl_type = q_fetch(dsc,QF_hli_type)+1; + switch (sap->bhli.hl_type) { + case ATM_HL_ISO: + sap->bhli.hl_length = q_length(dsc,QF_iso_hli); + q_read(dsc,QF_iso_hli,sap->bhli.hl_info,sap->bhli.hl_length); + break; + case ATM_HL_USER: + sap->bhli.hl_length = q_length(dsc,QF_user_hli); + q_read(dsc,QF_user_hli,sap->bhli.hl_info,sap->bhli.hl_length); + break; +#ifdef UNI30 + case ATM_HL_HLP: + sap->bhli.hl_length = 4; + q_read(dsc,QF_hlp,sap->bhli.hl_info,4); + break; +#endif + case ATM_HL_VENDOR: + sap->bhli.hl_length = 7; + q_read(dsc,QF_hli_oui,sap->bhli.hl_info,3); + q_read(dsc,QF_app_id,sap->bhli.hl_info+3,4); + break; + default: + diag(COMPONENT,DIAG_FATAL,"unrecognized hl_type"); + } + } + if (!q_present(dsc,QG_blli1)) return; + q_instance(dsc,QG_blli1); + decode_blli(dsc,sap->blli); + if (!q_present(dsc,QG_blli2)) return; + q_instance(dsc,QG_blli2); + decode_blli(dsc,sap->blli+1); + if (!q_present(dsc,QG_blli3)) return; + q_instance(dsc,QG_blli3); + decode_blli(dsc,sap->blli+2); +} diff -ur --new-file old/atm/sigd.old/sap.h new/atm/sigd.old/sap.h --- old/atm/sigd.old/sap.h Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/sap.h Thu Aug 20 18:04:25 1998 @@ -0,0 +1,24 @@ +/* sap.h - SAP manipulations */ + +/* Written 1996,1997 by Werner Almesberger, EPFL-LRC */ + + +#ifndef SAP_H +#define SAP_H + +#include + +#include "atmsap.h" + + +int sap_compat(const struct sockaddr_atmsvc *old_addr, + const struct sockaddr_atmsvc *new_addr,struct sockaddr_atmsvc *res_addr, + const struct atm_sap *old_sap,const struct atm_sap *new_sap, + struct atm_sap *res_sap,const struct atm_qos *old_qos, + const struct atm_qos *new_qos,struct atm_qos *res_qos); +int sap_encode(Q_DSC *dsc,const struct sockaddr_atmsvc *addr, + const struct atm_sap *sap,const struct atm_qos *qos); +void sap_decode(Q_DSC *dsc,struct sockaddr_atmsvc *addr,struct atm_sap *sap, + struct atm_qos *qos); + +#endif diff -ur --new-file old/atm/sigd.old/timeout.c new/atm/sigd.old/timeout.c --- old/atm/sigd.old/timeout.c Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/timeout.c Thu Aug 20 18:04:25 1998 @@ -0,0 +1,119 @@ +/* timeout.c - Processing of signaling timeout events */ + +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ + + +#include +#include +#include + +#include "atmd.h" + +#include "uni.h" +#include "proto.h" +#include "timeout.h" + + +#define COMPONENT "UNI" + + +static void complain(SOCKET *sock,const char *timer) +{ + diag(COMPONENT,DIAG_FATAL,"Timer %s expired in incompatible state %s", + timer,state_name[sock->state]); +} + + +void on_T303(void *user) /* CONNECTING */ +{ + SOCKET *sock = user; + + diag(COMPONENT,DIAG_DEBUG,"T303 on 0x%lx",sock->id); + if (sock->state != ss_connecting) complain(sock,"T303"); + SEND_ERROR(sock->id,-ETIMEDOUT); + sock->conn_timer = NULL; + free_sock(sock); +} + + +void on_T308_1(void *user) /* WAIT_REL or REL_REQ */ +{ + SOCKET *sock = user; + + diag(COMPONENT,DIAG_DEBUG,"T308_1 on 0x%lx",sock->id); + if (sock->state != ss_wait_rel && sock->state != ss_rel_req) + complain(sock,"T308_1"); + send_release(sock,ATM_CV_TIMER_EXP,308); /* @@@ ? */ + sock->conn_timer = NULL; + START_TIMER(sock,T308_2); +} + + +void on_T308_2(void *user) /* WAIT_REL or REL_REQ */ +{ + SOCKET *sock = user; + + diag(COMPONENT,DIAG_WARN,"Trouble: T308_2 has expired"); + if (sock->state != ss_wait_rel && sock->state != ss_rel_req) + complain(sock,"T308_2"); + sock->conn_timer = NULL; + if (sock->state == ss_rel_req) send_close(sock); + free_sock(sock); +} + + +void on_T309(void *user) +{ + diag(COMPONENT,DIAG_DEBUG,"T309 has expired"); + clear_all_calls_on_T309(); +} + + +void on_T310(void *user) +{ + on_T303(user); + diag(COMPONENT,DIAG_DEBUG,"(it's actually T310)"); +} + + +void on_T313(void *user) /* ACCEPTING */ +{ + SOCKET *sock = user; + + diag(COMPONENT,DIAG_DEBUG,"T313 on 0x%lx",sock->id); + if (sock->state != ss_accepting) complain(sock,"T313"); + send_release(sock,ATM_CV_TIMER_EXP,313); + sock->conn_timer = NULL; + START_TIMER(sock,T308_1); + new_state(sock,ss_rel_req); +} + + +#ifdef Q2963_1 + +void on_T360(void *user) +{ + SOCKET *sock = user; + + diag(COMPONENT,DIAG_DEBUG,"T360 on 0x%lx",sock->id); + if (sock->state != ss_mod_req) complain(sock,"T360"); + send_release(sock,ATM_CV_TIMER_EXP,360); + sock->conn_timer = NULL; + START_TIMER(sock,T308_1); + new_state(sock,ss_rel_req); +} + + +void on_T361(void *user) +{ + SOCKET *sock = user; + + diag(COMPONENT,DIAG_DEBUG,"T361 on 0x%lx",sock->id); + if (sock->state != ss_connected) complain(sock,"T361"); + sock->qos = sock->new_qos; + send_kernel(sock->id,0,as_modify,ATM_MF_SET,NULL,NULL,NULL,NULL,&sock->qos); + sock->conn_timer = NULL; + new_state(sock,ss_mod_fin_ack); +} + +#endif diff -ur --new-file old/atm/sigd.old/timeout.h new/atm/sigd.old/timeout.h --- old/atm/sigd.old/timeout.h Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/timeout.h Thu Aug 20 18:04:25 1998 @@ -0,0 +1,34 @@ +/* timeout.h - Processing of signaling timeout events */ + +/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ + + +#ifndef TIMEOUT_H +#define TIMEOUT_H + +#define T303_TIME 4000000 /* 4 sec */ +#define T308_1_TIME 30000000 /* 30 sec */ +#define T308_2_TIME 30000000 /* 30 sec */ +#define T309_TIME 10000000 /* 10 sec */ +#define T310_TIME 10000000 /* 10 sec */ +#define T313_TIME 4000000 /* 4 sec */ + +#define T360_TIME 30000000 /* 30 sec */ +#define T361_TIME 20000000 /* 20 sec */ + + +#define START_TIMER(u,t) { assert(!u->conn_timer); \ + u->conn_timer = start_timer(t##_TIME,on_##t,u); } +#define STOP_TIMER(u) { stop_timer(u->conn_timer); u->conn_timer = NULL; } + + +void on_T303(void *user); +void on_T308_1(void *user); +void on_T308_2(void *user); +void on_T309(void *user); +void on_T310(void *user); +void on_T313(void *user); +void on_T360(void *user); +void on_T361(void *user); + +#endif diff -ur --new-file old/atm/sigd.old/trace.c new/atm/sigd.old/trace.c --- old/atm/sigd.old/trace.c Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/trace.c Thu Aug 20 18:04:26 1998 @@ -0,0 +1,285 @@ +/* trace.c - Support functions for message tracing */ + +/* Written 1996-1998 by Werner Almesberger, EPFL-LRC/ICA */ + + +#include +#include +#include +#include +#include +#include +#include /* linux/atmsvc.h includes linux/atm.h */ +#include + +#include "atm.h" +#include "atmd.h" +#include "atmsap.h" +#include "trace.h" + + +#define DUMP_MODE +#include "qlib.h" + + +typedef struct _entry { + int number; + struct timeval time; + void (*print)(void *msg,int size); + const char *comment; + void *msg; + int size; + struct _entry *next; +} ENTRY; + + +int trace_size = 0; + +static int current_size = 0; +static int sequence = 0; +static ENTRY *first = NULL,*last = NULL; +static char *string = NULL; +static int curr_len; +static int new_line; + + +static inline void append_chunk(const char *str,int len) +{ + if (!string) curr_len = 0; + if (!(string = realloc(string,curr_len+len+1))) { + perror("realloc"); + exit(1); + } + memcpy(string+curr_len,str,len); + curr_len += len; + string[curr_len] = 0; +} + + +static void vappend(const char *fmt,va_list ap) +{ + const char *walk,*next; + + for (walk = next = fmt; *walk; walk++) + if (*walk == '%') { + if (walk != next) append_chunk(next,walk-next); + if (*++walk == 's') { + const char *str; + + str = va_arg(ap,const char *); + append_chunk(str,strlen(str)); + } + else { + char buf[21]; /* big enough for 64 bits */ + int num; + + while (isdigit(*walk) || *walk == 'l') walk++; /* @@@ FIXME */ + if (*walk != 'd' && *walk != 'x') { + fprintf(stderr,"bad format character %c (%d)\n",*walk, + *walk); + exit(1); + } + num = va_arg(ap,int); + sprintf(buf,*walk == 'd' ? "%d" : "%x",num); + append_chunk(buf,strlen(buf)); + } + next = walk+1; + } + if (walk != next) append_chunk(next,walk-next); +} + + +static void append(const char *fmt,...) +{ + va_list ap; + + va_start(ap,fmt); + vappend(fmt,ap); + va_end(ap); +} + + +static void print_text(void *msg,int size) +{ + append(" %s\n",msg); +} + + +static void append_svc(const struct sockaddr_atmsvc *svc) +{ + char buffer[MAX_ATM_ADDR_LEN+1]; + + if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) svc, + A2T_NAME | A2T_LOCAL | A2T_PRETTY) < 0) strcpy(buffer,""); + append("%s\n",buffer); +} + + +static void append_sap(const struct atm_sap *sap) +{ + char buffer[MAX_ATM_SAP_LEN+1]; + + if (sap2text(buffer,MAX_ATM_SAP_LEN+1,sap,S2T_NAME | S2T_LOCAL) < 0) + strcpy(buffer,""); + append("%s\n",buffer); +} + + +static void append_qos(const struct atm_qos *qos) +{ + char buffer[MAX_ATM_QOS_LEN+1]; + + if (qos2text(buffer,MAX_ATM_QOS_LEN+1,qos,0) < 0) + strcpy(buffer,""); + append("%s\n",buffer); +} + + +static void qd_vdump(const char *msg,va_list ap) +{ + if (new_line) append(" "); + vappend(msg,ap); + if (string && curr_len) new_line = string[curr_len-1] == '\n'; + else new_line = 1; +} + + +void qd_dump(const char *msg,...) +{ + va_list ap; + + va_start(ap,msg); + qd_vdump(msg,ap); + va_end(ap); +} + + +void qd_report(int severity,const char *msg,...) +{ + va_list ap; + + if (severity > Q_ERROR) return; + va_start(ap,msg); + qd_vdump(msg,ap); + va_end(ap); + qd_dump("\n"); +} + + +static void print_uni(void *msg,int size) +{ + Q_DSC dsc; + + (void) qd_open(&dsc,msg,size); + qd_close(&dsc); +} + + +static void print_kernel(void *msg,int size) +{ + static const char *type[] = { "as_catch_null","as_bind","as_connect", + "as_accept","as_reject","as_listen","as_okay","as_error","as_indicate", + "as_close","as_itf_notify","as_modify","as_identify" }; + struct atmsvc_msg *m = msg; + + append(" %s (vcc 0x%x, listen_vcc 0x%x)\n",m->type < sizeof(type)/ + sizeof(*type) ? type[m->type] : "???",m->vcc,m->listen_vcc); + append(" reply %d",m->reply); + if (m->reply) { + const char *error; + + error = strerror(m->reply > 0 ? m->reply : -m->reply); + append(" (%s)",error ? error : "???"); + } + append(", aal %d\n",m->qos.aal); + append(" pvc %d.%d.%d\n",m->pvc.sap_addr.itf,m->pvc.sap_addr.vpi, + m->pvc.sap_addr.vci); + append(" local "); + append_svc(&m->local); + append(" qos "); + append_qos(&m->qos); + append(" svc "); + append_svc(&m->svc); + append(" sap "); + append_sap(&m->sap); +} + + +static void store(void (*print)(void *msg,int size),const char *comment, + void *msg,int size) +{ + ENTRY *entry; + + entry = alloc_t(ENTRY); + (void) gettimeofday(&entry->time,NULL); + entry->number = sequence++; + entry->print = print; + entry->comment = comment; + entry->msg = msg; + entry->size = size; + entry->next = NULL; + if (current_size < trace_size) current_size++; + else { /* handle trace_size < 1 (< 0) too */ + ENTRY *next; + + next = first->next; + free(first->msg); + free(first); + if (first == last) last = NULL; /* someone set trace_size < 2 */ + first = next; + } + if (last) last->next = entry; + else first = entry; + last = entry; +} + + +void trace_msg(const char *msg) +{ + char *buf; + + if (!trace_size) return; + buf = alloc(strlen(msg)+1); + strcpy(buf,msg); + store(&print_text,"MESSAGE",buf,strlen(msg)); +} + + +void trace_uni(const char *comment,const void *msg,int size) +{ + void *buf; + + if (!trace_size) return; + buf = alloc(size); + memcpy(buf,msg,size); + store(&print_uni,comment,buf,size); +} + + +void trace_kernel(const char *comment,const struct atmsvc_msg *msg) +{ + struct atmsvc_msg *buf; + + if (!trace_size) return; + buf = alloc_t(struct atmsvc_msg); + *buf = *msg; + store(&print_kernel,comment,buf,sizeof(*msg)); +} + + +char *get_trace(void) +{ + ENTRY *walk; + + if (string) { + free(string); + string = NULL; + } + for (walk = first; walk; walk = walk->next) { + append("%6d (%d.%06d) %s:\n",walk->number,walk->time.tv_sec, + walk->time.tv_usec,walk->comment); + new_line = 1; + walk->print(walk->msg,walk->size); + } + return string; +} diff -ur --new-file old/atm/sigd.old/trace.h new/atm/sigd.old/trace.h --- old/atm/sigd.old/trace.h Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/trace.h Thu Aug 20 18:04:26 1998 @@ -0,0 +1,18 @@ +/* trace.h - Support functions for message tracing */ + +/* Written 1996 by Werner Almesberger, EPFL-LRC */ + + +#ifndef TRACE_H +#define TRACE_H + +#include + +extern int trace_size; + +void trace_msg(const char *msg); +void trace_uni(const char *comment,const void *msg,int size); +void trace_kernel(const char *comment,const struct atmsvc_msg *msg); +char *get_trace(void); + +#endif diff -ur --new-file old/atm/sigd.old/uni.c new/atm/sigd.old/uni.c --- old/atm/sigd.old/uni.c Thu Jan 1 01:00:00 1970 +++ new/atm/sigd.old/uni.c Mon Oct 5 18:56:01 1998 @@ -0,0 +1,788 @@ +/* uni.c - Processing of incoming UNI signaling messages */ + +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "atm.h" +#include "atmd.h" +#include "uni.h" +#include "qlib.h" +#include + +#include "proto.h" +#include "sap.h" +#include "io.h" +#include "policy.h" +#include "timeout.h" +#include "trace.h" + + +#define COMPONENT "UNI" + + +extern const char *cause_text[]; /* from mess.c */ + + +static Q_DSC in_dsc; +static TIMER *t309 = NULL; + + +int send_call_proceeding(SOCKET *sock) +{ + Q_DSC dsc; + int size; + + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_msg_type,ATM_MSG_CALL_PROC); + q_assign(&dsc,QF_call_ref,sock->call_ref); + if (net && allocate_ci) { + int vci; + + vci = get_vci(0); + if (vci < 0) { + (void) q_close(&dsc); + return vci; + } + sock->pvc.sap_family = AF_ATMPVC; + sock->pvc.sap_addr.itf = signaling_pvc.sap_addr.itf; + sock->pvc.sap_addr.vpi = 0; + sock->pvc.sap_addr.vci = vci; + } + if (net) { + q_assign(&dsc,QF_vpi,sock->pvc.sap_addr.vpi); + q_assign(&dsc,QF_vci,sock->pvc.sap_addr.vci); + } + if (sock->ep_ref >= 0) q_assign(&dsc,QF_ep_ref,sock->ep_ref); + if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + return 0; +} + + +static void setup_call(unsigned long call_ref) +{ + SOCKET *sock,*this,**walk; + struct sockaddr_atmsvc in_addr; + struct atm_sap in_sap; + struct atm_qos in_qos; + int i; + + sap_decode(&in_dsc,&in_addr,&in_sap,&in_qos); + if (!atmsvc_addr_in_use(in_addr)) { + send_release_complete(call_ref,ATM_CV_UNALLOC); + return; + } + if (!allow(&in_addr,ACL_IN)) { + send_release_complete(call_ref,ATM_CV_REJ_CLIR); + return; + } + this = new_sock(0); + sock = lookup_sap(&in_addr,&in_sap,&in_qos,&this->local,&this->sap, + &this->qos,0); + if (!sock) { + free_sock(this); + send_release_complete(call_ref,ATM_CV_INCOMP_DEST); + return; + } + this->qos.aal = ATM_AAL5; /* hack @@@ */ + this->state = net && allocate_ci ? ss_proceeding : ss_indicated; + this->call_state = cs_in_proc; + this->call_ref = call_ref; + if (q_present(&in_dsc,QF_ep_ref)) + this->ep_ref = q_fetch(&in_dsc,QF_ep_ref); +#ifdef CISCO + else +#endif + if (net && allocate_ci) { + int error; + + error = send_call_proceeding(this); + if (error) { + free_sock(this); + send_release_complete(call_ref,ATM_CV_NO_CI); + return; + } + } + /* if (sock->local) *this->local->sas_addr = sock->local->sas_addr; ??? */ + diag(COMPONENT,DIAG_DEBUG,"AAL type %ld",q_fetch(&in_dsc,QF_aal_type)); + if (!net) { /* already set by send_call_proceeding */ + int vpci; + + vpci = q_fetch(&in_dsc,QF_vpi); + this->pvc.sap_family = AF_ATMPVC; + this->pvc.sap_addr.itf = get_itf(&vpci); + this->pvc.sap_addr.vpi = vpci; + this->pvc.sap_addr.vci = q_fetch(&in_dsc,QF_vci); + } + diag(COMPONENT,DIAG_DEBUG,"ITF.VPI.VCI: %d.%d.%d",this->pvc.sap_addr.itf, + this->pvc.sap_addr.vpi,this->pvc.sap_addr.vci); + if (q_present(&in_dsc,QF_cgpn)) { /* should handle E.164 too */ + char buffer[MAX_ATM_ADDR_LEN+1]; + int plan; + + plan = q_fetch(&in_dsc,QF_cgpn_plan); + switch (plan) { + case ATM_NP_AEA: + i = q_read(&in_dsc,QF_cgpn,(void *) this->remote.sas_addr.prv, + ATM_ESA_LEN); + break; + case ATM_NP_E164: + i = q_read(&in_dsc,QF_cgpn,(void *) this->remote.sas_addr.pub, + ATM_E164_LEN); + break; + default: + diag(COMPONENT,DIAG_WARN,"Ignoring cgpn with unrecognized " + "numbering plan 0x%x\n",plan); + i = 0; + } + if (i) { + this->remote.sas_family = AF_ATMSVC; + if (atm2text(buffer,MAX_ATM_ADDR_LEN+1, + (struct sockaddr *) &this->remote,pretty) < 0) + strcpy(buffer,""); + diag(COMPONENT,DIAG_DEBUG,"Incoming call from %s",buffer); + } + } + send_kernel(0,sock->id,as_indicate,0,&this->pvc,&this->remote,&in_addr, + &this->sap,&this->qos); + for (walk = &sock->listen; *walk; walk = &(*walk)->listen); + *walk = this; + diag(COMPONENT,DIAG_DEBUG,"SE vpi.vci=%d.%d",this->pvc.sap_addr.vpi, + this->pvc.sap_addr.vci); +} + + +static void send_status(SOCKET *sock,unsigned long call_ref, + unsigned char cause,...) +{ + va_list ap; + Q_DSC dsc; + int size; + + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_msg_type,ATM_MSG_STATUS); + if (sock) { + q_assign(&dsc,QF_call_ref,sock->call_ref); + q_assign(&dsc,QF_call_state,(int) sock->call_state); + if (sock->ep_ref >= 0) { + q_assign(&dsc,QF_ep_ref,sock->ep_ref); + q_assign(&dsc,QF_ep_state,eps_map[sock->call_state]); + } + } + else { + q_assign(&dsc,QF_call_ref,call_ref); + q_assign(&dsc,QF_call_state,0); /* U0 - Null / REST 0 - Null */ + } + q_assign(&dsc,QF_cause,cause); + va_start(ap,cause); + switch (cause) { + case ATM_CV_UNKNOWN_MSG_TYPE: + case ATM_CV_INCOMP_MSG: + q_assign(&dsc,QF_bad_msg_type,va_arg(ap,unsigned char)); + break; + case ATM_CV_MAND_IE_MISSING: + case ATM_CV_INVALID_IE: + { + unsigned char ie; + + ie = va_arg(ap,unsigned char); + q_write(&dsc,QF_ie_id6,&ie,1); + break; + } + default: + ; + } + va_end(ap); + if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); +} + + +static void send_status_enq(SOCKET *sock) +{ + Q_DSC dsc; + int size; + + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_msg_type,ATM_MSG_STATUS_ENQ); + q_assign(&dsc,QF_call_ref,sock->call_ref); + if (sock->ep_ref >= 0) q_assign(&dsc,QF_ep_ref,sock->ep_ref); + if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + /* @@@ should start T322 */ +} + + +static void send_connect_ack(SOCKET *sock) +{ + Q_DSC dsc; + int size; + + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_msg_type,ATM_MSG_CONN_ACK); + q_assign(&dsc,QF_call_ref,sock->call_ref); + if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); +} + + +static void send_restart_ack(int vpi,int vci) +{ + Q_DSC dsc; + int size; + + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_msg_type,ATM_MSG_REST_ACK); + q_assign(&dsc,QF_call_ref,0); + if (!vpi && !vci) q_assign(&dsc,QF_rst_class,ATM_RST_ALL_VC); + else { + q_assign(&dsc,QF_rst_class,ATM_RST_IND_VC); + q_assign(&dsc,QF_vpi,vpi); + q_assign(&dsc,QF_vci,vci); + } + if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); +} + + +static void send_drop_party_ack(unsigned long call_ref,short ep_ref, + unsigned char cause) +{ + Q_DSC dsc; + int size; + + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_msg_type,ATM_MSG_DROP_PARTY_ACK); + q_assign(&dsc,QF_call_ref,call_ref); + q_assign(&dsc,QF_ep_ref,ep_ref); + q_assign(&dsc,QF_cause,cause); + if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); +} + + +#ifdef Q2963_1 + +static void send_conn_avail(SOCKET *sock) +{ + Q_DSC dsc; + int size; + + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_msg_type,ATM_MSG_CONN_AVAIL); + q_assign(&dsc,QF_call_ref,sock->call_ref); + if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); +} + +#endif + + +static void uni_call(SOCKET *sock,unsigned char mid) +{ + char buffer[MAX_ATM_ADDR_LEN+1]; + int error; + + switch (mid) { + case ATM_MSG_STATUS: /* 5.5.6.12 */ + { + CALL_STATE state; + + /* + * NOTE: T322 isn't implemented yet, but when it is, make sure + * to only stop it on STATUS iff the cause is + * ATM_CV_RESP_STAT_ENQ. Supplementary services break if + * you stop on any STATUS. + */ + state = q_fetch(&in_dsc,QF_call_state); + if (state == cs_null) break; /* clear call */ + if (sock->call_state == cs_rel_req || sock->call_state == + cs_rel_ind) return; + if (state != sock->call_state) + diag(COMPONENT,DIAG_WARN,"STATUS %s received in state %s", + cs_name[state],cs_name[sock->call_state]); + } + return; + default: + ; + } + switch (mid) { + case ATM_MSG_CALL_PROC: /* CONNECTING, WAIT_REL, REL_REQ */ + if (sock->state == ss_wait_rel || sock->state == ss_rel_req) { + send_status(sock,0,ATM_CV_INCOMP_MSG,ATM_MSG_CALL_PROC); + return; + } + if (sock->state != ss_connecting) break; + /* check for 2nd CALL_PROC @@@ */ + STOP_TIMER(sock); + if (q_present(&in_dsc,QG_conn_id)) { + int vpci; + + vpci = q_fetch(&in_dsc,QF_vpi); + sock->pvc.sap_family = AF_ATMPVC; + sock->pvc.sap_addr.itf = get_itf(&vpci); + sock->pvc.sap_addr.vpi = vpci; + sock->pvc.sap_addr.vci = q_fetch(&in_dsc,QF_vci); + diag(COMPONENT,DIAG_DEBUG,"ITF.VPI.VCI: %d.%d.%d", + sock->pvc.sap_addr.itf,sock->pvc.sap_addr.vpi, + sock->pvc.sap_addr.vci); + } + START_TIMER(sock,T310); + sock->call_state = cs_out_proc; + return; + case ATM_MSG_CONNECT: /* CONNECTING, REL_REQ */ + if (sock->state == ss_rel_req) { + send_status(sock,0,ATM_CV_INCOMP_MSG,ATM_MSG_CONNECT); + return; + } + if (sock->state != ss_connecting) break; + STOP_TIMER(sock); + if (q_present(&in_dsc,QG_conn_id)) { + int vpci; + + vpci = q_fetch(&in_dsc,QF_vpi); + sock->pvc.sap_family = AF_ATMPVC; + sock->pvc.sap_addr.itf = get_itf(&vpci); + sock->pvc.sap_addr.vpi = vpci; + sock->pvc.sap_addr.vci = q_fetch(&in_dsc,QF_vci); + diag(COMPONENT,DIAG_DEBUG,"ITF.VPI.VCI: %d/%d.%d", + sock->pvc.sap_addr.itf,sock->pvc.sap_addr.vpi, + sock->pvc.sap_addr.vci); + } + error = 0; + if (!sock->pvc.sap_addr.vpi && !sock->pvc.sap_addr.vci) + error = -EPROTO; + /* more problems */ + if (error) { + set_error(sock,error); + send_release(sock,0); /* @@@ cause follows reason ??? */ + START_TIMER(sock,T308_1); + new_state(sock,ss_rel_req); + return; + } + send_connect_ack(sock); + /* @@@ fill in sock->remote */ + /* @@@ fill in traffic parameters */ + send_kernel(sock->id,0,as_okay,0,&sock->pvc,NULL,&sock->local, + &sock->sap,&sock->qos); + new_state(sock,ss_connected); +#ifdef Q2963_1 + sock->owner = 1; +#endif + if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) + &sock->local,0) < 0) strcpy(buffer,""); + diag(COMPONENT,DIAG_INFO,"Active open succeeded (CR 0x%06X, " + "ID 0x%08x, addr %s)",sock->call_ref,sock->id,buffer); + return; + case ATM_MSG_CONN_ACK: /* ACCEPTING, WAIT_REL, REL_REQ */ + diag(COMPONENT,DIAG_DEBUG,"CA vpi.vci=%d.%d", + sock->pvc.sap_addr.vpi,sock->pvc.sap_addr.vci); + if (sock->state == ss_wait_rel || sock->state == ss_rel_req) { + send_status(sock,0,ATM_CV_INCOMP_MSG,ATM_MSG_CONN_ACK); + return; + } + if (sock->state != ss_accepting) break; + STOP_TIMER(sock); + send_kernel(sock->id,0,as_okay,0,NULL,NULL,&sock->local,&sock->sap, + NULL); + new_state(sock,ss_connected); +#ifdef Q2963_1 + sock->owner = 0; +#endif + if (atm2text(buffer,MAX_ATM_ADDR_LEN+1, (struct sockaddr *) + &sock->local,0) < 0) strcpy(buffer,""); + diag(COMPONENT,DIAG_INFO,"Passive open succeeded (CR 0x%06X, " + "ID 0x%08x, addr %s)",sock->call_ref,sock->id,buffer); + return; + case ATM_MSG_RELEASE: /* all states */ + { + unsigned char cause; + + cause = q_fetch(&in_dsc,QF_cause); + diag(COMPONENT,DIAG_DEBUG,"Cause %d (%s)",cause,cause > 127 ? + "invalid cause" : cause_text[cause]); + } + switch (sock->state) { + case ss_connecting: + set_error(sock,-ECONNREFUSED); + /* fall through */ + case ss_accepting: + set_error(sock,-ECONNRESET); /* ERESTARTSYS ? */ + send_release_complete(sock->call_ref,0); + SEND_ERROR(sock->id,sock->error); + STOP_TIMER(sock); + free_sock(sock); + return; + case ss_rel_req: + send_close(sock); + /* fall through */ + case ss_wait_rel: + STOP_TIMER(sock); + free_sock(sock); + return; +#ifdef Q2963_1 + case ss_mod_req: +#endif + STOP_TIMER(sock); + /* fall through */ +#ifdef Q2963_1 + case ss_mod_lcl: + case ss_mod_rcv: + case ss_mod_fin_ok: + case ss_mod_fin_fail: + case ss_mod_fin_ack: +#endif + case ss_connected: + diag(COMPONENT,DIAG_INFO,"Passive close (CR 0x%06X)", + sock->call_ref); +#ifdef Q2963_1 + if (timer_handler(sock->conn_timer) == on_T361) + STOP_TIMER(sock); +#endif + send_close(sock); + new_state(sock,ss_rel_ind); + return; + case ss_indicated: + /* fall through */ + case ss_proceeding: + send_release_complete(sock->call_ref,0); + new_state(sock,ss_zombie); + /* fall through */ + case ss_rel_ind: + return; + default: + send_release_complete(sock->call_ref,0); /* @@@ should + be ATM_CV_INCOMP_MSG */ + break; + } + break; + case ATM_MSG_RESTART: + set_error(sock,-ENETRESET); + /* fall through */ + case ATM_MSG_STATUS: /* fall through when clearing */ + case ATM_MSG_REL_COMP: /* basically any state (except LISTENING and + ZOMBIE) */ + { + unsigned char cause; + + if (mid != ATM_MSG_REL_COMP || !q_present(&in_dsc,QF_cause)) + cause = 0; + else { + cause = q_fetch(&in_dsc,QF_cause); + diag(COMPONENT,DIAG_DEBUG,"Cause %d (%s)",cause, + cause > 127 ? "invalid cause" : cause_text[cause]); + } + switch (sock->state) { + case ss_connecting: + set_error(sock,cause == ATM_CV_UNALLOC ? + -EADDRNOTAVAIL : cause == ATM_CV_RES_UNAVAIL || +#if defined(UNI31) || defined(UNI40) + cause == ATM_CV_UCR_UNAVAIL_NEW || +#endif + cause == ATM_CV_NO_ROUTE_DEST ? -EHOSTUNREACH : + cause == ATM_CV_NUM_CHANGED ? -EREMCHG : + cause == ATM_CV_DEST_OOO ? -EHOSTDOWN : + -ECONNREFUSED); + /* fall through */ + case ss_accepting: + set_error(sock,-ECONNRESET); /* ERESTARTSYS ? */ + SEND_ERROR(sock->id,sock->error); + STOP_TIMER(sock); + free_sock(sock); + return; + case ss_rel_req: + send_close(sock); + /* fall through */ + case ss_wait_rel: + STOP_TIMER(sock); + free_sock(sock); + return; +#ifdef Q2963_1 + case ss_mod_req: +#endif + STOP_TIMER(sock); + /* fall through */ +#ifdef Q2963_1 + case ss_mod_lcl: + case ss_mod_rcv: + case ss_mod_fin_ok: + case ss_mod_fin_fail: + case ss_mod_fin_ack: +#endif + case ss_connected: + diag(COMPONENT,DIAG_INFO,"Passive close (CR 0x%06X)", + sock->call_ref); +#ifdef Q2963_1 + if (timer_handler(sock->conn_timer) == on_T361) + STOP_TIMER(sock); +#endif + send_close(sock); + /* fall through */ + case ss_rel_ind: + new_state(sock,ss_wait_close); + return; + case ss_indicated: + /* fall through */ + case ss_proceeding: + new_state(sock,ss_zombie); + return; + default: + break; + } + break; /* fail */ + } + case ATM_MSG_ALERTING: + /* + * We basically ignore this junk message, except for the connection + * identifier it may carry. + */ + if (q_present(&in_dsc,QG_conn_id)) { + int vpci; + + vpci = q_fetch(&in_dsc,QF_vpi); + sock->pvc.sap_family = AF_ATMPVC; + sock->pvc.sap_addr.itf = get_itf(&vpci); + sock->pvc.sap_addr.vpi = vpci; + sock->pvc.sap_addr.vci = q_fetch(&in_dsc,QF_vci); + diag(COMPONENT,DIAG_DEBUG,"ITF.VPI.VCI: %d.%d.%d", + sock->pvc.sap_addr.itf,sock->pvc.sap_addr.vpi, + sock->pvc.sap_addr.vci); + } + return; + case ATM_MSG_NOTIFY: + /* silently ignore this junk */ + return; +#ifdef Q2963_1 +/* + * Buglet ahead: should actually test "call_state" + */ + case ATM_MSG_MODIFY_REQ: + if (sock->state != ss_connected || sock->owner) break; + sock->new_qos = sock->qos; + if (q_present(&in_dsc,QF_fw_pcr_01)) + sock->new_qos.rxtp.max_pcr = q_fetch(&in_dsc,QF_fw_pcr_01); + if (q_present(&in_dsc,QF_bw_pcr_01)) + sock->new_qos.txtp.max_pcr = q_fetch(&in_dsc,QF_bw_pcr_01); + send_kernel(sock->id,0,as_modify,ATM_MF_INC_RSV | ATM_MF_DEC_RSV | + ATM_MF_DEC_SHP,NULL,NULL,NULL,NULL,&sock->new_qos); + new_state(sock,ss_mod_rcv); + return; + case ATM_MSG_MODIFY_ACK: + if (sock->state != ss_mod_req) break; + STOP_TIMER(sock); + sock->qos = sock->new_qos; + if (q_present(&in_dsc,QG_bbrt)) send_conn_avail(sock); + send_kernel(sock->id,0,as_modify,ATM_MF_SET,NULL,NULL,NULL,NULL, + &sock->qos); + new_state(sock,ss_mod_fin_ok); + return; + case ATM_MSG_MODIFY_REJ: + if (sock->state != ss_mod_req) break; + STOP_TIMER(sock); + sock->error = -EAGAIN; + send_kernel(sock->id,0,as_modify,ATM_MF_SET,NULL,NULL,NULL,NULL, + &sock->qos); + new_state(sock,ss_mod_fin_fail); + return; + case ATM_MSG_CONN_AVAIL: + if (sock->state != ss_connected || !sock->owner) break; + STOP_TIMER(sock); + send_kernel(sock->id,0,as_modify,ATM_MF_SET,NULL,NULL,NULL,NULL, + &sock->qos); + new_state(sock,ss_mod_fin_ack); + return; +#endif + default: + diag(COMPONENT,DIAG_WARN,"Bad signaling message %d",mid); + send_status(sock,0,ATM_CV_UNKNOWN_MSG_TYPE,mid); + return; + } + diag(COMPONENT,DIAG_WARN, + "Signaling message %s is incompatible with state %s/%s (%d?%d)", + mid2name(mid),state_name[sock->state],cs_name[sock->call_state], + (int) sock->state,(int) sock->call_state); + send_status(sock,0,ATM_CV_INCOMP_MSG,mid); +} + + +void clear_all_calls(void) +{ + SOCKET *curr,*next; + + for (curr = sockets; curr; curr = next) { + next = curr->next; + if (curr->call_state != cs_null) uni_call(curr,ATM_MSG_RESTART); + } +} + + +void clear_all_calls_on_T309(void) +{ + clear_all_calls(); + t309 = NULL; +} + + +void saal_failure(void) +{ + SOCKET *curr,*next; + + trace_msg("SAAL went down"); + for (curr = sockets; curr; curr = next) { + next = curr->next; + if (curr->call_state != cs_null) + if (curr->call_state != cs_active) + uni_call(curr,ATM_MSG_RESTART); + else if (!t309) t309 = start_timer(T309_TIME,on_T309,NULL); + } +} + + +void saal_okay(void) +{ + SOCKET *curr; + + trace_msg("SAAL came up"); +#ifdef THOMFLEX + /* + * Some versions of the Thomson Thomflex 5000 won't do any signaling before + * they get a RESTART. Whenever SAAL comes up, this may indicate that the + * switch got booted, so we send that RESTART. We also have to clear all + * pending connections, which isn't that nice ... Note that the rest of the + * RESTART state machine is not implemented, so the RESTART ACKNOWLEDGE + * will yield a warning. + */ + { + Q_DSC dsc; + int size; + + clear_all_calls(); + q_create(&dsc,q_buffer,MAX_Q_MSG); + q_assign(&dsc,QF_msg_type,QMSG_RESTART); + q_assign(&dsc,QF_call_ref,0); + q_assign(&dsc,QF_rst_class,ATM_RST_ALL_VC); + if ((size = q_close(&dsc)) >= 0) to_signaling(q_buffer,size); + } +#endif + if (!t309) return; + stop_timer(t309); + t309 = NULL; + for (curr = sockets; curr; curr = curr->next) + if (curr->call_state != cs_null) send_status_enq(curr); +} + + +static void process_uni(void *msg) +{ + SOCKET *curr; + unsigned long call_ref; + unsigned char mid; + + call_ref = q_fetch(&in_dsc,QF_call_ref)^0x800000; + mid = q_fetch(&in_dsc,QF_msg_type); + if (mid == ATM_MSG_REST_ACK) return; + if (mid == ATM_MSG_RESTART) { /* 5.5.5.2 */ + int rst_class; + + rst_class = q_fetch(&in_dsc,QF_rst_class); + switch (rst_class) { + case ATM_RST_IND_VC: + { + int vpi,vci; + + if (!q_present(&in_dsc,QG_conn_id)) { + send_status(NULL,0L,ATM_CV_MAND_IE_MISSING, + ATM_IE_CONN_ID); + return; + } + vpi = q_fetch(&in_dsc,QF_vpi); + vci = q_fetch(&in_dsc,QF_vci); + for (curr = sockets; curr; curr = curr->next) + if (curr->pvc.sap_addr.vpi == vpi && + curr->pvc.sap_addr.vci == vci) break; + if (!curr) { + send_status(NULL,0L,ATM_CV_INVALID_IE, + ATM_IE_CONN_ID); + return; + } + uni_call(curr,mid); + send_restart_ack(vpi,vci); + } + break; + case ATM_RST_ALL_VC: + clear_all_calls(); + send_restart_ack(0,0); + break; + default: + send_status(NULL,0L,ATM_CV_INVALID_IE,ATM_IE_RESTART); + } + return; + } + if (!(call_ref & 0x7fffff)) { + return; /* bad things happen ... @@@ */ + } + for (curr = sockets; curr; curr = curr->next) + if (curr->call_ref == call_ref) break; + diag(COMPONENT,DIAG_DEBUG,"FROM SAAL: %s (0x%02X) CR 0x%06lx for 0x%lx", + mid2name(((unsigned char *) msg)[5]),((unsigned char *)msg)[5],call_ref, + curr ? curr->id : 0); + if (mid == ATM_MSG_SETUP) { + if (!curr) setup_call(call_ref); + return; + } + if (mid == ATM_MSG_STATUS_ENQ) { + send_status(curr,call_ref,ATM_CV_RESP_STAT_ENQ); + return; + } + if (curr && q_present(&in_dsc,QF_ep_ref) && mid != ATM_MSG_ADD_PARTY && + mid != ATM_MSG_DROP_PARTY_ACK) + if (curr->ep_ref != q_fetch(&in_dsc,QF_ep_ref)) { + send_drop_party_ack(call_ref,q_fetch(&in_dsc,QF_ep_ref), + ATM_CV_INV_EPR); + return; + } + if (!curr || curr->call_state == cs_null) { + if (mid != ATM_MSG_REL_COMP) + if (mid != ATM_MSG_STATUS) + send_release_complete(call_ref,ATM_CV_INV_CR); + else if (q_fetch(&in_dsc,QF_call_state) != (int) cs_null) + send_release_complete(call_ref,ATM_CV_INCOMP_MSG); + return; + } + uni_call(curr,mid); +} + + +static void abort_call(unsigned char *msg,int size) +{ + SOCKET *curr; + unsigned long call_ref; + + if (size < 6) { + diag(COMPONENT,DIAG_ERROR,"message too short (%d bytes)",size); + return; + } + /* hope that at least the call ref is okay ... */ + call_ref = ((msg[3] << 16) | (msg[4] << 8) | msg[5])^0x800000; + diag(COMPONENT,DIAG_ERROR,"can't parse message - aborting the call " + "(CR 0x%06lx)",call_ref); + for (curr = sockets; curr; curr = curr->next) + if (curr->call_ref == call_ref) { + uni_call(curr,ATM_MSG_RESTART); + break; + } + send_release_complete(call_ref,ATM_CV_PROTOCOL_ERROR); +} + + +void to_uni(void *msg,int size) +{ + if (q_open(&in_dsc,msg,size) < 0) { + abort_call(msg,size); + return; + } + process_uni(msg); + if (q_close(&in_dsc) < 0) + diag(COMPONENT,DIAG_ERROR,"q_close returned <0 in to_uni"); +} .