aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarsten Keil <kkeil@suse.de>2007-02-28 23:13:50 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-03-01 17:53:39 -0500
commit17f0cd2f350b90b28301e27fe0e39f34bfe7e730 (patch)
tree6baba85d4f3b83398dc5a412b328bfcef1633548
parent34bbd704051c9d053d69e90569a3a2365f4c7b50 (diff)
[PATCH] Fix buffer overflow and races in capi debug functions
The CAPI trace debug functions were using a fixed size buffer, which can be overflowed if wrong formatted CAPI messages were sent to the kernel capi layer. The code was also not protected against multiple callers. This fix bug 8028. Additionally the patch make the CAPI trace functions optional. Signed-off-by: Karsten Keil <kkeil@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/isdn/capi/Kconfig16
-rw-r--r--drivers/isdn/capi/capidrv.c28
-rw-r--r--drivers/isdn/capi/capiutil.c254
-rw-r--r--drivers/isdn/capi/kcapi.c77
-rw-r--r--include/linux/isdn/capiutil.h21
5 files changed, 318 insertions, 78 deletions
diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig
index 8b6c9a431ffa..c921d6c522f5 100644
--- a/drivers/isdn/capi/Kconfig
+++ b/drivers/isdn/capi/Kconfig
@@ -2,13 +2,25 @@
2# Config.in for the CAPI subsystem 2# Config.in for the CAPI subsystem
3# 3#
4config ISDN_DRV_AVMB1_VERBOSE_REASON 4config ISDN_DRV_AVMB1_VERBOSE_REASON
5 bool "Verbose reason code reporting (kernel size +=7K)" 5 bool "Verbose reason code reporting"
6 depends on ISDN_CAPI 6 depends on ISDN_CAPI
7 default y
7 help 8 help
8 If you say Y here, the AVM B1 driver will give verbose reasons for 9 If you say Y here, the CAPI drivers will give verbose reasons for
9 disconnecting. This will increase the size of the kernel by 7 KB. If 10 disconnecting. This will increase the size of the kernel by 7 KB. If
10 unsure, say Y. 11 unsure, say Y.
11 12
13config CAPI_TRACE
14 bool "CAPI trace support"
15 depends on ISDN_CAPI
16 default y
17 help
18 If you say Y here, the kernelcapi driver can make verbose traces
19 of CAPI messages. This feature can be enabled/disabled via IOCTL for
20 every controler (default disabled).
21 This will increase the size of the kernelcapi module by 20 KB.
22 If unsure, say Y.
23
12config ISDN_CAPI_MIDDLEWARE 24config ISDN_CAPI_MIDDLEWARE
13 bool "CAPI2.0 Middleware support (EXPERIMENTAL)" 25 bool "CAPI2.0 Middleware support (EXPERIMENTAL)"
14 depends on ISDN_CAPI && EXPERIMENTAL 26 depends on ISDN_CAPI && EXPERIMENTAL
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index 2a49cea0a223..23b6f7bc16b7 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -990,6 +990,7 @@ static void handle_plci(_cmsg * cmsg)
990 capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f); 990 capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
991 capidrv_plci *plcip; 991 capidrv_plci *plcip;
992 isdn_ctrl cmd; 992 isdn_ctrl cmd;
993 _cdebbuf *cdb;
993 994
994 if (!card) { 995 if (!card) {
995 printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n", 996 printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
@@ -1122,8 +1123,15 @@ static void handle_plci(_cmsg * cmsg)
1122 break; 1123 break;
1123 } 1124 }
1124 } 1125 }
1125 printk(KERN_ERR "capidrv-%d: %s\n", 1126 cdb = capi_cmsg2str(cmsg);
1126 card->contrnr, capi_cmsg2str(cmsg)); 1127 if (cdb) {
1128 printk(KERN_WARNING "capidrv-%d: %s\n",
1129 card->contrnr, cdb->buf);
1130 cdebbuf_free(cdb);
1131 } else
1132 printk(KERN_WARNING "capidrv-%d: CAPI_INFO_IND InfoNumber %x not handled\n",
1133 card->contrnr, cmsg->InfoNumber);
1134
1127 break; 1135 break;
1128 1136
1129 case CAPI_CONNECT_ACTIVE_CONF: /* plci */ 1137 case CAPI_CONNECT_ACTIVE_CONF: /* plci */
@@ -1371,10 +1379,18 @@ static _cmsg s_cmsg;
1371static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb) 1379static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
1372{ 1380{
1373 capi_message2cmsg(&s_cmsg, skb->data); 1381 capi_message2cmsg(&s_cmsg, skb->data);
1374 if (debugmode > 3) 1382 if (debugmode > 3) {
1375 printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n", 1383 _cdebbuf *cdb = capi_cmsg2str(&s_cmsg);
1376 ap->applid, capi_cmsg2str(&s_cmsg)); 1384
1377 1385 if (cdb) {
1386 printk(KERN_DEBUG "%s: applid=%d %s\n", __FUNCTION__,
1387 ap->applid, cdb->buf);
1388 cdebbuf_free(cdb);
1389 } else
1390 printk(KERN_DEBUG "%s: applid=%d %s not traced\n",
1391 __FUNCTION__, ap->applid,
1392 capi_cmd2str(s_cmsg.Command, s_cmsg.Subcommand));
1393 }
1378 if (s_cmsg.Command == CAPI_DATA_B3 1394 if (s_cmsg.Command == CAPI_DATA_B3
1379 && s_cmsg.Subcommand == CAPI_IND) { 1395 && s_cmsg.Subcommand == CAPI_IND) {
1380 handle_data(&s_cmsg, skb); 1396 handle_data(&s_cmsg, skb);
diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c
index c1b21552fc03..ad1e2702c2d1 100644
--- a/drivers/isdn/capi/capiutil.c
+++ b/drivers/isdn/capi/capiutil.c
@@ -648,6 +648,9 @@ char *capi_cmd2str(u8 cmd, u8 subcmd)
648 648
649 649
650/*-------------------------------------------------------*/ 650/*-------------------------------------------------------*/
651
652#ifdef CONFIG_CAPI_TRACE
653
651/*-------------------------------------------------------*/ 654/*-------------------------------------------------------*/
652 655
653static char *pnames[] = 656static char *pnames[] =
@@ -703,44 +706,77 @@ static char *pnames[] =
703}; 706};
704 707
705 708
706static char buf[8192];
707static char *p = NULL;
708 709
709#include <stdarg.h> 710#include <stdarg.h>
710 711
711/*-------------------------------------------------------*/ 712/*-------------------------------------------------------*/
712static void bufprint(char *fmt,...) 713static _cdebbuf *bufprint(_cdebbuf *cdb, char *fmt,...)
713{ 714{
714 va_list f; 715 va_list f;
716 size_t n,r;
717
718 if (!cdb)
719 return NULL;
715 va_start(f, fmt); 720 va_start(f, fmt);
716 vsprintf(p, fmt, f); 721 r = cdb->size - cdb->pos;
722 n = vsnprintf(cdb->p, r, fmt, f);
717 va_end(f); 723 va_end(f);
718 p += strlen(p); 724 if (n >= r) {
725 /* truncated, need bigger buffer */
726 size_t ns = 2 * cdb->size;
727 u_char *nb;
728
729 while ((ns - cdb->pos) <= n)
730 ns *= 2;
731 nb = kmalloc(ns, GFP_ATOMIC);
732 if (!nb) {
733 cdebbuf_free(cdb);
734 return NULL;
735 }
736 memcpy(nb, cdb->buf, cdb->pos);
737 kfree(cdb->buf);
738 nb[cdb->pos] = 0;
739 cdb->buf = nb;
740 cdb->p = cdb->buf + cdb->pos;
741 cdb->size = ns;
742 va_start(f, fmt);
743 r = cdb->size - cdb->pos;
744 n = vsnprintf(cdb->p, r, fmt, f);
745 va_end(f);
746 }
747 cdb->p += n;
748 cdb->pos += n;
749 return cdb;
719} 750}
720 751
721static void printstructlen(u8 * m, unsigned len) 752static _cdebbuf *printstructlen(_cdebbuf *cdb, u8 * m, unsigned len)
722{ 753{
723 unsigned hex = 0; 754 unsigned hex = 0;
755
756 if (!cdb)
757 return NULL;
724 for (; len; len--, m++) 758 for (; len; len--, m++)
725 if (isalnum(*m) || *m == ' ') { 759 if (isalnum(*m) || *m == ' ') {
726 if (hex) 760 if (hex)
727 bufprint(">"); 761 cdb = bufprint(cdb, ">");
728 bufprint("%c", *m); 762 cdb = bufprint(cdb, "%c", *m);
729 hex = 0; 763 hex = 0;
730 } else { 764 } else {
731 if (!hex) 765 if (!hex)
732 bufprint("<%02x", *m); 766 cdb = bufprint(cdb, "<%02x", *m);
733 else 767 else
734 bufprint(" %02x", *m); 768 cdb = bufprint(cdb, " %02x", *m);
735 hex = 1; 769 hex = 1;
736 } 770 }
737 if (hex) 771 if (hex)
738 bufprint(">"); 772 cdb = bufprint(cdb, ">");
773 return cdb;
739} 774}
740 775
741static void printstruct(u8 * m) 776static _cdebbuf *printstruct(_cdebbuf *cdb, u8 * m)
742{ 777{
743 unsigned len; 778 unsigned len;
779
744 if (m[0] != 0xff) { 780 if (m[0] != 0xff) {
745 len = m[0]; 781 len = m[0];
746 m += 1; 782 m += 1;
@@ -748,42 +784,45 @@ static void printstruct(u8 * m)
748 len = ((u16 *) (m + 1))[0]; 784 len = ((u16 *) (m + 1))[0];
749 m += 3; 785 m += 3;
750 } 786 }
751 printstructlen(m, len); 787 cdb = printstructlen(cdb, m, len);
788 return cdb;
752} 789}
753 790
754/*-------------------------------------------------------*/ 791/*-------------------------------------------------------*/
755#define NAME (pnames[cmsg->par[cmsg->p]]) 792#define NAME (pnames[cmsg->par[cmsg->p]])
756 793
757static void protocol_message_2_pars(_cmsg * cmsg, int level) 794static _cdebbuf *protocol_message_2_pars(_cdebbuf *cdb, _cmsg *cmsg, int level)
758{ 795{
759 for (; TYP != _CEND; cmsg->p++) { 796 for (; TYP != _CEND; cmsg->p++) {
760 int slen = 29 + 3 - level; 797 int slen = 29 + 3 - level;
761 int i; 798 int i;
762 799
763 bufprint(" "); 800 if (!cdb)
801 return NULL;
802 cdb = bufprint(cdb, " ");
764 for (i = 0; i < level - 1; i++) 803 for (i = 0; i < level - 1; i++)
765 bufprint(" "); 804 cdb = bufprint(cdb, " ");
766 805
767 switch (TYP) { 806 switch (TYP) {
768 case _CBYTE: 807 case _CBYTE:
769 bufprint("%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l)); 808 cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l));
770 cmsg->l++; 809 cmsg->l++;
771 break; 810 break;
772 case _CWORD: 811 case _CWORD:
773 bufprint("%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l)); 812 cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l));
774 cmsg->l += 2; 813 cmsg->l += 2;
775 break; 814 break;
776 case _CDWORD: 815 case _CDWORD:
777 bufprint("%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l)); 816 cdb = bufprint(cdb, "%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l));
778 cmsg->l += 4; 817 cmsg->l += 4;
779 break; 818 break;
780 case _CSTRUCT: 819 case _CSTRUCT:
781 bufprint("%-*s = ", slen, NAME); 820 cdb = bufprint(cdb, "%-*s = ", slen, NAME);
782 if (cmsg->m[cmsg->l] == '\0') 821 if (cmsg->m[cmsg->l] == '\0')
783 bufprint("default"); 822 cdb = bufprint(cdb, "default");
784 else 823 else
785 printstruct(cmsg->m + cmsg->l); 824 cdb = printstruct(cdb, cmsg->m + cmsg->l);
786 bufprint("\n"); 825 cdb = bufprint(cdb, "\n");
787 if (cmsg->m[cmsg->l] != 0xff) 826 if (cmsg->m[cmsg->l] != 0xff)
788 cmsg->l += 1 + cmsg->m[cmsg->l]; 827 cmsg->l += 1 + cmsg->m[cmsg->l];
789 else 828 else
@@ -794,61 +833,184 @@ static void protocol_message_2_pars(_cmsg * cmsg, int level)
794 case _CMSTRUCT: 833 case _CMSTRUCT:
795/*----- Metastruktur 0 -----*/ 834/*----- Metastruktur 0 -----*/
796 if (cmsg->m[cmsg->l] == '\0') { 835 if (cmsg->m[cmsg->l] == '\0') {
797 bufprint("%-*s = default\n", slen, NAME); 836 cdb = bufprint(cdb, "%-*s = default\n", slen, NAME);
798 cmsg->l++; 837 cmsg->l++;
799 jumpcstruct(cmsg); 838 jumpcstruct(cmsg);
800 } else { 839 } else {
801 char *name = NAME; 840 char *name = NAME;
802 unsigned _l = cmsg->l; 841 unsigned _l = cmsg->l;
803 bufprint("%-*s\n", slen, name); 842 cdb = bufprint(cdb, "%-*s\n", slen, name);
804 cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1; 843 cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1;
805 cmsg->p++; 844 cmsg->p++;
806 protocol_message_2_pars(cmsg, level + 1); 845 cdb = protocol_message_2_pars(cdb, cmsg, level + 1);
807 } 846 }
808 break; 847 break;
809 } 848 }
810 } 849 }
850 return cdb;
811} 851}
812/*-------------------------------------------------------*/ 852/*-------------------------------------------------------*/
813char *capi_message2str(u8 * msg) 853
854static _cdebbuf *g_debbuf;
855static u_long g_debbuf_lock;
856static _cmsg *g_cmsg;
857
858_cdebbuf *cdebbuf_alloc(void)
814{ 859{
860 _cdebbuf *cdb;
861
862 if (likely(!test_and_set_bit(1, &g_debbuf_lock))) {
863 cdb = g_debbuf;
864 goto init;
865 } else
866 cdb = kmalloc(sizeof(_cdebbuf), GFP_ATOMIC);
867 if (!cdb)
868 return NULL;
869 cdb->buf = kmalloc(CDEBUG_SIZE, GFP_ATOMIC);
870 if (!cdb->buf) {
871 kfree(cdb);
872 return NULL;
873 }
874 cdb->size = CDEBUG_SIZE;
875init:
876 cdb->buf[0] = 0;
877 cdb->p = cdb->buf;
878 cdb->pos = 0;
879 return cdb;
880}
815 881
816 _cmsg cmsg; 882void cdebbuf_free(_cdebbuf *cdb)
817 p = buf; 883{
818 p[0] = 0; 884 if (likely(cdb == g_debbuf)) {
885 test_and_clear_bit(1, &g_debbuf_lock);
886 return;
887 }
888 if (likely(cdb))
889 kfree(cdb->buf);
890 kfree(cdb);
891}
819 892
820 cmsg.m = msg;
821 cmsg.l = 8;
822 cmsg.p = 0;
823 byteTRcpy(cmsg.m + 4, &cmsg.Command);
824 byteTRcpy(cmsg.m + 5, &cmsg.Subcommand);
825 cmsg.par = cpars[command_2_index(cmsg.Command, cmsg.Subcommand)];
826 893
827 bufprint("%-26s ID=%03d #0x%04x LEN=%04d\n", 894_cdebbuf *capi_message2str(u8 * msg)
828 mnames[command_2_index(cmsg.Command, cmsg.Subcommand)], 895{
896 _cdebbuf *cdb;
897 _cmsg *cmsg;
898
899 cdb = cdebbuf_alloc();
900 if (unlikely(!cdb))
901 return NULL;
902 if (likely(cdb == g_debbuf))
903 cmsg = g_cmsg;
904 else
905 cmsg = kmalloc(sizeof(_cmsg), GFP_ATOMIC);
906 if (unlikely(!cmsg)) {
907 cdebbuf_free(cdb);
908 return NULL;
909 }
910 cmsg->m = msg;
911 cmsg->l = 8;
912 cmsg->p = 0;
913 byteTRcpy(cmsg->m + 4, &cmsg->Command);
914 byteTRcpy(cmsg->m + 5, &cmsg->Subcommand);
915 cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)];
916
917 cdb = bufprint(cdb, "%-26s ID=%03d #0x%04x LEN=%04d\n",
918 mnames[command_2_index(cmsg->Command, cmsg->Subcommand)],
829 ((unsigned short *) msg)[1], 919 ((unsigned short *) msg)[1],
830 ((unsigned short *) msg)[3], 920 ((unsigned short *) msg)[3],
831 ((unsigned short *) msg)[0]); 921 ((unsigned short *) msg)[0]);
832 922
833 protocol_message_2_pars(&cmsg, 1); 923 cdb = protocol_message_2_pars(cdb, cmsg, 1);
834 return buf; 924 if (unlikely(cmsg != g_cmsg))
925 kfree(cmsg);
926 return cdb;
835} 927}
836 928
837char *capi_cmsg2str(_cmsg * cmsg) 929_cdebbuf *capi_cmsg2str(_cmsg * cmsg)
838{ 930{
839 p = buf; 931 _cdebbuf *cdb;
840 p[0] = 0; 932
933 cdb = cdebbuf_alloc();
934 if (!cdb)
935 return NULL;
841 cmsg->l = 8; 936 cmsg->l = 8;
842 cmsg->p = 0; 937 cmsg->p = 0;
843 bufprint("%s ID=%03d #0x%04x LEN=%04d\n", 938 cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n",
844 mnames[command_2_index(cmsg->Command, cmsg->Subcommand)], 939 mnames[command_2_index(cmsg->Command, cmsg->Subcommand)],
845 ((u16 *) cmsg->m)[1], 940 ((u16 *) cmsg->m)[1],
846 ((u16 *) cmsg->m)[3], 941 ((u16 *) cmsg->m)[3],
847 ((u16 *) cmsg->m)[0]); 942 ((u16 *) cmsg->m)[0]);
848 protocol_message_2_pars(cmsg, 1); 943 cdb = protocol_message_2_pars(cdb, cmsg, 1);
849 return buf; 944 return cdb;
850} 945}
851 946
947int __init cdebug_init(void)
948{
949 g_cmsg= kmalloc(sizeof(_cmsg), GFP_KERNEL);
950 if (!g_cmsg)
951 return ENOMEM;
952 g_debbuf = kmalloc(sizeof(_cdebbuf), GFP_KERNEL);
953 if (!g_debbuf) {
954 kfree(g_cmsg);
955 return ENOMEM;
956 }
957 g_debbuf->buf = kmalloc(CDEBUG_GSIZE, GFP_KERNEL);
958 if (!g_debbuf->buf) {
959 kfree(g_cmsg);
960 kfree(g_debbuf);
961 return ENOMEM;;
962 }
963 g_debbuf->size = CDEBUG_GSIZE;
964 g_debbuf->buf[0] = 0;
965 g_debbuf->p = g_debbuf->buf;
966 g_debbuf->pos = 0;
967 return 0;
968}
969
970void __exit cdebug_exit(void)
971{
972 if (g_debbuf)
973 kfree(g_debbuf->buf);
974 kfree(g_debbuf);
975 kfree(g_cmsg);
976}
977
978#else /* !CONFIG_CAPI_TRACE */
979
980static _cdebbuf g_debbuf = {"CONFIG_CAPI_TRACE not enabled", NULL, 0, 0};
981
982_cdebbuf *capi_message2str(u8 * msg)
983{
984 return &g_debbuf;
985}
986
987_cdebbuf *capi_cmsg2str(_cmsg * cmsg)
988{
989 return &g_debbuf;
990}
991
992_cdebbuf *cdebbuf_alloc(void)
993{
994 return &g_debbuf;
995}
996
997void cdebbuf_free(_cdebbuf *cdb)
998{
999}
1000
1001int __init cdebug_init(void)
1002{
1003 return 0;
1004}
1005
1006void __exit cdebug_exit(void)
1007{
1008}
1009
1010#endif
1011
1012EXPORT_SYMBOL(cdebbuf_alloc);
1013EXPORT_SYMBOL(cdebbuf_free);
852EXPORT_SYMBOL(capi_cmsg2message); 1014EXPORT_SYMBOL(capi_cmsg2message);
853EXPORT_SYMBOL(capi_message2cmsg); 1015EXPORT_SYMBOL(capi_message2cmsg);
854EXPORT_SYMBOL(capi_cmsg_header); 1016EXPORT_SYMBOL(capi_cmsg_header);
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index 783a25526315..3ed34f7a1c4f 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -276,10 +276,17 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s
276 int showctl = 0; 276 int showctl = 0;
277 u8 cmd, subcmd; 277 u8 cmd, subcmd;
278 unsigned long flags; 278 unsigned long flags;
279 _cdebbuf *cdb;
279 280
280 if (card->cardstate != CARD_RUNNING) { 281 if (card->cardstate != CARD_RUNNING) {
281 printk(KERN_INFO "kcapi: controller %d not active, got: %s", 282 cdb = capi_message2str(skb->data);
282 card->cnr, capi_message2str(skb->data)); 283 if (cdb) {
284 printk(KERN_INFO "kcapi: controller [%03d] not active, got: %s",
285 card->cnr, cdb->buf);
286 cdebbuf_free(cdb);
287 } else
288 printk(KERN_INFO "kcapi: controller [%03d] not active, cannot trace\n",
289 card->cnr);
283 goto error; 290 goto error;
284 } 291 }
285 292
@@ -295,15 +302,21 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s
295 showctl |= (card->traceflag & 1); 302 showctl |= (card->traceflag & 1);
296 if (showctl & 2) { 303 if (showctl & 2) {
297 if (showctl & 1) { 304 if (showctl & 1) {
298 printk(KERN_DEBUG "kcapi: got [0x%lx] id#%d %s len=%u\n", 305 printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u\n",
299 (unsigned long) card->cnr, 306 card->cnr, CAPIMSG_APPID(skb->data),
300 CAPIMSG_APPID(skb->data),
301 capi_cmd2str(cmd, subcmd), 307 capi_cmd2str(cmd, subcmd),
302 CAPIMSG_LEN(skb->data)); 308 CAPIMSG_LEN(skb->data));
303 } else { 309 } else {
304 printk(KERN_DEBUG "kcapi: got [0x%lx] %s\n", 310 cdb = capi_message2str(skb->data);
305 (unsigned long) card->cnr, 311 if (cdb) {
306 capi_message2str(skb->data)); 312 printk(KERN_DEBUG "kcapi: got [%03d] %s\n",
313 card->cnr, cdb->buf);
314 cdebbuf_free(cdb);
315 } else
316 printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u, cannot trace\n",
317 card->cnr, CAPIMSG_APPID(skb->data),
318 capi_cmd2str(cmd, subcmd),
319 CAPIMSG_LEN(skb->data));
307 } 320 }
308 321
309 } 322 }
@@ -312,8 +325,15 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s
312 ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data)); 325 ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data));
313 if ((!ap) || (ap->release_in_progress)) { 326 if ((!ap) || (ap->release_in_progress)) {
314 read_unlock_irqrestore(&application_lock, flags); 327 read_unlock_irqrestore(&application_lock, flags);
315 printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n", 328 cdb = capi_message2str(skb->data);
316 CAPIMSG_APPID(skb->data), capi_message2str(skb->data)); 329 if (cdb) {
330 printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n",
331 CAPIMSG_APPID(skb->data), cdb->buf);
332 cdebbuf_free(cdb);
333 } else
334 printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s) cannot trace\n",
335 CAPIMSG_APPID(skb->data),
336 capi_cmd2str(cmd, subcmd));
317 goto error; 337 goto error;
318 } 338 }
319 skb_queue_tail(&ap->recv_queue, skb); 339 skb_queue_tail(&ap->recv_queue, skb);
@@ -332,7 +352,7 @@ void capi_ctr_ready(struct capi_ctr * card)
332{ 352{
333 card->cardstate = CARD_RUNNING; 353 card->cardstate = CARD_RUNNING;
334 354
335 printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n", 355 printk(KERN_NOTICE "kcapi: card [%03d] \"%s\" ready.\n",
336 card->cnr, card->name); 356 card->cnr, card->name);
337 357
338 notify_push(KCI_CONTRUP, card->cnr, 0, 0); 358 notify_push(KCI_CONTRUP, card->cnr, 0, 0);
@@ -364,7 +384,7 @@ void capi_ctr_reseted(struct capi_ctr * card)
364 capi_ctr_put(card); 384 capi_ctr_put(card);
365 } 385 }
366 386
367 printk(KERN_NOTICE "kcapi: card %d down.\n", card->cnr); 387 printk(KERN_NOTICE "kcapi: card [%03d] down.\n", card->cnr);
368 388
369 notify_push(KCI_CONTRDOWN, card->cnr, 0, 0); 389 notify_push(KCI_CONTRDOWN, card->cnr, 0, 0);
370} 390}
@@ -374,7 +394,7 @@ EXPORT_SYMBOL(capi_ctr_reseted);
374void capi_ctr_suspend_output(struct capi_ctr *card) 394void capi_ctr_suspend_output(struct capi_ctr *card)
375{ 395{
376 if (!card->blocked) { 396 if (!card->blocked) {
377 printk(KERN_DEBUG "kcapi: card %d suspend\n", card->cnr); 397 printk(KERN_DEBUG "kcapi: card [%03d] suspend\n", card->cnr);
378 card->blocked = 1; 398 card->blocked = 1;
379 } 399 }
380} 400}
@@ -384,7 +404,7 @@ EXPORT_SYMBOL(capi_ctr_suspend_output);
384void capi_ctr_resume_output(struct capi_ctr *card) 404void capi_ctr_resume_output(struct capi_ctr *card)
385{ 405{
386 if (card->blocked) { 406 if (card->blocked) {
387 printk(KERN_DEBUG "kcapi: card %d resume\n", card->cnr); 407 printk(KERN_DEBUG "kcapi: card [%03d] resume\n", card->cnr);
388 card->blocked = 0; 408 card->blocked = 0;
389 } 409 }
390} 410}
@@ -432,7 +452,7 @@ attach_capi_ctr(struct capi_ctr *card)
432 } 452 }
433 453
434 ncards++; 454 ncards++;
435 printk(KERN_NOTICE "kcapi: Controller %d: %s attached\n", 455 printk(KERN_NOTICE "kcapi: Controller [%03d]: %s attached\n",
436 card->cnr, card->name); 456 card->cnr, card->name);
437 return 0; 457 return 0;
438} 458}
@@ -451,7 +471,7 @@ int detach_capi_ctr(struct capi_ctr *card)
451 card->procent = NULL; 471 card->procent = NULL;
452 } 472 }
453 capi_cards[card->cnr - 1] = NULL; 473 capi_cards[card->cnr - 1] = NULL;
454 printk(KERN_NOTICE "kcapi: Controller %d: %s unregistered\n", 474 printk(KERN_NOTICE "kcapi: Controller [%03d]: %s unregistered\n",
455 card->cnr, card->name); 475 card->cnr, card->name);
456 476
457 return 0; 477 return 0;
@@ -623,17 +643,25 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb)
623 showctl |= (card->traceflag & 1); 643 showctl |= (card->traceflag & 1);
624 if (showctl & 2) { 644 if (showctl & 2) {
625 if (showctl & 1) { 645 if (showctl & 1) {
626 printk(KERN_DEBUG "kcapi: put [%#x] id#%d %s len=%u\n", 646 printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u\n",
627 CAPIMSG_CONTROLLER(skb->data), 647 CAPIMSG_CONTROLLER(skb->data),
628 CAPIMSG_APPID(skb->data), 648 CAPIMSG_APPID(skb->data),
629 capi_cmd2str(cmd, subcmd), 649 capi_cmd2str(cmd, subcmd),
630 CAPIMSG_LEN(skb->data)); 650 CAPIMSG_LEN(skb->data));
631 } else { 651 } else {
632 printk(KERN_DEBUG "kcapi: put [%#x] %s\n", 652 _cdebbuf *cdb = capi_message2str(skb->data);
633 CAPIMSG_CONTROLLER(skb->data), 653 if (cdb) {
634 capi_message2str(skb->data)); 654 printk(KERN_DEBUG "kcapi: put [%03d] %s\n",
655 CAPIMSG_CONTROLLER(skb->data),
656 cdb->buf);
657 cdebbuf_free(cdb);
658 } else
659 printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u cannot trace\n",
660 CAPIMSG_CONTROLLER(skb->data),
661 CAPIMSG_APPID(skb->data),
662 capi_cmd2str(cmd, subcmd),
663 CAPIMSG_LEN(skb->data));
635 } 664 }
636
637 } 665 }
638 return card->send_message(card, skb); 666 return card->send_message(card, skb);
639} 667}
@@ -894,7 +922,7 @@ int capi20_manufacturer(unsigned int cmd, void __user *data)
894 return -ESRCH; 922 return -ESRCH;
895 923
896 card->traceflag = fdef.flag; 924 card->traceflag = fdef.flag;
897 printk(KERN_INFO "kcapi: contr %d set trace=%d\n", 925 printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n",
898 card->cnr, card->traceflag); 926 card->cnr, card->traceflag);
899 return 0; 927 return 0;
900 } 928 }
@@ -967,7 +995,11 @@ static int __init kcapi_init(void)
967{ 995{
968 char *p; 996 char *p;
969 char rev[32]; 997 char rev[32];
998 int ret;
970 999
1000 ret = cdebug_init();
1001 if (ret)
1002 return ret;
971 kcapi_proc_init(); 1003 kcapi_proc_init();
972 1004
973 if ((p = strchr(revision, ':')) != 0 && p[1]) { 1005 if ((p = strchr(revision, ':')) != 0 && p[1]) {
@@ -988,6 +1020,7 @@ static void __exit kcapi_exit(void)
988 1020
989 /* make sure all notifiers are finished */ 1021 /* make sure all notifiers are finished */
990 flush_scheduled_work(); 1022 flush_scheduled_work();
1023 cdebug_exit();
991} 1024}
992 1025
993module_init(kcapi_init); 1026module_init(kcapi_init);
diff --git a/include/linux/isdn/capiutil.h b/include/linux/isdn/capiutil.h
index 2e79f816703b..63bd9cf821a7 100644
--- a/include/linux/isdn/capiutil.h
+++ b/include/linux/isdn/capiutil.h
@@ -174,9 +174,26 @@ char *capi_info2str(__u16 reason);
174/* 174/*
175 * Debugging / Tracing functions 175 * Debugging / Tracing functions
176 */ 176 */
177
177char *capi_cmd2str(__u8 cmd, __u8 subcmd); 178char *capi_cmd2str(__u8 cmd, __u8 subcmd);
178char *capi_cmsg2str(_cmsg * cmsg); 179
179char *capi_message2str(__u8 * msg); 180typedef struct {
181 u_char *buf;
182 u_char *p;
183 size_t size;
184 size_t pos;
185} _cdebbuf;
186
187#define CDEBUG_SIZE 1024
188#define CDEBUG_GSIZE 4096
189
190_cdebbuf *cdebbuf_alloc(void);
191void cdebbuf_free(_cdebbuf *cdb);
192int cdebug_init(void);
193void cdebug_exit(void);
194
195_cdebbuf *capi_cmsg2str(_cmsg *cmsg);
196_cdebbuf *capi_message2str(__u8 *msg);
180 197
181/*-----------------------------------------------------------------------*/ 198/*-----------------------------------------------------------------------*/
182 199